nsxfobj.c revision 85756
1/*******************************************************************************
2 *
3 * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
4 *                         ACPI Object oriented interfaces
5 *              $Revision: 95 $
6 *
7 ******************************************************************************/
8
9/******************************************************************************
10 *
11 * 1. Copyright Notice
12 *
13 * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
14 * All rights reserved.
15 *
16 * 2. License
17 *
18 * 2.1. This is your license from Intel Corp. under its intellectual property
19 * rights.  You may have additional license terms from the party that provided
20 * you this software, covering your right to use that party's intellectual
21 * property rights.
22 *
23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24 * copy of the source code appearing in this file ("Covered Code") an
25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26 * base code distributed originally by Intel ("Original Intel Code") to copy,
27 * make derivatives, distribute, use and display any portion of the Covered
28 * Code in any form, with the right to sublicense such rights; and
29 *
30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31 * license (with the right to sublicense), under only those claims of Intel
32 * patents that are infringed by the Original Intel Code, to make, use, sell,
33 * offer to sell, and import the Covered Code and derivative works thereof
34 * solely to the minimum extent necessary to exercise the above copyright
35 * license, and in no event shall the patent license extend to any additions
36 * to or modifications of the Original Intel Code.  No other license or right
37 * is granted directly or by implication, estoppel or otherwise;
38 *
39 * The above copyright and patent license is granted only if the following
40 * conditions are met:
41 *
42 * 3. Conditions
43 *
44 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45 * Redistribution of source code of any substantial portion of the Covered
46 * Code or modification with rights to further distribute source must include
47 * the above Copyright Notice, the above License, this list of Conditions,
48 * and the following Disclaimer and Export Compliance provision.  In addition,
49 * Licensee must cause all Covered Code to which Licensee contributes to
50 * contain a file documenting the changes Licensee made to create that Covered
51 * Code and the date of any change.  Licensee must include in that file the
52 * documentation of any changes made by any predecessor Licensee.  Licensee
53 * must include a prominent statement that the modification is derived,
54 * directly or indirectly, from Original Intel Code.
55 *
56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57 * Redistribution of source code of any substantial portion of the Covered
58 * Code or modification without rights to further distribute source must
59 * include the following Disclaimer and Export Compliance provision in the
60 * documentation and/or other materials provided with distribution.  In
61 * addition, Licensee may not authorize further sublicense of source of any
62 * portion of the Covered Code, and must include terms to the effect that the
63 * license from Licensee to its licensee is limited to the intellectual
64 * property embodied in the software Licensee provides to its licensee, and
65 * not to intellectual property embodied in modifications its licensee may
66 * make.
67 *
68 * 3.3. Redistribution of Executable. Redistribution in executable form of any
69 * substantial portion of the Covered Code or modification must reproduce the
70 * above Copyright Notice, and the following Disclaimer and Export Compliance
71 * provision in the documentation and/or other materials provided with the
72 * distribution.
73 *
74 * 3.4. Intel retains all right, title, and interest in and to the Original
75 * Intel Code.
76 *
77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78 * Intel shall be used in advertising or otherwise to promote the sale, use or
79 * other dealings in products derived from or relating to the Covered Code
80 * without prior written authorization from Intel.
81 *
82 * 4. Disclaimer and Export Compliance
83 *
84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90 * PARTICULAR PURPOSE.
91 *
92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99 * LIMITED REMEDY.
100 *
101 * 4.3. Licensee shall not export, either directly or indirectly, any of this
102 * software or system incorporating such software without first obtaining any
103 * required license or other approval from the U. S. Department of Commerce or
104 * any other agency or department of the United States Government.  In the
105 * event Licensee exports any such software from the United States or
106 * re-exports any such software from a foreign destination, Licensee shall
107 * ensure that the distribution and export/re-export of the software is in
108 * compliance with all laws, regulations, orders, or other restrictions of the
109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110 * any of its subsidiaries will export/re-export any technical data, process,
111 * software, or service, directly or indirectly, to any country for which the
112 * United States government or any agency thereof requires an export license,
113 * other governmental approval, or letter of assurance, without first obtaining
114 * such license, approval or letter.
115 *
116 *****************************************************************************/
117
118
119#define __NSXFOBJ_C__
120
121#include "acpi.h"
122#include "acinterp.h"
123#include "acnamesp.h"
124#include "acdispat.h"
125
126
127#define _COMPONENT          ACPI_NAMESPACE
128        MODULE_NAME         ("nsxfobj")
129
130
131/*******************************************************************************
132 *
133 * FUNCTION:    AcpiEvaluateObject
134 *
135 * PARAMETERS:  Handle              - Object handle (optional)
136 *              *Pathname           - Object pathname (optional)
137 *              **ExternalParams    - List of parameters to pass to method,
138 *                                    terminated by NULL.  May be NULL
139 *                                    if no parameters are being passed.
140 *              *ReturnBuffer       - Where to put method's return value (if
141 *                                    any).  If NULL, no value is returned.
142 *
143 * RETURN:      Status
144 *
145 * DESCRIPTION: Find and evaluate the given object, passing the given
146 *              parameters if necessary.  One of "Handle" or "Pathname" must
147 *              be valid (non-null)
148 *
149 ******************************************************************************/
150
151ACPI_STATUS
152AcpiEvaluateObject (
153    ACPI_HANDLE             Handle,
154    ACPI_STRING             Pathname,
155    ACPI_OBJECT_LIST        *ExternalParams,
156    ACPI_BUFFER             *ReturnBuffer)
157{
158    ACPI_STATUS             Status;
159    ACPI_OPERAND_OBJECT     **InternalParams = NULL;
160    ACPI_OPERAND_OBJECT     *InternalReturnObj = NULL;
161    UINT32                  BufferSpaceNeeded;
162    UINT32                  UserBufferLength;
163    UINT32                  i;
164
165
166    FUNCTION_TRACE ("AcpiEvaluateObject");
167
168
169    /*
170     * If there are parameters to be passed to the object
171     * (which must be a control method), the external objects
172     * must be converted to internal objects
173     */
174    if (ExternalParams && ExternalParams->Count)
175    {
176        /*
177         * Allocate a new parameter block for the internal objects
178         * Add 1 to count to allow for null terminated internal list
179         */
180        InternalParams = ACPI_MEM_CALLOCATE ((ExternalParams->Count + 1) * sizeof (void *));
181        if (!InternalParams)
182        {
183            return_ACPI_STATUS (AE_NO_MEMORY);
184        }
185
186
187        /*
188         * Convert each external object in the list to an
189         * internal object
190         */
191        for (i = 0; i < ExternalParams->Count; i++)
192        {
193            Status = AcpiUtCopyEobjectToIobject (&ExternalParams->Pointer[i],
194                                                &InternalParams[i]);
195
196            if (ACPI_FAILURE (Status))
197            {
198                AcpiUtDeleteInternalObjectList (InternalParams);
199                return_ACPI_STATUS (Status);
200            }
201        }
202        InternalParams[ExternalParams->Count] = NULL;
203    }
204
205
206    /*
207     * Three major cases:
208     * 1) Fully qualified pathname
209     * 2) No handle, not fully qualified pathname (error)
210     * 3) Valid handle
211     */
212    if ((Pathname) &&
213        (AcpiNsValidRootPrefix (Pathname[0])))
214    {
215        /*
216         *  The path is fully qualified, just evaluate by name
217         */
218        Status = AcpiNsEvaluateByName (Pathname, InternalParams, &InternalReturnObj);
219    }
220
221    else if (!Handle)
222    {
223        /*
224         * A handle is optional iff a fully qualified pathname
225         * is specified.  Since we've already handled fully
226         * qualified names above, this is an error
227         */
228        if (!Pathname)
229        {
230            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Both Handle and Pathname are NULL\n"));
231        }
232
233        else
234        {
235            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Handle is NULL and Pathname is relative\n"));
236        }
237
238        Status = AE_BAD_PARAMETER;
239    }
240
241    else
242    {
243        /*
244         * We get here if we have a handle -- and if we have a
245         * pathname it is relative.  The handle will be validated
246         * in the lower procedures
247         */
248        if (!Pathname)
249        {
250            /*
251             * The null pathname case means the handle is for
252             * the actual object to be evaluated
253             */
254            Status = AcpiNsEvaluateByHandle (Handle, InternalParams, &InternalReturnObj);
255        }
256
257        else
258        {
259           /*
260            * Both a Handle and a relative Pathname
261            */
262            Status = AcpiNsEvaluateRelative (Handle, Pathname, InternalParams,
263                                                &InternalReturnObj);
264        }
265    }
266
267
268    /*
269     * If we are expecting a return value, and all went well above,
270     * copy the return value to an external object.
271     */
272
273    if (ReturnBuffer)
274    {
275        UserBufferLength = ReturnBuffer->Length;
276        ReturnBuffer->Length = 0;
277
278        if (InternalReturnObj)
279        {
280            if (VALID_DESCRIPTOR_TYPE (InternalReturnObj, ACPI_DESC_TYPE_NAMED))
281            {
282                /*
283                 * If we got an Node as a return object,
284                 * this means the object we are evaluating
285                 * has nothing interesting to return (such
286                 * as a mutex, etc.)  We return an error
287                 * because these types are essentially
288                 * unsupported by this interface.  We
289                 * don't check up front because this makes
290                 * it easier to add support for various
291                 * types at a later date if necessary.
292                 */
293                Status = AE_TYPE;
294                InternalReturnObj = NULL;   /* No need to delete an Node */
295            }
296
297            if (ACPI_SUCCESS (Status))
298            {
299                /*
300                 * Find out how large a buffer is needed
301                 * to contain the returned object
302                 */
303                Status = AcpiUtGetObjectSize (InternalReturnObj,
304                                                &BufferSpaceNeeded);
305                if (ACPI_SUCCESS (Status))
306                {
307                    /*
308                     * Check if there is enough room in the
309                     * caller's buffer
310                     */
311                    if (UserBufferLength < BufferSpaceNeeded)
312                    {
313                        /*
314                         * Caller's buffer is too small, can't
315                         * give him partial results fail the call
316                         * but return the buffer size needed
317                         */
318                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
319                            "Needed buffer size %X, received %X\n",
320                            BufferSpaceNeeded, UserBufferLength));
321
322                        ReturnBuffer->Length = BufferSpaceNeeded;
323                        Status = AE_BUFFER_OVERFLOW;
324                    }
325
326                    else
327                    {
328                        /*
329                         *  We have enough space for the object, build it
330                         */
331                        Status = AcpiUtCopyIobjectToEobject (InternalReturnObj,
332                                        ReturnBuffer);
333                        ReturnBuffer->Length = BufferSpaceNeeded;
334                    }
335                }
336            }
337        }
338    }
339
340
341    /* Delete the return and parameter objects */
342
343    if (InternalReturnObj)
344    {
345        /*
346         * Delete the internal return object. (Or at least
347         * decrement the reference count by one)
348         */
349        AcpiUtRemoveReference (InternalReturnObj);
350    }
351
352    /*
353     * Free the input parameter list (if we created one),
354     */
355    if (InternalParams)
356    {
357        /* Free the allocated parameter block */
358
359        AcpiUtDeleteInternalObjectList (InternalParams);
360    }
361
362    return_ACPI_STATUS (Status);
363}
364
365
366/*******************************************************************************
367 *
368 * FUNCTION:    AcpiGetNextObject
369 *
370 * PARAMETERS:  Type            - Type of object to be searched for
371 *              Parent          - Parent object whose children we are getting
372 *              LastChild       - Previous child that was found.
373 *                                The NEXT child will be returned
374 *              RetHandle       - Where handle to the next object is placed
375 *
376 * RETURN:      Status
377 *
378 * DESCRIPTION: Return the next peer object within the namespace.  If Handle is
379 *              valid, Scope is ignored.  Otherwise, the first object within
380 *              Scope is returned.
381 *
382 ******************************************************************************/
383
384ACPI_STATUS
385AcpiGetNextObject (
386    ACPI_OBJECT_TYPE        Type,
387    ACPI_HANDLE             Parent,
388    ACPI_HANDLE             Child,
389    ACPI_HANDLE             *RetHandle)
390{
391    ACPI_STATUS             Status = AE_OK;
392    ACPI_NAMESPACE_NODE     *Node;
393    ACPI_NAMESPACE_NODE     *ParentNode = NULL;
394    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
395
396
397    /* Parameter validation */
398
399    if (Type > ACPI_TYPE_MAX)
400    {
401        return (AE_BAD_PARAMETER);
402    }
403
404    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
405
406    /* If null handle, use the parent */
407
408    if (!Child)
409    {
410        /* Start search at the beginning of the specified scope */
411
412        ParentNode = AcpiNsMapHandleToNode (Parent);
413        if (!ParentNode)
414        {
415            Status = AE_BAD_PARAMETER;
416            goto UnlockAndExit;
417        }
418    }
419
420    /* Non-null handle, ignore the parent */
421
422    else
423    {
424        /* Convert and validate the handle */
425
426        ChildNode = AcpiNsMapHandleToNode (Child);
427        if (!ChildNode)
428        {
429            Status = AE_BAD_PARAMETER;
430            goto UnlockAndExit;
431        }
432    }
433
434
435    /* Internal function does the real work */
436
437    Node = AcpiNsGetNextNode ((ACPI_OBJECT_TYPE8) Type,
438                                    ParentNode, ChildNode);
439    if (!Node)
440    {
441        Status = AE_NOT_FOUND;
442        goto UnlockAndExit;
443    }
444
445    if (RetHandle)
446    {
447        *RetHandle = AcpiNsConvertEntryToHandle (Node);
448    }
449
450
451UnlockAndExit:
452
453    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
454    return (Status);
455}
456
457
458/*******************************************************************************
459 *
460 * FUNCTION:    AcpiGetType
461 *
462 * PARAMETERS:  Handle          - Handle of object whose type is desired
463 *              *RetType        - Where the type will be placed
464 *
465 * RETURN:      Status
466 *
467 * DESCRIPTION: This routine returns the type associatd with a particular handle
468 *
469 ******************************************************************************/
470
471ACPI_STATUS
472AcpiGetType (
473    ACPI_HANDLE             Handle,
474    ACPI_OBJECT_TYPE        *RetType)
475{
476    ACPI_NAMESPACE_NODE     *Node;
477
478
479    /* Parameter Validation */
480
481    if (!RetType)
482    {
483        return (AE_BAD_PARAMETER);
484    }
485
486    /*
487     * Special case for the predefined Root Node
488     * (return type ANY)
489     */
490    if (Handle == ACPI_ROOT_OBJECT)
491    {
492        *RetType = ACPI_TYPE_ANY;
493        return (AE_OK);
494    }
495
496    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
497
498    /* Convert and validate the handle */
499
500    Node = AcpiNsMapHandleToNode (Handle);
501    if (!Node)
502    {
503        AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
504        return (AE_BAD_PARAMETER);
505    }
506
507    *RetType = Node->Type;
508
509
510    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
511    return (AE_OK);
512}
513
514
515/*******************************************************************************
516 *
517 * FUNCTION:    AcpiGetParent
518 *
519 * PARAMETERS:  Handle          - Handle of object whose parent is desired
520 *              RetHandle       - Where the parent handle will be placed
521 *
522 * RETURN:      Status
523 *
524 * DESCRIPTION: Returns a handle to the parent of the object represented by
525 *              Handle.
526 *
527 ******************************************************************************/
528
529ACPI_STATUS
530AcpiGetParent (
531    ACPI_HANDLE             Handle,
532    ACPI_HANDLE             *RetHandle)
533{
534    ACPI_NAMESPACE_NODE     *Node;
535    ACPI_STATUS             Status = AE_OK;
536
537
538    if (!RetHandle)
539    {
540        return (AE_BAD_PARAMETER);
541    }
542
543    /* Special case for the predefined Root Node (no parent) */
544
545    if (Handle == ACPI_ROOT_OBJECT)
546    {
547        return (AE_NULL_ENTRY);
548    }
549
550
551    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
552
553    /* Convert and validate the handle */
554
555    Node = AcpiNsMapHandleToNode (Handle);
556    if (!Node)
557    {
558        Status = AE_BAD_PARAMETER;
559        goto UnlockAndExit;
560    }
561
562
563    /* Get the parent entry */
564
565    *RetHandle =
566        AcpiNsConvertEntryToHandle (AcpiNsGetParentObject (Node));
567
568    /* Return exeption if parent is null */
569
570    if (!AcpiNsGetParentObject (Node))
571    {
572        Status = AE_NULL_ENTRY;
573    }
574
575
576UnlockAndExit:
577
578    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
579    return (Status);
580}
581
582
583/*******************************************************************************
584 *
585 * FUNCTION:    AcpiWalkNamespace
586 *
587 * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
588 *              StartObject         - Handle in namespace where search begins
589 *              MaxDepth            - Depth to which search is to reach
590 *              UserFunction        - Called when an object of "Type" is found
591 *              Context             - Passed to user function
592 *              ReturnValue         - Location where return value of
593 *                                    UserFunction is put if terminated early
594 *
595 * RETURNS      Return value from the UserFunction if terminated early.
596 *              Otherwise, returns NULL.
597 *
598 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
599 *              starting (and ending) at the object specified by StartHandle.
600 *              The UserFunction is called whenever an object that matches
601 *              the type parameter is found.  If the user function returns
602 *              a non-zero value, the search is terminated immediately and this
603 *              value is returned to the caller.
604 *
605 *              The point of this procedure is to provide a generic namespace
606 *              walk routine that can be called from multiple places to
607 *              provide multiple services;  the User Function can be tailored
608 *              to each task, whether it is a print function, a compare
609 *              function, etc.
610 *
611 ******************************************************************************/
612
613ACPI_STATUS
614AcpiWalkNamespace (
615    ACPI_OBJECT_TYPE        Type,
616    ACPI_HANDLE             StartObject,
617    UINT32                  MaxDepth,
618    ACPI_WALK_CALLBACK      UserFunction,
619    void                    *Context,
620    void                    **ReturnValue)
621{
622    ACPI_STATUS             Status;
623
624
625    FUNCTION_TRACE ("AcpiWalkNamespace");
626
627
628    /* Parameter validation */
629
630    if ((Type > ACPI_TYPE_MAX)  ||
631        (!MaxDepth)             ||
632        (!UserFunction))
633    {
634        return_ACPI_STATUS (AE_BAD_PARAMETER);
635    }
636
637    /*
638     * Lock the namespace around the walk.
639     * The namespace will be unlocked/locked around each call
640     * to the user function - since this function
641     * must be allowed to make Acpi calls itself.
642     */
643    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
644    Status = AcpiNsWalkNamespace ((ACPI_OBJECT_TYPE8) Type, StartObject,
645                    MaxDepth, NS_WALK_UNLOCK, UserFunction, Context,
646                    ReturnValue);
647
648    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
649
650    return_ACPI_STATUS (Status);
651}
652
653
654/*******************************************************************************
655 *
656 * FUNCTION:    AcpiNsGetDeviceCallback
657 *
658 * PARAMETERS:  Callback from AcpiGetDevice
659 *
660 * RETURN:      Status
661 *
662 * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
663 *              present devices, or if they specified a HID, it filters based
664 *              on that.
665 *
666 ******************************************************************************/
667
668static ACPI_STATUS
669AcpiNsGetDeviceCallback (
670    ACPI_HANDLE             ObjHandle,
671    UINT32                  NestingLevel,
672    void                    *Context,
673    void                    **ReturnValue)
674{
675    ACPI_STATUS             Status;
676    ACPI_NAMESPACE_NODE     *Node;
677    UINT32                  Flags;
678    ACPI_DEVICE_ID          DeviceId;
679    ACPI_GET_DEVICES_INFO   *Info;
680
681
682    Info = Context;
683
684    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
685    Node = AcpiNsMapHandleToNode (ObjHandle);
686    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
687
688    if (!Node)
689    {
690        return (AE_BAD_PARAMETER);
691    }
692
693    /*
694     * Run _STA to determine if device is present
695     */
696    Status = AcpiUtExecute_STA (Node, &Flags);
697    if (ACPI_FAILURE (Status))
698    {
699        return (AE_CTRL_DEPTH);
700    }
701
702    if (!(Flags & 0x01))
703    {
704        /* don't return at the device or children of the device if not there */
705        return (AE_CTRL_DEPTH);
706    }
707
708    /*
709     * Filter based on device HID
710     */
711    if (Info->Hid != NULL)
712    {
713        Status = AcpiUtExecute_HID (Node, &DeviceId);
714        if (Status == AE_NOT_FOUND)
715        {
716            return (AE_OK);
717        }
718
719        else if (ACPI_FAILURE (Status))
720        {
721            return (AE_CTRL_DEPTH);
722        }
723
724        if (STRNCMP (DeviceId.Buffer, Info->Hid, sizeof (DeviceId.Buffer)) != 0)
725        {
726            return (AE_OK);
727        }
728    }
729
730    Info->UserFunction (ObjHandle, NestingLevel, Info->Context, ReturnValue);
731    return (AE_OK);
732}
733
734
735/*******************************************************************************
736 *
737 * FUNCTION:    AcpiGetDevices
738 *
739 * PARAMETERS:  HID                 - HID to search for. Can be NULL.
740 *              UserFunction        - Called when a matching object is found
741 *              Context             - Passed to user function
742 *              ReturnValue         - Location where return value of
743 *                                    UserFunction is put if terminated early
744 *
745 * RETURNS      Return value from the UserFunction if terminated early.
746 *              Otherwise, returns NULL.
747 *
748 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
749 *              starting (and ending) at the object specified by StartHandle.
750 *              The UserFunction is called whenever an object that matches
751 *              the type parameter is found.  If the user function returns
752 *              a non-zero value, the search is terminated immediately and this
753 *              value is returned to the caller.
754 *
755 *              This is a wrapper for WalkNamespace, but the callback performs
756 *              additional filtering. Please see AcpiGetDeviceCallback.
757 *
758 ******************************************************************************/
759
760ACPI_STATUS
761AcpiGetDevices (
762    NATIVE_CHAR             *HID,
763    ACPI_WALK_CALLBACK      UserFunction,
764    void                    *Context,
765    void                    **ReturnValue)
766{
767    ACPI_STATUS             Status;
768    ACPI_GET_DEVICES_INFO   Info;
769
770
771    FUNCTION_TRACE ("AcpiGetDevices");
772
773
774    /* Parameter validation */
775
776    if (!UserFunction)
777    {
778        return_ACPI_STATUS (AE_BAD_PARAMETER);
779    }
780
781    /*
782     * We're going to call their callback from OUR callback, so we need
783     * to know what it is, and their context parameter.
784     */
785    Info.Context      = Context;
786    Info.UserFunction = UserFunction;
787    Info.Hid          = HID;
788
789    /*
790     * Lock the namespace around the walk.
791     * The namespace will be unlocked/locked around each call
792     * to the user function - since this function
793     * must be allowed to make Acpi calls itself.
794     */
795    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
796    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE,
797                                    ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
798                                    NS_WALK_UNLOCK,
799                                    AcpiNsGetDeviceCallback, &Info,
800                                    ReturnValue);
801
802    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
803
804    return_ACPI_STATUS (Status);
805}
806