nsxfeval.c revision 197104
1/*******************************************************************************
2 *
3 * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4 *                         ACPI Object evaluation interfaces
5 *
6 ******************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#define __NSXFEVAL_C__
119
120#include <contrib/dev/acpica/include/acpi.h>
121#include <contrib/dev/acpica/include/accommon.h>
122#include <contrib/dev/acpica/include/acnamesp.h>
123#include <contrib/dev/acpica/include/acinterp.h>
124
125
126#define _COMPONENT          ACPI_NAMESPACE
127        ACPI_MODULE_NAME    ("nsxfeval")
128
129/* Local prototypes */
130
131static void
132AcpiNsResolveReferences (
133    ACPI_EVALUATE_INFO      *Info);
134
135
136/*******************************************************************************
137 *
138 * FUNCTION:    AcpiEvaluateObjectTyped
139 *
140 * PARAMETERS:  Handle              - Object handle (optional)
141 *              Pathname            - Object pathname (optional)
142 *              ExternalParams      - List of parameters to pass to method,
143 *                                    terminated by NULL.  May be NULL
144 *                                    if no parameters are being passed.
145 *              ReturnBuffer        - Where to put method's return value (if
146 *                                    any).  If NULL, no value is returned.
147 *              ReturnType          - Expected type of return object
148 *
149 * RETURN:      Status
150 *
151 * DESCRIPTION: Find and evaluate the given object, passing the given
152 *              parameters if necessary.  One of "Handle" or "Pathname" must
153 *              be valid (non-null)
154 *
155 ******************************************************************************/
156
157ACPI_STATUS
158AcpiEvaluateObjectTyped (
159    ACPI_HANDLE             Handle,
160    ACPI_STRING             Pathname,
161    ACPI_OBJECT_LIST        *ExternalParams,
162    ACPI_BUFFER             *ReturnBuffer,
163    ACPI_OBJECT_TYPE        ReturnType)
164{
165    ACPI_STATUS             Status;
166    BOOLEAN                 MustFree = FALSE;
167
168
169    ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
170
171
172    /* Return buffer must be valid */
173
174    if (!ReturnBuffer)
175    {
176        return_ACPI_STATUS (AE_BAD_PARAMETER);
177    }
178
179    if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
180    {
181        MustFree = TRUE;
182    }
183
184    /* Evaluate the object */
185
186    Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer);
187    if (ACPI_FAILURE (Status))
188    {
189        return_ACPI_STATUS (Status);
190    }
191
192    /* Type ANY means "don't care" */
193
194    if (ReturnType == ACPI_TYPE_ANY)
195    {
196        return_ACPI_STATUS (AE_OK);
197    }
198
199    if (ReturnBuffer->Length == 0)
200    {
201        /* Error because caller specifically asked for a return value */
202
203        ACPI_ERROR ((AE_INFO, "No return value"));
204        return_ACPI_STATUS (AE_NULL_OBJECT);
205    }
206
207    /* Examine the object type returned from EvaluateObject */
208
209    if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
210    {
211        return_ACPI_STATUS (AE_OK);
212    }
213
214    /* Return object type does not match requested type */
215
216    ACPI_ERROR ((AE_INFO,
217        "Incorrect return type [%s] requested [%s]",
218        AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
219        AcpiUtGetTypeName (ReturnType)));
220
221    if (MustFree)
222    {
223        /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
224
225        AcpiOsFree (ReturnBuffer->Pointer);
226        ReturnBuffer->Pointer = NULL;
227    }
228
229    ReturnBuffer->Length = 0;
230    return_ACPI_STATUS (AE_TYPE);
231}
232
233ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
234
235
236/*******************************************************************************
237 *
238 * FUNCTION:    AcpiEvaluateObject
239 *
240 * PARAMETERS:  Handle              - Object handle (optional)
241 *              Pathname            - Object pathname (optional)
242 *              ExternalParams      - List of parameters to pass to method,
243 *                                    terminated by NULL.  May be NULL
244 *                                    if no parameters are being passed.
245 *              ReturnBuffer        - Where to put method's return value (if
246 *                                    any).  If NULL, no value is returned.
247 *
248 * RETURN:      Status
249 *
250 * DESCRIPTION: Find and evaluate the given object, passing the given
251 *              parameters if necessary.  One of "Handle" or "Pathname" must
252 *              be valid (non-null)
253 *
254 ******************************************************************************/
255
256ACPI_STATUS
257AcpiEvaluateObject (
258    ACPI_HANDLE             Handle,
259    ACPI_STRING             Pathname,
260    ACPI_OBJECT_LIST        *ExternalParams,
261    ACPI_BUFFER             *ReturnBuffer)
262{
263    ACPI_STATUS             Status;
264    ACPI_EVALUATE_INFO      *Info;
265    ACPI_SIZE               BufferSpaceNeeded;
266    UINT32                  i;
267
268
269    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
270
271
272    /* Allocate and initialize the evaluation information block */
273
274    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
275    if (!Info)
276    {
277        return_ACPI_STATUS (AE_NO_MEMORY);
278    }
279
280    Info->Pathname = Pathname;
281
282    /* Convert and validate the device handle */
283
284    Info->PrefixNode = AcpiNsMapHandleToNode (Handle);
285    if (!Info->PrefixNode)
286    {
287        Status = AE_BAD_PARAMETER;
288        goto Cleanup;
289    }
290
291    /*
292     * If there are parameters to be passed to a control method, the external
293     * objects must all be converted to internal objects
294     */
295    if (ExternalParams && ExternalParams->Count)
296    {
297        /*
298         * Allocate a new parameter block for the internal objects
299         * Add 1 to count to allow for null terminated internal list
300         */
301        Info->Parameters = ACPI_ALLOCATE_ZEROED (
302            ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
303        if (!Info->Parameters)
304        {
305            Status = AE_NO_MEMORY;
306            goto Cleanup;
307        }
308
309        /* Convert each external object in the list to an internal object */
310
311        for (i = 0; i < ExternalParams->Count; i++)
312        {
313            Status = AcpiUtCopyEobjectToIobject (
314                        &ExternalParams->Pointer[i], &Info->Parameters[i]);
315            if (ACPI_FAILURE (Status))
316            {
317                goto Cleanup;
318            }
319        }
320        Info->Parameters[ExternalParams->Count] = NULL;
321    }
322
323    /*
324     * Three major cases:
325     * 1) Fully qualified pathname
326     * 2) No handle, not fully qualified pathname (error)
327     * 3) Valid handle
328     */
329    if ((Pathname) &&
330        (AcpiNsValidRootPrefix (Pathname[0])))
331    {
332        /* The path is fully qualified, just evaluate by name */
333
334        Info->PrefixNode = NULL;
335        Status = AcpiNsEvaluate (Info);
336    }
337    else if (!Handle)
338    {
339        /*
340         * A handle is optional iff a fully qualified pathname is specified.
341         * Since we've already handled fully qualified names above, this is
342         * an error
343         */
344        if (!Pathname)
345        {
346            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
347                "Both Handle and Pathname are NULL"));
348        }
349        else
350        {
351            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
352                "Null Handle with relative pathname [%s]", Pathname));
353        }
354
355        Status = AE_BAD_PARAMETER;
356    }
357    else
358    {
359        /* We have a namespace a node and a possible relative path */
360
361        Status = AcpiNsEvaluate (Info);
362    }
363
364    /*
365     * If we are expecting a return value, and all went well above,
366     * copy the return value to an external object.
367     */
368    if (ReturnBuffer)
369    {
370        if (!Info->ReturnObject)
371        {
372            ReturnBuffer->Length = 0;
373        }
374        else
375        {
376            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
377                ACPI_DESC_TYPE_NAMED)
378            {
379                /*
380                 * If we received a NS Node as a return object, this means that
381                 * the object we are evaluating has nothing interesting to
382                 * return (such as a mutex, etc.)  We return an error because
383                 * these types are essentially unsupported by this interface.
384                 * We don't check up front because this makes it easier to add
385                 * support for various types at a later date if necessary.
386                 */
387                Status = AE_TYPE;
388                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
389                ReturnBuffer->Length = 0;
390            }
391
392            if (ACPI_SUCCESS (Status))
393            {
394                /* Dereference Index and RefOf references */
395
396                AcpiNsResolveReferences (Info);
397
398                /* Get the size of the returned object */
399
400                Status = AcpiUtGetObjectSize (Info->ReturnObject,
401                            &BufferSpaceNeeded);
402                if (ACPI_SUCCESS (Status))
403                {
404                    /* Validate/Allocate/Clear caller buffer */
405
406                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
407                                BufferSpaceNeeded);
408                    if (ACPI_FAILURE (Status))
409                    {
410                        /*
411                         * Caller's buffer is too small or a new one can't
412                         * be allocated
413                         */
414                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
415                            "Needed buffer size %X, %s\n",
416                            (UINT32) BufferSpaceNeeded,
417                            AcpiFormatException (Status)));
418                    }
419                    else
420                    {
421                        /* We have enough space for the object, build it */
422
423                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
424                                    ReturnBuffer);
425                    }
426                }
427            }
428        }
429    }
430
431    if (Info->ReturnObject)
432    {
433        /*
434         * Delete the internal return object. NOTE: Interpreter must be
435         * locked to avoid race condition.
436         */
437        AcpiExEnterInterpreter ();
438
439        /* Remove one reference on the return object (should delete it) */
440
441        AcpiUtRemoveReference (Info->ReturnObject);
442        AcpiExExitInterpreter ();
443    }
444
445
446Cleanup:
447
448    /* Free the input parameter list (if we created one) */
449
450    if (Info->Parameters)
451    {
452        /* Free the allocated parameter block */
453
454        AcpiUtDeleteInternalObjectList (Info->Parameters);
455    }
456
457    ACPI_FREE (Info);
458    return_ACPI_STATUS (Status);
459}
460
461ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
462
463
464/*******************************************************************************
465 *
466 * FUNCTION:    AcpiNsResolveReferences
467 *
468 * PARAMETERS:  Info                    - Evaluation info block
469 *
470 * RETURN:      Info->ReturnObject is replaced with the dereferenced object
471 *
472 * DESCRIPTION: Dereference certain reference objects. Called before an
473 *              internal return object is converted to an external ACPI_OBJECT.
474 *
475 * Performs an automatic dereference of Index and RefOf reference objects.
476 * These reference objects are not supported by the ACPI_OBJECT, so this is a
477 * last resort effort to return something useful. Also, provides compatibility
478 * with other ACPI implementations.
479 *
480 * NOTE: does not handle references within returned package objects or nested
481 * references, but this support could be added later if found to be necessary.
482 *
483 ******************************************************************************/
484
485static void
486AcpiNsResolveReferences (
487    ACPI_EVALUATE_INFO      *Info)
488{
489    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
490    ACPI_NAMESPACE_NODE     *Node;
491
492
493    /* We are interested in reference objects only */
494
495    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
496    {
497        return;
498    }
499
500    /*
501     * Two types of references are supported - those created by Index and
502     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
503     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
504     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
505     * an ACPI_OBJECT.
506     */
507    switch (Info->ReturnObject->Reference.Class)
508    {
509    case ACPI_REFCLASS_INDEX:
510
511        ObjDesc = *(Info->ReturnObject->Reference.Where);
512        break;
513
514    case ACPI_REFCLASS_REFOF:
515
516        Node = Info->ReturnObject->Reference.Object;
517        if (Node)
518        {
519            ObjDesc = Node->Object;
520        }
521        break;
522
523    default:
524        return;
525    }
526
527    /* Replace the existing reference object */
528
529    if (ObjDesc)
530    {
531        AcpiUtAddReference (ObjDesc);
532        AcpiUtRemoveReference (Info->ReturnObject);
533        Info->ReturnObject = ObjDesc;
534    }
535
536    return;
537}
538
539
540/*******************************************************************************
541 *
542 * FUNCTION:    AcpiWalkNamespace
543 *
544 * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
545 *              StartObject         - Handle in namespace where search begins
546 *              MaxDepth            - Depth to which search is to reach
547 *              UserFunction        - Called when an object of "Type" is found
548 *              Context             - Passed to user function
549 *              ReturnValue         - Location where return value of
550 *                                    UserFunction is put if terminated early
551 *
552 * RETURNS      Return value from the UserFunction if terminated early.
553 *              Otherwise, returns NULL.
554 *
555 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
556 *              starting (and ending) at the object specified by StartHandle.
557 *              The UserFunction is called whenever an object that matches
558 *              the type parameter is found.  If the user function returns
559 *              a non-zero value, the search is terminated immediately and this
560 *              value is returned to the caller.
561 *
562 *              The point of this procedure is to provide a generic namespace
563 *              walk routine that can be called from multiple places to
564 *              provide multiple services;  the User Function can be tailored
565 *              to each task, whether it is a print function, a compare
566 *              function, etc.
567 *
568 ******************************************************************************/
569
570ACPI_STATUS
571AcpiWalkNamespace (
572    ACPI_OBJECT_TYPE        Type,
573    ACPI_HANDLE             StartObject,
574    UINT32                  MaxDepth,
575    ACPI_WALK_CALLBACK      UserFunction,
576    void                    *Context,
577    void                    **ReturnValue)
578{
579    ACPI_STATUS             Status;
580
581
582    ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
583
584
585    /* Parameter validation */
586
587    if ((Type > ACPI_TYPE_LOCAL_MAX) ||
588        (!MaxDepth)                  ||
589        (!UserFunction))
590    {
591        return_ACPI_STATUS (AE_BAD_PARAMETER);
592    }
593
594    /*
595     * Need to acquire the namespace reader lock to prevent interference
596     * with any concurrent table unloads (which causes the deletion of
597     * namespace objects). We cannot allow the deletion of a namespace node
598     * while the user function is using it. The exception to this are the
599     * nodes created and deleted during control method execution -- these
600     * nodes are marked as temporary nodes and are ignored by the namespace
601     * walk. Thus, control methods can be executed while holding the
602     * namespace deletion lock (and the user function can execute control
603     * methods.)
604     */
605    Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
606    if (ACPI_FAILURE (Status))
607    {
608        return (Status);
609    }
610
611    /*
612     * Lock the namespace around the walk. The namespace will be
613     * unlocked/locked around each call to the user function - since the user
614     * function must be allowed to make ACPICA calls itself (for example, it
615     * will typically execute control methods during device enumeration.)
616     */
617    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
618    if (ACPI_FAILURE (Status))
619    {
620        goto UnlockAndExit;
621    }
622
623    Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
624                ACPI_NS_WALK_UNLOCK, UserFunction, Context, ReturnValue);
625
626    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
627
628UnlockAndExit:
629    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
630    return_ACPI_STATUS (Status);
631}
632
633ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
634
635
636/*******************************************************************************
637 *
638 * FUNCTION:    AcpiNsGetDeviceCallback
639 *
640 * PARAMETERS:  Callback from AcpiGetDevice
641 *
642 * RETURN:      Status
643 *
644 * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
645 *              present devices, or if they specified a HID, it filters based
646 *              on that.
647 *
648 ******************************************************************************/
649
650static ACPI_STATUS
651AcpiNsGetDeviceCallback (
652    ACPI_HANDLE             ObjHandle,
653    UINT32                  NestingLevel,
654    void                    *Context,
655    void                    **ReturnValue)
656{
657    ACPI_GET_DEVICES_INFO   *Info = Context;
658    ACPI_STATUS             Status;
659    ACPI_NAMESPACE_NODE     *Node;
660    UINT32                  Flags;
661    ACPI_DEVICE_ID          *Hid;
662    ACPI_DEVICE_ID_LIST     *Cid;
663    UINT32                  i;
664    BOOLEAN                 Found;
665    int                     NoMatch;
666
667
668    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
669    if (ACPI_FAILURE (Status))
670    {
671        return (Status);
672    }
673
674    Node = AcpiNsMapHandleToNode (ObjHandle);
675    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
676    if (ACPI_FAILURE (Status))
677    {
678        return (Status);
679    }
680
681    if (!Node)
682    {
683        return (AE_BAD_PARAMETER);
684    }
685
686    /* Run _STA to determine if device is present */
687
688    Status = AcpiUtExecute_STA (Node, &Flags);
689    if (ACPI_FAILURE (Status))
690    {
691        return (AE_CTRL_DEPTH);
692    }
693
694    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
695        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
696    {
697        /*
698         * Don't examine the children of the device only when the
699         * device is neither present nor functional. See ACPI spec,
700         * description of _STA for more information.
701         */
702        return (AE_CTRL_DEPTH);
703    }
704
705    /* Filter based on device HID & CID */
706
707    if (Info->Hid != NULL)
708    {
709        Status = AcpiUtExecute_HID (Node, &Hid);
710        if (Status == AE_NOT_FOUND)
711        {
712            return (AE_OK);
713        }
714        else if (ACPI_FAILURE (Status))
715        {
716            return (AE_CTRL_DEPTH);
717        }
718
719        NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
720        ACPI_FREE (Hid);
721
722        if (NoMatch)
723        {
724            /*
725             * HID does not match, attempt match within the
726             * list of Compatible IDs (CIDs)
727             */
728            Status = AcpiUtExecute_CID (Node, &Cid);
729            if (Status == AE_NOT_FOUND)
730            {
731                return (AE_OK);
732            }
733            else if (ACPI_FAILURE (Status))
734            {
735                return (AE_CTRL_DEPTH);
736            }
737
738            /* Walk the CID list */
739
740            Found = FALSE;
741            for (i = 0; i < Cid->Count; i++)
742            {
743                if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
744                {
745                    /* Found a matching CID */
746
747                    Found = TRUE;
748                    break;
749                }
750            }
751
752            ACPI_FREE (Cid);
753            if (!Found)
754            {
755                return (AE_OK);
756            }
757        }
758    }
759
760    /* We have a valid device, invoke the user function */
761
762    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
763                ReturnValue);
764    return (Status);
765}
766
767
768/*******************************************************************************
769 *
770 * FUNCTION:    AcpiGetDevices
771 *
772 * PARAMETERS:  HID                 - HID to search for. Can be NULL.
773 *              UserFunction        - Called when a matching object is found
774 *              Context             - Passed to user function
775 *              ReturnValue         - Location where return value of
776 *                                    UserFunction is put if terminated early
777 *
778 * RETURNS      Return value from the UserFunction if terminated early.
779 *              Otherwise, returns NULL.
780 *
781 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
782 *              starting (and ending) at the object specified by StartHandle.
783 *              The UserFunction is called whenever an object of type
784 *              Device is found.  If the user function returns
785 *              a non-zero value, the search is terminated immediately and this
786 *              value is returned to the caller.
787 *
788 *              This is a wrapper for WalkNamespace, but the callback performs
789 *              additional filtering. Please see AcpiNsGetDeviceCallback.
790 *
791 ******************************************************************************/
792
793ACPI_STATUS
794AcpiGetDevices (
795    char                    *HID,
796    ACPI_WALK_CALLBACK      UserFunction,
797    void                    *Context,
798    void                    **ReturnValue)
799{
800    ACPI_STATUS             Status;
801    ACPI_GET_DEVICES_INFO   Info;
802
803
804    ACPI_FUNCTION_TRACE (AcpiGetDevices);
805
806
807    /* Parameter validation */
808
809    if (!UserFunction)
810    {
811        return_ACPI_STATUS (AE_BAD_PARAMETER);
812    }
813
814    /*
815     * We're going to call their callback from OUR callback, so we need
816     * to know what it is, and their context parameter.
817     */
818    Info.Hid          = HID;
819    Info.Context      = Context;
820    Info.UserFunction = UserFunction;
821
822    /*
823     * Lock the namespace around the walk.
824     * The namespace will be unlocked/locked around each call
825     * to the user function - since this function
826     * must be allowed to make Acpi calls itself.
827     */
828    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
829    if (ACPI_FAILURE (Status))
830    {
831        return_ACPI_STATUS (Status);
832    }
833
834    Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
835                ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
836                AcpiNsGetDeviceCallback, &Info, ReturnValue);
837
838    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
839    return_ACPI_STATUS (Status);
840}
841
842ACPI_EXPORT_SYMBOL (AcpiGetDevices)
843
844
845/*******************************************************************************
846 *
847 * FUNCTION:    AcpiAttachData
848 *
849 * PARAMETERS:  ObjHandle           - Namespace node
850 *              Handler             - Handler for this attachment
851 *              Data                - Pointer to data to be attached
852 *
853 * RETURN:      Status
854 *
855 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
856 *
857 ******************************************************************************/
858
859ACPI_STATUS
860AcpiAttachData (
861    ACPI_HANDLE             ObjHandle,
862    ACPI_OBJECT_HANDLER     Handler,
863    void                    *Data)
864{
865    ACPI_NAMESPACE_NODE     *Node;
866    ACPI_STATUS             Status;
867
868
869    /* Parameter validation */
870
871    if (!ObjHandle  ||
872        !Handler    ||
873        !Data)
874    {
875        return (AE_BAD_PARAMETER);
876    }
877
878    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
879    if (ACPI_FAILURE (Status))
880    {
881        return (Status);
882    }
883
884    /* Convert and validate the handle */
885
886    Node = AcpiNsMapHandleToNode (ObjHandle);
887    if (!Node)
888    {
889        Status = AE_BAD_PARAMETER;
890        goto UnlockAndExit;
891    }
892
893    Status = AcpiNsAttachData (Node, Handler, Data);
894
895UnlockAndExit:
896    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
897    return (Status);
898}
899
900ACPI_EXPORT_SYMBOL (AcpiAttachData)
901
902
903/*******************************************************************************
904 *
905 * FUNCTION:    AcpiDetachData
906 *
907 * PARAMETERS:  ObjHandle           - Namespace node handle
908 *              Handler             - Handler used in call to AcpiAttachData
909 *
910 * RETURN:      Status
911 *
912 * DESCRIPTION: Remove data that was previously attached to a node.
913 *
914 ******************************************************************************/
915
916ACPI_STATUS
917AcpiDetachData (
918    ACPI_HANDLE             ObjHandle,
919    ACPI_OBJECT_HANDLER     Handler)
920{
921    ACPI_NAMESPACE_NODE     *Node;
922    ACPI_STATUS             Status;
923
924
925    /* Parameter validation */
926
927    if (!ObjHandle  ||
928        !Handler)
929    {
930        return (AE_BAD_PARAMETER);
931    }
932
933    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
934    if (ACPI_FAILURE (Status))
935    {
936        return (Status);
937    }
938
939    /* Convert and validate the handle */
940
941    Node = AcpiNsMapHandleToNode (ObjHandle);
942    if (!Node)
943    {
944        Status = AE_BAD_PARAMETER;
945        goto UnlockAndExit;
946    }
947
948    Status = AcpiNsDetachData (Node, Handler);
949
950UnlockAndExit:
951    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
952    return (Status);
953}
954
955ACPI_EXPORT_SYMBOL (AcpiDetachData)
956
957
958/*******************************************************************************
959 *
960 * FUNCTION:    AcpiGetData
961 *
962 * PARAMETERS:  ObjHandle           - Namespace node
963 *              Handler             - Handler used in call to AttachData
964 *              Data                - Where the data is returned
965 *
966 * RETURN:      Status
967 *
968 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
969 *
970 ******************************************************************************/
971
972ACPI_STATUS
973AcpiGetData (
974    ACPI_HANDLE             ObjHandle,
975    ACPI_OBJECT_HANDLER     Handler,
976    void                    **Data)
977{
978    ACPI_NAMESPACE_NODE     *Node;
979    ACPI_STATUS             Status;
980
981
982    /* Parameter validation */
983
984    if (!ObjHandle  ||
985        !Handler    ||
986        !Data)
987    {
988        return (AE_BAD_PARAMETER);
989    }
990
991    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
992    if (ACPI_FAILURE (Status))
993    {
994        return (Status);
995    }
996
997    /* Convert and validate the handle */
998
999    Node = AcpiNsMapHandleToNode (ObjHandle);
1000    if (!Node)
1001    {
1002        Status = AE_BAD_PARAMETER;
1003        goto UnlockAndExit;
1004    }
1005
1006    Status = AcpiNsGetAttachedData (Node, Handler, Data);
1007
1008UnlockAndExit:
1009    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1010    return (Status);
1011}
1012
1013ACPI_EXPORT_SYMBOL (AcpiGetData)
1014
1015
1016