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