nsxfobj.c revision 82367
1/*******************************************************************************
2 *
3 * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
4 *                         ACPI Object oriented interfaces
5 *              $Revision: 88 $
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 *              **Params            - List of parameters to pass to
138 *                                    method, terminated by NULL.
139 *                                    Params itself may be NULL
140 *                                    if no parameters are being
141 *                                    passed.
142 *              *ReturnObject       - Where to put method's return value (if
143 *                                    any).  If NULL, no value is returned.
144 *
145 * RETURN:      Status
146 *
147 * DESCRIPTION: Find and evaluate the given object, passing the given
148 *              parameters if necessary.  One of "Handle" or "Pathname" must
149 *              be valid (non-null)
150 *
151 ******************************************************************************/
152
153ACPI_STATUS
154AcpiEvaluateObject (
155    ACPI_HANDLE             Handle,
156    ACPI_STRING             Pathname,
157    ACPI_OBJECT_LIST        *ParamObjects,
158    ACPI_BUFFER             *ReturnBuffer)
159{
160    ACPI_STATUS             Status;
161    ACPI_OPERAND_OBJECT     **ParamPtr = NULL;
162    ACPI_OPERAND_OBJECT     *ReturnObj = NULL;
163    ACPI_OPERAND_OBJECT     *ObjectPtr = NULL;
164    UINT32                  BufferSpaceNeeded;
165    UINT32                  UserBufferLength;
166    UINT32                  Count;
167    UINT32                  i;
168    UINT32                  ParamLength;
169    UINT32                  ObjectLength;
170
171
172    FUNCTION_TRACE ("AcpiEvaluateObject");
173
174
175    /* Ensure that ACPI has been initialized */
176
177    ACPI_IS_INITIALIZATION_COMPLETE (Status);
178    if (ACPI_FAILURE (Status))
179    {
180        return_ACPI_STATUS (Status);
181    }
182
183    /*
184     * If there are parameters to be passed to the object
185     * (which must be a control method), the external objects
186     * must be converted to internal objects
187     */
188
189    if (ParamObjects && ParamObjects->Count)
190    {
191        /*
192         * Allocate a new parameter block for the internal objects
193         * Add 1 to count to allow for null terminated internal list
194         */
195
196        Count           = ParamObjects->Count;
197        ParamLength     = (Count + 1) * sizeof (void *);
198        ObjectLength    = Count * sizeof (ACPI_OPERAND_OBJECT);
199
200        ParamPtr = ACPI_MEM_CALLOCATE (ParamLength +    /* Parameter List part */
201                                    ObjectLength);      /* Actual objects */
202        if (!ParamPtr)
203        {
204            return_ACPI_STATUS (AE_NO_MEMORY);
205        }
206
207        ObjectPtr = (ACPI_OPERAND_OBJECT  *) ((UINT8 *) ParamPtr +
208                        ParamLength);
209
210        /*
211         * Init the param array of pointers and NULL terminate
212         * the list
213         */
214
215        for (i = 0; i < Count; i++)
216        {
217            ParamPtr[i] = &ObjectPtr[i];
218            AcpiUtInitStaticObject (&ObjectPtr[i]);
219        }
220        ParamPtr[Count] = NULL;
221
222        /*
223         * Convert each external object in the list to an
224         * internal object
225         */
226        for (i = 0; i < Count; i++)
227        {
228            Status = AcpiUtCopyEobjectToIobject (&ParamObjects->Pointer[i],
229                                                ParamPtr[i]);
230
231            if (ACPI_FAILURE (Status))
232            {
233                AcpiUtDeleteInternalObjectList (ParamPtr);
234                return_ACPI_STATUS (Status);
235            }
236        }
237    }
238
239
240    /*
241     * Three major cases:
242     * 1) Fully qualified pathname
243     * 2) No handle, not fully qualified pathname (error)
244     * 3) Valid handle
245     */
246
247    if ((Pathname) &&
248        (AcpiNsValidRootPrefix (Pathname[0])))
249    {
250        /*
251         *  The path is fully qualified, just evaluate by name
252         */
253        Status = AcpiNsEvaluateByName (Pathname, ParamPtr, &ReturnObj);
254    }
255
256    else if (!Handle)
257    {
258        /*
259         * A handle is optional iff a fully qualified pathname
260         * is specified.  Since we've already handled fully
261         * qualified names above, this is an error
262         */
263
264        if (!Pathname)
265        {
266            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Both Handle and Pathname are NULL\n"));
267        }
268
269        else
270        {
271            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Handle is NULL and Pathname is relative\n"));
272        }
273
274        Status = AE_BAD_PARAMETER;
275    }
276
277    else
278    {
279        /*
280         * We get here if we have a handle -- and if we have a
281         * pathname it is relative.  The handle will be validated
282         * in the lower procedures
283         */
284
285        if (!Pathname)
286        {
287            /*
288             * The null pathname case means the handle is for
289             * the actual object to be evaluated
290             */
291            Status = AcpiNsEvaluateByHandle (Handle, ParamPtr, &ReturnObj);
292        }
293
294        else
295        {
296           /*
297            * Both a Handle and a relative Pathname
298            */
299            Status = AcpiNsEvaluateRelative (Handle, Pathname, ParamPtr,
300                                                &ReturnObj);
301        }
302    }
303
304
305    /*
306     * If we are expecting a return value, and all went well above,
307     * copy the return value to an external object.
308     */
309
310    if (ReturnBuffer)
311    {
312        UserBufferLength = ReturnBuffer->Length;
313        ReturnBuffer->Length = 0;
314
315        if (ReturnObj)
316        {
317            if (VALID_DESCRIPTOR_TYPE (ReturnObj, ACPI_DESC_TYPE_NAMED))
318            {
319                /*
320                 * If we got an Node as a return object,
321                 * this means the object we are evaluating
322                 * has nothing interesting to return (such
323                 * as a mutex, etc.)  We return an error
324                 * because these types are essentially
325                 * unsupported by this interface.  We
326                 * don't check up front because this makes
327                 * it easier to add support for various
328                 * types at a later date if necessary.
329                 */
330                Status = AE_TYPE;
331                ReturnObj = NULL;   /* No need to delete an Node */
332            }
333
334            if (ACPI_SUCCESS (Status))
335            {
336                /*
337                 * Find out how large a buffer is needed
338                 * to contain the returned object
339                 */
340                Status = AcpiUtGetObjectSize (ReturnObj,
341                                                &BufferSpaceNeeded);
342                if (ACPI_SUCCESS (Status))
343                {
344                    /*
345                     * Check if there is enough room in the
346                     * caller's buffer
347                     */
348
349                    if (UserBufferLength < BufferSpaceNeeded)
350                    {
351                        /*
352                         * Caller's buffer is too small, can't
353                         * give him partial results fail the call
354                         * but return the buffer size needed
355                         */
356
357                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
358                            "Needed buffer size %X, received %X\n",
359                            BufferSpaceNeeded, UserBufferLength));
360
361                        ReturnBuffer->Length = BufferSpaceNeeded;
362                        Status = AE_BUFFER_OVERFLOW;
363                    }
364
365                    else
366                    {
367                        /*
368                         *  We have enough space for the object, build it
369                         */
370                        Status = AcpiUtCopyIobjectToEobject (ReturnObj,
371                                        ReturnBuffer);
372                        ReturnBuffer->Length = BufferSpaceNeeded;
373                    }
374                }
375            }
376        }
377    }
378
379
380    /* Delete the return and parameter objects */
381
382    if (ReturnObj)
383    {
384        /*
385         * Delete the internal return object. (Or at least
386         * decrement the reference count by one)
387         */
388        AcpiUtRemoveReference (ReturnObj);
389    }
390
391    /*
392     * Free the input parameter list (if we created one),
393     */
394
395    if (ParamPtr)
396    {
397        /* Free the allocated parameter block */
398
399        AcpiUtDeleteInternalObjectList (ParamPtr);
400    }
401
402    return_ACPI_STATUS (Status);
403}
404
405
406/*******************************************************************************
407 *
408 * FUNCTION:    AcpiGetNextObject
409 *
410 * PARAMETERS:  Type            - Type of object to be searched for
411 *              Parent          - Parent object whose children we are getting
412 *              LastChild       - Previous child that was found.
413 *                                The NEXT child will be returned
414 *              RetHandle       - Where handle to the next object is placed
415 *
416 * RETURN:      Status
417 *
418 * DESCRIPTION: Return the next peer object within the namespace.  If Handle is
419 *              valid, Scope is ignored.  Otherwise, the first object within
420 *              Scope is returned.
421 *
422 ******************************************************************************/
423
424ACPI_STATUS
425AcpiGetNextObject (
426    ACPI_OBJECT_TYPE        Type,
427    ACPI_HANDLE             Parent,
428    ACPI_HANDLE             Child,
429    ACPI_HANDLE             *RetHandle)
430{
431    ACPI_STATUS             Status = AE_OK;
432    ACPI_NAMESPACE_NODE     *Node;
433    ACPI_NAMESPACE_NODE     *ParentNode = NULL;
434    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
435
436
437    /* Ensure that ACPI has been initialized */
438
439    ACPI_IS_INITIALIZATION_COMPLETE (Status);
440    if (ACPI_FAILURE (Status))
441    {
442        return (Status);
443    }
444
445    /* Parameter validation */
446
447    if (Type > ACPI_TYPE_MAX)
448    {
449        return (AE_BAD_PARAMETER);
450    }
451
452    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
453
454    /* If null handle, use the parent */
455
456    if (!Child)
457    {
458        /* Start search at the beginning of the specified scope */
459
460        ParentNode = AcpiNsConvertHandleToEntry (Parent);
461        if (!ParentNode)
462        {
463            Status = AE_BAD_PARAMETER;
464            goto UnlockAndExit;
465        }
466    }
467
468    /* Non-null handle, ignore the parent */
469
470    else
471    {
472        /* Convert and validate the handle */
473
474        ChildNode = AcpiNsConvertHandleToEntry (Child);
475        if (!ChildNode)
476        {
477            Status = AE_BAD_PARAMETER;
478            goto UnlockAndExit;
479        }
480    }
481
482
483    /* Internal function does the real work */
484
485    Node = AcpiNsGetNextObject ((ACPI_OBJECT_TYPE8) Type,
486                                    ParentNode, ChildNode);
487    if (!Node)
488    {
489        Status = AE_NOT_FOUND;
490        goto UnlockAndExit;
491    }
492
493    if (RetHandle)
494    {
495        *RetHandle = AcpiNsConvertEntryToHandle (Node);
496    }
497
498
499UnlockAndExit:
500
501    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
502    return (Status);
503}
504
505
506/*******************************************************************************
507 *
508 * FUNCTION:    AcpiGetType
509 *
510 * PARAMETERS:  Handle          - Handle of object whose type is desired
511 *              *RetType        - Where the type will be placed
512 *
513 * RETURN:      Status
514 *
515 * DESCRIPTION: This routine returns the type associatd with a particular handle
516 *
517 ******************************************************************************/
518
519ACPI_STATUS
520AcpiGetType (
521    ACPI_HANDLE             Handle,
522    ACPI_OBJECT_TYPE        *RetType)
523{
524    ACPI_NAMESPACE_NODE     *Node;
525    ACPI_STATUS             Status;
526
527
528    /* Ensure that ACPI has been initialized */
529
530    ACPI_IS_INITIALIZATION_COMPLETE (Status);
531    if (ACPI_FAILURE (Status))
532    {
533        return (Status);
534    }
535
536    /* Parameter Validation */
537
538    if (!RetType)
539    {
540        return (AE_BAD_PARAMETER);
541    }
542
543    /*
544     * Special case for the predefined Root Node
545     * (return type ANY)
546     */
547    if (Handle == ACPI_ROOT_OBJECT)
548    {
549        *RetType = ACPI_TYPE_ANY;
550        return (AE_OK);
551    }
552
553    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
554
555    /* Convert and validate the handle */
556
557    Node = AcpiNsConvertHandleToEntry (Handle);
558    if (!Node)
559    {
560        AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
561        return (AE_BAD_PARAMETER);
562    }
563
564    *RetType = Node->Type;
565
566
567    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
568    return (AE_OK);
569}
570
571
572/*******************************************************************************
573 *
574 * FUNCTION:    AcpiGetParent
575 *
576 * PARAMETERS:  Handle          - Handle of object whose parent is desired
577 *              RetHandle       - Where the parent handle will be placed
578 *
579 * RETURN:      Status
580 *
581 * DESCRIPTION: Returns a handle to the parent of the object represented by
582 *              Handle.
583 *
584 ******************************************************************************/
585
586ACPI_STATUS
587AcpiGetParent (
588    ACPI_HANDLE             Handle,
589    ACPI_HANDLE             *RetHandle)
590{
591    ACPI_NAMESPACE_NODE     *Node;
592    ACPI_STATUS             Status = AE_OK;
593
594
595    /* Ensure that ACPI has been initialized */
596
597    ACPI_IS_INITIALIZATION_COMPLETE (Status);
598    if (ACPI_FAILURE (Status))
599    {
600        return (Status);
601    }
602
603    if (!RetHandle)
604    {
605        return (AE_BAD_PARAMETER);
606    }
607
608    /* Special case for the predefined Root Node (no parent) */
609
610    if (Handle == ACPI_ROOT_OBJECT)
611    {
612        return (AE_NULL_ENTRY);
613    }
614
615
616    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
617
618    /* Convert and validate the handle */
619
620    Node = AcpiNsConvertHandleToEntry (Handle);
621    if (!Node)
622    {
623        Status = AE_BAD_PARAMETER;
624        goto UnlockAndExit;
625    }
626
627
628    /* Get the parent entry */
629
630    *RetHandle =
631        AcpiNsConvertEntryToHandle (AcpiNsGetParentObject (Node));
632
633    /* Return exeption if parent is null */
634
635    if (!AcpiNsGetParentObject (Node))
636    {
637        Status = AE_NULL_ENTRY;
638    }
639
640
641UnlockAndExit:
642
643    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
644    return (Status);
645}
646
647
648/*******************************************************************************
649 *
650 * FUNCTION:    AcpiWalkNamespace
651 *
652 * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
653 *              StartObject         - Handle in namespace where search begins
654 *              MaxDepth            - Depth to which search is to reach
655 *              UserFunction        - Called when an object of "Type" is found
656 *              Context             - Passed to user function
657 *              ReturnValue         - Location where return value of
658 *                                    UserFunction is put if terminated early
659 *
660 * RETURNS      Return value from the UserFunction if terminated early.
661 *              Otherwise, returns NULL.
662 *
663 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
664 *              starting (and ending) at the object specified by StartHandle.
665 *              The UserFunction is called whenever an object that matches
666 *              the type parameter is found.  If the user function returns
667 *              a non-zero value, the search is terminated immediately and this
668 *              value is returned to the caller.
669 *
670 *              The point of this procedure is to provide a generic namespace
671 *              walk routine that can be called from multiple places to
672 *              provide multiple services;  the User Function can be tailored
673 *              to each task, whether it is a print function, a compare
674 *              function, etc.
675 *
676 ******************************************************************************/
677
678ACPI_STATUS
679AcpiWalkNamespace (
680    ACPI_OBJECT_TYPE        Type,
681    ACPI_HANDLE             StartObject,
682    UINT32                  MaxDepth,
683    ACPI_WALK_CALLBACK      UserFunction,
684    void                    *Context,
685    void                    **ReturnValue)
686{
687    ACPI_STATUS             Status;
688
689
690    FUNCTION_TRACE ("AcpiWalkNamespace");
691
692
693    /* Ensure that ACPI has been initialized */
694
695    ACPI_IS_INITIALIZATION_COMPLETE (Status);
696    if (ACPI_FAILURE (Status))
697    {
698        return_ACPI_STATUS (Status);
699    }
700
701    /* Parameter validation */
702
703    if ((Type > ACPI_TYPE_MAX)  ||
704        (!MaxDepth)             ||
705        (!UserFunction))
706    {
707        return_ACPI_STATUS (AE_BAD_PARAMETER);
708    }
709
710    /*
711     * Lock the namespace around the walk.
712     * The namespace will be unlocked/locked around each call
713     * to the user function - since this function
714     * must be allowed to make Acpi calls itself.
715     */
716
717    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
718    Status = AcpiNsWalkNamespace ((ACPI_OBJECT_TYPE8) Type,
719                                    StartObject, MaxDepth,
720                                    NS_WALK_UNLOCK,
721                                    UserFunction, Context,
722                                    ReturnValue);
723
724    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
725
726    return_ACPI_STATUS (Status);
727}
728
729
730/*******************************************************************************
731 *
732 * FUNCTION:    AcpiNsGetDeviceCallback
733 *
734 * PARAMETERS:  Callback from AcpiGetDevice
735 *
736 * RETURN:      Status
737 *
738 * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
739 *              present devices, or if they specified a HID, it filters based
740 *              on that.
741 *
742 ******************************************************************************/
743
744static ACPI_STATUS
745AcpiNsGetDeviceCallback (
746    ACPI_HANDLE             ObjHandle,
747    UINT32                  NestingLevel,
748    void                    *Context,
749    void                    **ReturnValue)
750{
751    ACPI_STATUS             Status;
752    ACPI_NAMESPACE_NODE     *Node;
753    UINT32                  Flags;
754    ACPI_DEVICE_ID          DeviceId;
755    ACPI_GET_DEVICES_INFO   *Info;
756
757
758    Info = Context;
759
760    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
761    Node = AcpiNsConvertHandleToEntry (ObjHandle);
762    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
763
764    if (!Node)
765    {
766        return (AE_BAD_PARAMETER);
767    }
768
769    /*
770     * Run _STA to determine if device is present
771     */
772    Status = AcpiUtExecute_STA (Node, &Flags);
773    if (ACPI_FAILURE (Status))
774    {
775        return (AE_CTRL_DEPTH);
776    }
777
778    if (!(Flags & 0x01))
779    {
780        /* don't return at the device or children of the device if not there */
781        return (AE_CTRL_DEPTH);
782    }
783
784    /*
785     * Filter based on device HID
786     */
787    if (Info->Hid != NULL)
788    {
789        Status = AcpiUtExecute_HID (Node, &DeviceId);
790        if (Status == AE_NOT_FOUND)
791        {
792            return (AE_OK);
793        }
794
795        else if (ACPI_FAILURE (Status))
796        {
797            return (AE_CTRL_DEPTH);
798        }
799
800        if (STRNCMP (DeviceId.Buffer, Info->Hid, sizeof (DeviceId.Buffer)) != 0)
801        {
802            return (AE_OK);
803        }
804    }
805
806    Info->UserFunction (ObjHandle, NestingLevel, Info->Context, ReturnValue);
807    return (AE_OK);
808}
809
810
811/*******************************************************************************
812 *
813 * FUNCTION:    AcpiGetDevices
814 *
815 * PARAMETERS:  HID                 - HID to search for. Can be NULL.
816 *              UserFunction        - Called when a matching object is found
817 *              Context             - Passed to user function
818 *              ReturnValue         - Location where return value of
819 *                                    UserFunction is put if terminated early
820 *
821 * RETURNS      Return value from the UserFunction if terminated early.
822 *              Otherwise, returns NULL.
823 *
824 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
825 *              starting (and ending) at the object specified by StartHandle.
826 *              The UserFunction is called whenever an object that matches
827 *              the type parameter is found.  If the user function returns
828 *              a non-zero value, the search is terminated immediately and this
829 *              value is returned to the caller.
830 *
831 *              This is a wrapper for WalkNamespace, but the callback performs
832 *              additional filtering. Please see AcpiGetDeviceCallback.
833 *
834 ******************************************************************************/
835
836ACPI_STATUS
837AcpiGetDevices (
838    NATIVE_CHAR             *HID,
839    ACPI_WALK_CALLBACK      UserFunction,
840    void                    *Context,
841    void                    **ReturnValue)
842{
843    ACPI_STATUS             Status;
844    ACPI_GET_DEVICES_INFO   Info;
845
846
847    FUNCTION_TRACE ("AcpiGetDevices");
848
849
850    /* Ensure that ACPI has been initialized */
851
852    ACPI_IS_INITIALIZATION_COMPLETE (Status);
853    if (ACPI_FAILURE (Status))
854    {
855        return_ACPI_STATUS (Status);
856    }
857
858    /* Parameter validation */
859
860    if (!UserFunction)
861    {
862        return_ACPI_STATUS (AE_BAD_PARAMETER);
863    }
864
865    /*
866     * We're going to call their callback from OUR callback, so we need
867     * to know what it is, and their context parameter.
868     */
869    Info.Context      = Context;
870    Info.UserFunction = UserFunction;
871    Info.Hid          = HID;
872
873    /*
874     * Lock the namespace around the walk.
875     * The namespace will be unlocked/locked around each call
876     * to the user function - since this function
877     * must be allowed to make Acpi calls itself.
878     */
879
880    AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
881    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE,
882                                    ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
883                                    NS_WALK_UNLOCK,
884                                    AcpiNsGetDeviceCallback, &Info,
885                                    ReturnValue);
886
887    AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
888
889    return_ACPI_STATUS (Status);
890}
891