xref: /minix3/minix/drivers/power/acpi/namespace/nsxfeval.c (revision 29492bb71c7148a089a5afafa0c99409161218df)
1433d6423SLionel Sambuc /*******************************************************************************
2433d6423SLionel Sambuc  *
3433d6423SLionel Sambuc  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4433d6423SLionel Sambuc  *                         ACPI Object evaluation interfaces
5433d6423SLionel Sambuc  *
6433d6423SLionel Sambuc  ******************************************************************************/
7433d6423SLionel Sambuc 
8*29492bb7SDavid van Moolenbroek /*
9*29492bb7SDavid van Moolenbroek  * Copyright (C) 2000 - 2014, Intel Corp.
10433d6423SLionel Sambuc  * All rights reserved.
11433d6423SLionel Sambuc  *
12*29492bb7SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
13*29492bb7SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
14*29492bb7SDavid van Moolenbroek  * are met:
15*29492bb7SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
16*29492bb7SDavid van Moolenbroek  *    notice, this list of conditions, and the following disclaimer,
17*29492bb7SDavid van Moolenbroek  *    without modification.
18*29492bb7SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*29492bb7SDavid van Moolenbroek  *    substantially similar to the "NO WARRANTY" disclaimer below
20*29492bb7SDavid van Moolenbroek  *    ("Disclaimer") and any redistribution must be conditioned upon
21*29492bb7SDavid van Moolenbroek  *    including a substantially similar Disclaimer requirement for further
22*29492bb7SDavid van Moolenbroek  *    binary redistribution.
23*29492bb7SDavid van Moolenbroek  * 3. Neither the names of the above-listed copyright holders nor the names
24*29492bb7SDavid van Moolenbroek  *    of any contributors may be used to endorse or promote products derived
25*29492bb7SDavid van Moolenbroek  *    from this software without specific prior written permission.
26433d6423SLionel Sambuc  *
27*29492bb7SDavid van Moolenbroek  * Alternatively, this software may be distributed under the terms of the
28*29492bb7SDavid van Moolenbroek  * GNU General Public License ("GPL") version 2 as published by the Free
29*29492bb7SDavid van Moolenbroek  * Software Foundation.
30433d6423SLionel Sambuc  *
31*29492bb7SDavid van Moolenbroek  * NO WARRANTY
32*29492bb7SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*29492bb7SDavid van Moolenbroek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*29492bb7SDavid van Moolenbroek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*29492bb7SDavid van Moolenbroek  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*29492bb7SDavid van Moolenbroek  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*29492bb7SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*29492bb7SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*29492bb7SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*29492bb7SDavid van Moolenbroek  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*29492bb7SDavid van Moolenbroek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*29492bb7SDavid van Moolenbroek  * POSSIBILITY OF SUCH DAMAGES.
43*29492bb7SDavid van Moolenbroek  */
44433d6423SLionel Sambuc 
45*29492bb7SDavid van Moolenbroek #define EXPORT_ACPI_INTERFACES
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc #include "acpi.h"
48433d6423SLionel Sambuc #include "accommon.h"
49433d6423SLionel Sambuc #include "acnamesp.h"
50433d6423SLionel Sambuc #include "acinterp.h"
51433d6423SLionel Sambuc 
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc #define _COMPONENT          ACPI_NAMESPACE
54433d6423SLionel Sambuc         ACPI_MODULE_NAME    ("nsxfeval")
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc /* Local prototypes */
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc static void
59433d6423SLionel Sambuc AcpiNsResolveReferences (
60433d6423SLionel Sambuc     ACPI_EVALUATE_INFO      *Info);
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc /*******************************************************************************
64433d6423SLionel Sambuc  *
65433d6423SLionel Sambuc  * FUNCTION:    AcpiEvaluateObjectTyped
66433d6423SLionel Sambuc  *
67433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Object handle (optional)
68433d6423SLionel Sambuc  *              Pathname            - Object pathname (optional)
69433d6423SLionel Sambuc  *              ExternalParams      - List of parameters to pass to method,
70433d6423SLionel Sambuc  *                                    terminated by NULL. May be NULL
71433d6423SLionel Sambuc  *                                    if no parameters are being passed.
72433d6423SLionel Sambuc  *              ReturnBuffer        - Where to put method's return value (if
73433d6423SLionel Sambuc  *                                    any). If NULL, no value is returned.
74433d6423SLionel Sambuc  *              ReturnType          - Expected type of return object
75433d6423SLionel Sambuc  *
76433d6423SLionel Sambuc  * RETURN:      Status
77433d6423SLionel Sambuc  *
78433d6423SLionel Sambuc  * DESCRIPTION: Find and evaluate the given object, passing the given
79433d6423SLionel Sambuc  *              parameters if necessary. One of "Handle" or "Pathname" must
80433d6423SLionel Sambuc  *              be valid (non-null)
81433d6423SLionel Sambuc  *
82433d6423SLionel Sambuc  ******************************************************************************/
83433d6423SLionel Sambuc 
84433d6423SLionel Sambuc ACPI_STATUS
AcpiEvaluateObjectTyped(ACPI_HANDLE Handle,ACPI_STRING Pathname,ACPI_OBJECT_LIST * ExternalParams,ACPI_BUFFER * ReturnBuffer,ACPI_OBJECT_TYPE ReturnType)85433d6423SLionel Sambuc AcpiEvaluateObjectTyped (
86433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
87433d6423SLionel Sambuc     ACPI_STRING             Pathname,
88433d6423SLionel Sambuc     ACPI_OBJECT_LIST        *ExternalParams,
89433d6423SLionel Sambuc     ACPI_BUFFER             *ReturnBuffer,
90433d6423SLionel Sambuc     ACPI_OBJECT_TYPE        ReturnType)
91433d6423SLionel Sambuc {
92433d6423SLionel Sambuc     ACPI_STATUS             Status;
93*29492bb7SDavid van Moolenbroek     BOOLEAN                 FreeBufferOnError = FALSE;
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc 
96433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc 
99433d6423SLionel Sambuc     /* Return buffer must be valid */
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc     if (!ReturnBuffer)
102433d6423SLionel Sambuc     {
103433d6423SLionel Sambuc         return_ACPI_STATUS (AE_BAD_PARAMETER);
104433d6423SLionel Sambuc     }
105433d6423SLionel Sambuc 
106433d6423SLionel Sambuc     if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
107433d6423SLionel Sambuc     {
108*29492bb7SDavid van Moolenbroek         FreeBufferOnError = TRUE;
109433d6423SLionel Sambuc     }
110433d6423SLionel Sambuc 
111433d6423SLionel Sambuc     /* Evaluate the object */
112433d6423SLionel Sambuc 
113*29492bb7SDavid van Moolenbroek     Status = AcpiEvaluateObject (Handle, Pathname,
114*29492bb7SDavid van Moolenbroek         ExternalParams, ReturnBuffer);
115433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
116433d6423SLionel Sambuc     {
117433d6423SLionel Sambuc         return_ACPI_STATUS (Status);
118433d6423SLionel Sambuc     }
119433d6423SLionel Sambuc 
120433d6423SLionel Sambuc     /* Type ANY means "don't care" */
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc     if (ReturnType == ACPI_TYPE_ANY)
123433d6423SLionel Sambuc     {
124433d6423SLionel Sambuc         return_ACPI_STATUS (AE_OK);
125433d6423SLionel Sambuc     }
126433d6423SLionel Sambuc 
127433d6423SLionel Sambuc     if (ReturnBuffer->Length == 0)
128433d6423SLionel Sambuc     {
129433d6423SLionel Sambuc         /* Error because caller specifically asked for a return value */
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc         ACPI_ERROR ((AE_INFO, "No return value"));
132433d6423SLionel Sambuc         return_ACPI_STATUS (AE_NULL_OBJECT);
133433d6423SLionel Sambuc     }
134433d6423SLionel Sambuc 
135433d6423SLionel Sambuc     /* Examine the object type returned from EvaluateObject */
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc     if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
138433d6423SLionel Sambuc     {
139433d6423SLionel Sambuc         return_ACPI_STATUS (AE_OK);
140433d6423SLionel Sambuc     }
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc     /* Return object type does not match requested type */
143433d6423SLionel Sambuc 
144433d6423SLionel Sambuc     ACPI_ERROR ((AE_INFO,
145433d6423SLionel Sambuc         "Incorrect return type [%s] requested [%s]",
146433d6423SLionel Sambuc         AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
147433d6423SLionel Sambuc         AcpiUtGetTypeName (ReturnType)));
148433d6423SLionel Sambuc 
149*29492bb7SDavid van Moolenbroek     if (FreeBufferOnError)
150433d6423SLionel Sambuc     {
151*29492bb7SDavid van Moolenbroek         /*
152*29492bb7SDavid van Moolenbroek          * Free a buffer created via ACPI_ALLOCATE_BUFFER.
153*29492bb7SDavid van Moolenbroek          * Note: We use AcpiOsFree here because AcpiOsAllocate was used
154*29492bb7SDavid van Moolenbroek          * to allocate the buffer. This purposefully bypasses the
155*29492bb7SDavid van Moolenbroek          * (optionally enabled) allocation tracking mechanism since we
156*29492bb7SDavid van Moolenbroek          * only want to track internal allocations.
157*29492bb7SDavid van Moolenbroek          */
158433d6423SLionel Sambuc         AcpiOsFree (ReturnBuffer->Pointer);
159433d6423SLionel Sambuc         ReturnBuffer->Pointer = NULL;
160433d6423SLionel Sambuc     }
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc     ReturnBuffer->Length = 0;
163433d6423SLionel Sambuc     return_ACPI_STATUS (AE_TYPE);
164433d6423SLionel Sambuc }
165433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiEvaluateObjectTyped)166433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
167433d6423SLionel Sambuc 
168433d6423SLionel Sambuc 
169433d6423SLionel Sambuc /*******************************************************************************
170433d6423SLionel Sambuc  *
171433d6423SLionel Sambuc  * FUNCTION:    AcpiEvaluateObject
172433d6423SLionel Sambuc  *
173433d6423SLionel Sambuc  * PARAMETERS:  Handle              - Object handle (optional)
174433d6423SLionel Sambuc  *              Pathname            - Object pathname (optional)
175433d6423SLionel Sambuc  *              ExternalParams      - List of parameters to pass to method,
176433d6423SLionel Sambuc  *                                    terminated by NULL. May be NULL
177433d6423SLionel Sambuc  *                                    if no parameters are being passed.
178433d6423SLionel Sambuc  *              ReturnBuffer        - Where to put method's return value (if
179433d6423SLionel Sambuc  *                                    any). If NULL, no value is returned.
180433d6423SLionel Sambuc  *
181433d6423SLionel Sambuc  * RETURN:      Status
182433d6423SLionel Sambuc  *
183433d6423SLionel Sambuc  * DESCRIPTION: Find and evaluate the given object, passing the given
184433d6423SLionel Sambuc  *              parameters if necessary. One of "Handle" or "Pathname" must
185433d6423SLionel Sambuc  *              be valid (non-null)
186433d6423SLionel Sambuc  *
187433d6423SLionel Sambuc  ******************************************************************************/
188433d6423SLionel Sambuc 
189433d6423SLionel Sambuc ACPI_STATUS
190433d6423SLionel Sambuc AcpiEvaluateObject (
191433d6423SLionel Sambuc     ACPI_HANDLE             Handle,
192433d6423SLionel Sambuc     ACPI_STRING             Pathname,
193433d6423SLionel Sambuc     ACPI_OBJECT_LIST        *ExternalParams,
194433d6423SLionel Sambuc     ACPI_BUFFER             *ReturnBuffer)
195433d6423SLionel Sambuc {
196433d6423SLionel Sambuc     ACPI_STATUS             Status;
197433d6423SLionel Sambuc     ACPI_EVALUATE_INFO      *Info;
198433d6423SLionel Sambuc     ACPI_SIZE               BufferSpaceNeeded;
199433d6423SLionel Sambuc     UINT32                  i;
200433d6423SLionel Sambuc 
201433d6423SLionel Sambuc 
202433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
203433d6423SLionel Sambuc 
204433d6423SLionel Sambuc 
205433d6423SLionel Sambuc     /* Allocate and initialize the evaluation information block */
206433d6423SLionel Sambuc 
207433d6423SLionel Sambuc     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
208433d6423SLionel Sambuc     if (!Info)
209433d6423SLionel Sambuc     {
210433d6423SLionel Sambuc         return_ACPI_STATUS (AE_NO_MEMORY);
211433d6423SLionel Sambuc     }
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc     /* Convert and validate the device handle */
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc     Info->PrefixNode = AcpiNsValidateHandle (Handle);
216433d6423SLionel Sambuc     if (!Info->PrefixNode)
217433d6423SLionel Sambuc     {
218433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
219433d6423SLionel Sambuc         goto Cleanup;
220433d6423SLionel Sambuc     }
221433d6423SLionel Sambuc 
222433d6423SLionel Sambuc     /*
223*29492bb7SDavid van Moolenbroek      * Get the actual namespace node for the target object.
224*29492bb7SDavid van Moolenbroek      * Handles these cases:
225*29492bb7SDavid van Moolenbroek      *
226*29492bb7SDavid van Moolenbroek      * 1) Null node, valid pathname from root (absolute path)
227*29492bb7SDavid van Moolenbroek      * 2) Node and valid pathname (path relative to Node)
228*29492bb7SDavid van Moolenbroek      * 3) Node, Null pathname
229433d6423SLionel Sambuc      */
230433d6423SLionel Sambuc     if ((Pathname) &&
231*29492bb7SDavid van Moolenbroek         (ACPI_IS_ROOT_PREFIX (Pathname[0])))
232433d6423SLionel Sambuc     {
233433d6423SLionel Sambuc         /* The path is fully qualified, just evaluate by name */
234433d6423SLionel Sambuc 
235433d6423SLionel Sambuc         Info->PrefixNode = NULL;
236433d6423SLionel Sambuc     }
237433d6423SLionel Sambuc     else if (!Handle)
238433d6423SLionel Sambuc     {
239433d6423SLionel Sambuc         /*
240433d6423SLionel Sambuc          * A handle is optional iff a fully qualified pathname is specified.
241433d6423SLionel Sambuc          * Since we've already handled fully qualified names above, this is
242*29492bb7SDavid van Moolenbroek          * an error.
243433d6423SLionel Sambuc          */
244433d6423SLionel Sambuc         if (!Pathname)
245433d6423SLionel Sambuc         {
246433d6423SLionel Sambuc             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
247433d6423SLionel Sambuc                 "Both Handle and Pathname are NULL"));
248433d6423SLionel Sambuc         }
249433d6423SLionel Sambuc         else
250433d6423SLionel Sambuc         {
251433d6423SLionel Sambuc             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
252433d6423SLionel Sambuc                 "Null Handle with relative pathname [%s]", Pathname));
253433d6423SLionel Sambuc         }
254433d6423SLionel Sambuc 
255433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
256*29492bb7SDavid van Moolenbroek         goto Cleanup;
257433d6423SLionel Sambuc     }
258*29492bb7SDavid van Moolenbroek 
259*29492bb7SDavid van Moolenbroek     Info->RelativePathname = Pathname;
260*29492bb7SDavid van Moolenbroek 
261*29492bb7SDavid van Moolenbroek     /*
262*29492bb7SDavid van Moolenbroek      * Convert all external objects passed as arguments to the
263*29492bb7SDavid van Moolenbroek      * internal version(s).
264*29492bb7SDavid van Moolenbroek      */
265*29492bb7SDavid van Moolenbroek     if (ExternalParams && ExternalParams->Count)
266433d6423SLionel Sambuc     {
267*29492bb7SDavid van Moolenbroek         Info->ParamCount = (UINT16) ExternalParams->Count;
268*29492bb7SDavid van Moolenbroek 
269*29492bb7SDavid van Moolenbroek         /* Warn on impossible argument count */
270*29492bb7SDavid van Moolenbroek 
271*29492bb7SDavid van Moolenbroek         if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
272*29492bb7SDavid van Moolenbroek         {
273*29492bb7SDavid van Moolenbroek             ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
274*29492bb7SDavid van Moolenbroek                 "Excess arguments (%u) - using only %u",
275*29492bb7SDavid van Moolenbroek                 Info->ParamCount, ACPI_METHOD_NUM_ARGS));
276*29492bb7SDavid van Moolenbroek 
277*29492bb7SDavid van Moolenbroek             Info->ParamCount = ACPI_METHOD_NUM_ARGS;
278*29492bb7SDavid van Moolenbroek         }
279*29492bb7SDavid van Moolenbroek 
280*29492bb7SDavid van Moolenbroek         /*
281*29492bb7SDavid van Moolenbroek          * Allocate a new parameter block for the internal objects
282*29492bb7SDavid van Moolenbroek          * Add 1 to count to allow for null terminated internal list
283*29492bb7SDavid van Moolenbroek          */
284*29492bb7SDavid van Moolenbroek         Info->Parameters = ACPI_ALLOCATE_ZEROED (
285*29492bb7SDavid van Moolenbroek             ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
286*29492bb7SDavid van Moolenbroek         if (!Info->Parameters)
287*29492bb7SDavid van Moolenbroek         {
288*29492bb7SDavid van Moolenbroek             Status = AE_NO_MEMORY;
289*29492bb7SDavid van Moolenbroek             goto Cleanup;
290*29492bb7SDavid van Moolenbroek         }
291*29492bb7SDavid van Moolenbroek 
292*29492bb7SDavid van Moolenbroek         /* Convert each external object in the list to an internal object */
293*29492bb7SDavid van Moolenbroek 
294*29492bb7SDavid van Moolenbroek         for (i = 0; i < Info->ParamCount; i++)
295*29492bb7SDavid van Moolenbroek         {
296*29492bb7SDavid van Moolenbroek             Status = AcpiUtCopyEobjectToIobject (
297*29492bb7SDavid van Moolenbroek                 &ExternalParams->Pointer[i], &Info->Parameters[i]);
298*29492bb7SDavid van Moolenbroek             if (ACPI_FAILURE (Status))
299*29492bb7SDavid van Moolenbroek             {
300*29492bb7SDavid van Moolenbroek                 goto Cleanup;
301*29492bb7SDavid van Moolenbroek             }
302*29492bb7SDavid van Moolenbroek         }
303*29492bb7SDavid van Moolenbroek 
304*29492bb7SDavid van Moolenbroek         Info->Parameters[Info->ParamCount] = NULL;
305*29492bb7SDavid van Moolenbroek     }
306*29492bb7SDavid van Moolenbroek 
307*29492bb7SDavid van Moolenbroek 
308*29492bb7SDavid van Moolenbroek #if 0
309*29492bb7SDavid van Moolenbroek 
310*29492bb7SDavid van Moolenbroek     /*
311*29492bb7SDavid van Moolenbroek      * Begin incoming argument count analysis. Check for too few args
312*29492bb7SDavid van Moolenbroek      * and too many args.
313*29492bb7SDavid van Moolenbroek      */
314*29492bb7SDavid van Moolenbroek 
315*29492bb7SDavid van Moolenbroek     switch (AcpiNsGetType (Info->Node))
316*29492bb7SDavid van Moolenbroek     {
317*29492bb7SDavid van Moolenbroek     case ACPI_TYPE_METHOD:
318*29492bb7SDavid van Moolenbroek 
319*29492bb7SDavid van Moolenbroek         /* Check incoming argument count against the method definition */
320*29492bb7SDavid van Moolenbroek 
321*29492bb7SDavid van Moolenbroek         if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
322*29492bb7SDavid van Moolenbroek         {
323*29492bb7SDavid van Moolenbroek             ACPI_ERROR ((AE_INFO,
324*29492bb7SDavid van Moolenbroek                 "Insufficient arguments (%u) - %u are required",
325*29492bb7SDavid van Moolenbroek                 Info->ParamCount,
326*29492bb7SDavid van Moolenbroek                 Info->ObjDesc->Method.ParamCount));
327*29492bb7SDavid van Moolenbroek 
328*29492bb7SDavid van Moolenbroek             Status = AE_MISSING_ARGUMENTS;
329*29492bb7SDavid van Moolenbroek             goto Cleanup;
330*29492bb7SDavid van Moolenbroek         }
331*29492bb7SDavid van Moolenbroek 
332*29492bb7SDavid van Moolenbroek         else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
333*29492bb7SDavid van Moolenbroek         {
334*29492bb7SDavid van Moolenbroek             ACPI_WARNING ((AE_INFO,
335*29492bb7SDavid van Moolenbroek                 "Excess arguments (%u) - only %u are required",
336*29492bb7SDavid van Moolenbroek                 Info->ParamCount,
337*29492bb7SDavid van Moolenbroek                 Info->ObjDesc->Method.ParamCount));
338*29492bb7SDavid van Moolenbroek 
339*29492bb7SDavid van Moolenbroek             /* Just pass the required number of arguments */
340*29492bb7SDavid van Moolenbroek 
341*29492bb7SDavid van Moolenbroek             Info->ParamCount = Info->ObjDesc->Method.ParamCount;
342*29492bb7SDavid van Moolenbroek         }
343*29492bb7SDavid van Moolenbroek 
344*29492bb7SDavid van Moolenbroek         /*
345*29492bb7SDavid van Moolenbroek          * Any incoming external objects to be passed as arguments to the
346*29492bb7SDavid van Moolenbroek          * method must be converted to internal objects
347*29492bb7SDavid van Moolenbroek          */
348*29492bb7SDavid van Moolenbroek         if (Info->ParamCount)
349*29492bb7SDavid van Moolenbroek         {
350*29492bb7SDavid van Moolenbroek             /*
351*29492bb7SDavid van Moolenbroek              * Allocate a new parameter block for the internal objects
352*29492bb7SDavid van Moolenbroek              * Add 1 to count to allow for null terminated internal list
353*29492bb7SDavid van Moolenbroek              */
354*29492bb7SDavid van Moolenbroek             Info->Parameters = ACPI_ALLOCATE_ZEROED (
355*29492bb7SDavid van Moolenbroek                 ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
356*29492bb7SDavid van Moolenbroek             if (!Info->Parameters)
357*29492bb7SDavid van Moolenbroek             {
358*29492bb7SDavid van Moolenbroek                 Status = AE_NO_MEMORY;
359*29492bb7SDavid van Moolenbroek                 goto Cleanup;
360*29492bb7SDavid van Moolenbroek             }
361*29492bb7SDavid van Moolenbroek 
362*29492bb7SDavid van Moolenbroek             /* Convert each external object in the list to an internal object */
363*29492bb7SDavid van Moolenbroek 
364*29492bb7SDavid van Moolenbroek             for (i = 0; i < Info->ParamCount; i++)
365*29492bb7SDavid van Moolenbroek             {
366*29492bb7SDavid van Moolenbroek                 Status = AcpiUtCopyEobjectToIobject (
367*29492bb7SDavid van Moolenbroek                     &ExternalParams->Pointer[i], &Info->Parameters[i]);
368*29492bb7SDavid van Moolenbroek                 if (ACPI_FAILURE (Status))
369*29492bb7SDavid van Moolenbroek                 {
370*29492bb7SDavid van Moolenbroek                     goto Cleanup;
371*29492bb7SDavid van Moolenbroek                 }
372*29492bb7SDavid van Moolenbroek             }
373*29492bb7SDavid van Moolenbroek 
374*29492bb7SDavid van Moolenbroek             Info->Parameters[Info->ParamCount] = NULL;
375*29492bb7SDavid van Moolenbroek         }
376*29492bb7SDavid van Moolenbroek         break;
377*29492bb7SDavid van Moolenbroek 
378*29492bb7SDavid van Moolenbroek     default:
379*29492bb7SDavid van Moolenbroek 
380*29492bb7SDavid van Moolenbroek         /* Warn if arguments passed to an object that is not a method */
381*29492bb7SDavid van Moolenbroek 
382*29492bb7SDavid van Moolenbroek         if (Info->ParamCount)
383*29492bb7SDavid van Moolenbroek         {
384*29492bb7SDavid van Moolenbroek             ACPI_WARNING ((AE_INFO,
385*29492bb7SDavid van Moolenbroek                 "%u arguments were passed to a non-method ACPI object",
386*29492bb7SDavid van Moolenbroek                 Info->ParamCount));
387*29492bb7SDavid van Moolenbroek         }
388*29492bb7SDavid van Moolenbroek         break;
389*29492bb7SDavid van Moolenbroek     }
390*29492bb7SDavid van Moolenbroek 
391*29492bb7SDavid van Moolenbroek #endif
392*29492bb7SDavid van Moolenbroek 
393*29492bb7SDavid van Moolenbroek 
394*29492bb7SDavid van Moolenbroek     /* Now we can evaluate the object */
395433d6423SLionel Sambuc 
396433d6423SLionel Sambuc     Status = AcpiNsEvaluate (Info);
397433d6423SLionel Sambuc 
398433d6423SLionel Sambuc     /*
399433d6423SLionel Sambuc      * If we are expecting a return value, and all went well above,
400433d6423SLionel Sambuc      * copy the return value to an external object.
401433d6423SLionel Sambuc      */
402433d6423SLionel Sambuc     if (ReturnBuffer)
403433d6423SLionel Sambuc     {
404433d6423SLionel Sambuc         if (!Info->ReturnObject)
405433d6423SLionel Sambuc         {
406433d6423SLionel Sambuc             ReturnBuffer->Length = 0;
407433d6423SLionel Sambuc         }
408433d6423SLionel Sambuc         else
409433d6423SLionel Sambuc         {
410433d6423SLionel Sambuc             if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
411433d6423SLionel Sambuc                 ACPI_DESC_TYPE_NAMED)
412433d6423SLionel Sambuc             {
413433d6423SLionel Sambuc                 /*
414433d6423SLionel Sambuc                  * If we received a NS Node as a return object, this means that
415433d6423SLionel Sambuc                  * the object we are evaluating has nothing interesting to
416433d6423SLionel Sambuc                  * return (such as a mutex, etc.)  We return an error because
417433d6423SLionel Sambuc                  * these types are essentially unsupported by this interface.
418433d6423SLionel Sambuc                  * We don't check up front because this makes it easier to add
419433d6423SLionel Sambuc                  * support for various types at a later date if necessary.
420433d6423SLionel Sambuc                  */
421433d6423SLionel Sambuc                 Status = AE_TYPE;
422433d6423SLionel Sambuc                 Info->ReturnObject = NULL;   /* No need to delete a NS Node */
423433d6423SLionel Sambuc                 ReturnBuffer->Length = 0;
424433d6423SLionel Sambuc             }
425433d6423SLionel Sambuc 
426433d6423SLionel Sambuc             if (ACPI_SUCCESS (Status))
427433d6423SLionel Sambuc             {
428433d6423SLionel Sambuc                 /* Dereference Index and RefOf references */
429433d6423SLionel Sambuc 
430433d6423SLionel Sambuc                 AcpiNsResolveReferences (Info);
431433d6423SLionel Sambuc 
432433d6423SLionel Sambuc                 /* Get the size of the returned object */
433433d6423SLionel Sambuc 
434433d6423SLionel Sambuc                 Status = AcpiUtGetObjectSize (Info->ReturnObject,
435433d6423SLionel Sambuc                             &BufferSpaceNeeded);
436433d6423SLionel Sambuc                 if (ACPI_SUCCESS (Status))
437433d6423SLionel Sambuc                 {
438433d6423SLionel Sambuc                     /* Validate/Allocate/Clear caller buffer */
439433d6423SLionel Sambuc 
440433d6423SLionel Sambuc                     Status = AcpiUtInitializeBuffer (ReturnBuffer,
441433d6423SLionel Sambuc                                 BufferSpaceNeeded);
442433d6423SLionel Sambuc                     if (ACPI_FAILURE (Status))
443433d6423SLionel Sambuc                     {
444433d6423SLionel Sambuc                         /*
445433d6423SLionel Sambuc                          * Caller's buffer is too small or a new one can't
446433d6423SLionel Sambuc                          * be allocated
447433d6423SLionel Sambuc                          */
448433d6423SLionel Sambuc                         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
449433d6423SLionel Sambuc                             "Needed buffer size %X, %s\n",
450433d6423SLionel Sambuc                             (UINT32) BufferSpaceNeeded,
451433d6423SLionel Sambuc                             AcpiFormatException (Status)));
452433d6423SLionel Sambuc                     }
453433d6423SLionel Sambuc                     else
454433d6423SLionel Sambuc                     {
455433d6423SLionel Sambuc                         /* We have enough space for the object, build it */
456433d6423SLionel Sambuc 
457433d6423SLionel Sambuc                         Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
458433d6423SLionel Sambuc                                     ReturnBuffer);
459433d6423SLionel Sambuc                     }
460433d6423SLionel Sambuc                 }
461433d6423SLionel Sambuc             }
462433d6423SLionel Sambuc         }
463433d6423SLionel Sambuc     }
464433d6423SLionel Sambuc 
465433d6423SLionel Sambuc     if (Info->ReturnObject)
466433d6423SLionel Sambuc     {
467433d6423SLionel Sambuc         /*
468433d6423SLionel Sambuc          * Delete the internal return object. NOTE: Interpreter must be
469433d6423SLionel Sambuc          * locked to avoid race condition.
470433d6423SLionel Sambuc          */
471433d6423SLionel Sambuc         AcpiExEnterInterpreter ();
472433d6423SLionel Sambuc 
473433d6423SLionel Sambuc         /* Remove one reference on the return object (should delete it) */
474433d6423SLionel Sambuc 
475433d6423SLionel Sambuc         AcpiUtRemoveReference (Info->ReturnObject);
476433d6423SLionel Sambuc         AcpiExExitInterpreter ();
477433d6423SLionel Sambuc     }
478433d6423SLionel Sambuc 
479433d6423SLionel Sambuc 
480433d6423SLionel Sambuc Cleanup:
481433d6423SLionel Sambuc 
482433d6423SLionel Sambuc     /* Free the input parameter list (if we created one) */
483433d6423SLionel Sambuc 
484433d6423SLionel Sambuc     if (Info->Parameters)
485433d6423SLionel Sambuc     {
486433d6423SLionel Sambuc         /* Free the allocated parameter block */
487433d6423SLionel Sambuc 
488433d6423SLionel Sambuc         AcpiUtDeleteInternalObjectList (Info->Parameters);
489433d6423SLionel Sambuc     }
490433d6423SLionel Sambuc 
491433d6423SLionel Sambuc     ACPI_FREE (Info);
492433d6423SLionel Sambuc     return_ACPI_STATUS (Status);
493433d6423SLionel Sambuc }
494433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiEvaluateObject)495433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
496433d6423SLionel Sambuc 
497433d6423SLionel Sambuc 
498433d6423SLionel Sambuc /*******************************************************************************
499433d6423SLionel Sambuc  *
500433d6423SLionel Sambuc  * FUNCTION:    AcpiNsResolveReferences
501433d6423SLionel Sambuc  *
502433d6423SLionel Sambuc  * PARAMETERS:  Info                    - Evaluation info block
503433d6423SLionel Sambuc  *
504433d6423SLionel Sambuc  * RETURN:      Info->ReturnObject is replaced with the dereferenced object
505433d6423SLionel Sambuc  *
506433d6423SLionel Sambuc  * DESCRIPTION: Dereference certain reference objects. Called before an
507433d6423SLionel Sambuc  *              internal return object is converted to an external ACPI_OBJECT.
508433d6423SLionel Sambuc  *
509433d6423SLionel Sambuc  * Performs an automatic dereference of Index and RefOf reference objects.
510433d6423SLionel Sambuc  * These reference objects are not supported by the ACPI_OBJECT, so this is a
511433d6423SLionel Sambuc  * last resort effort to return something useful. Also, provides compatibility
512433d6423SLionel Sambuc  * with other ACPI implementations.
513433d6423SLionel Sambuc  *
514433d6423SLionel Sambuc  * NOTE: does not handle references within returned package objects or nested
515433d6423SLionel Sambuc  * references, but this support could be added later if found to be necessary.
516433d6423SLionel Sambuc  *
517433d6423SLionel Sambuc  ******************************************************************************/
518433d6423SLionel Sambuc 
519433d6423SLionel Sambuc static void
520433d6423SLionel Sambuc AcpiNsResolveReferences (
521433d6423SLionel Sambuc     ACPI_EVALUATE_INFO      *Info)
522433d6423SLionel Sambuc {
523433d6423SLionel Sambuc     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
524433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
525433d6423SLionel Sambuc 
526433d6423SLionel Sambuc 
527433d6423SLionel Sambuc     /* We are interested in reference objects only */
528433d6423SLionel Sambuc 
529433d6423SLionel Sambuc     if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
530433d6423SLionel Sambuc     {
531433d6423SLionel Sambuc         return;
532433d6423SLionel Sambuc     }
533433d6423SLionel Sambuc 
534433d6423SLionel Sambuc     /*
535433d6423SLionel Sambuc      * Two types of references are supported - those created by Index and
536433d6423SLionel Sambuc      * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
537433d6423SLionel Sambuc      * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
538433d6423SLionel Sambuc      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
539433d6423SLionel Sambuc      * an ACPI_OBJECT.
540433d6423SLionel Sambuc      */
541433d6423SLionel Sambuc     switch (Info->ReturnObject->Reference.Class)
542433d6423SLionel Sambuc     {
543433d6423SLionel Sambuc     case ACPI_REFCLASS_INDEX:
544433d6423SLionel Sambuc 
545433d6423SLionel Sambuc         ObjDesc = *(Info->ReturnObject->Reference.Where);
546433d6423SLionel Sambuc         break;
547433d6423SLionel Sambuc 
548433d6423SLionel Sambuc     case ACPI_REFCLASS_REFOF:
549433d6423SLionel Sambuc 
550433d6423SLionel Sambuc         Node = Info->ReturnObject->Reference.Object;
551433d6423SLionel Sambuc         if (Node)
552433d6423SLionel Sambuc         {
553433d6423SLionel Sambuc             ObjDesc = Node->Object;
554433d6423SLionel Sambuc         }
555433d6423SLionel Sambuc         break;
556433d6423SLionel Sambuc 
557433d6423SLionel Sambuc     default:
558*29492bb7SDavid van Moolenbroek 
559433d6423SLionel Sambuc         return;
560433d6423SLionel Sambuc     }
561433d6423SLionel Sambuc 
562433d6423SLionel Sambuc     /* Replace the existing reference object */
563433d6423SLionel Sambuc 
564433d6423SLionel Sambuc     if (ObjDesc)
565433d6423SLionel Sambuc     {
566433d6423SLionel Sambuc         AcpiUtAddReference (ObjDesc);
567433d6423SLionel Sambuc         AcpiUtRemoveReference (Info->ReturnObject);
568433d6423SLionel Sambuc         Info->ReturnObject = ObjDesc;
569433d6423SLionel Sambuc     }
570433d6423SLionel Sambuc 
571433d6423SLionel Sambuc     return;
572433d6423SLionel Sambuc }
573433d6423SLionel Sambuc 
574433d6423SLionel Sambuc 
575433d6423SLionel Sambuc /*******************************************************************************
576433d6423SLionel Sambuc  *
577433d6423SLionel Sambuc  * FUNCTION:    AcpiWalkNamespace
578433d6423SLionel Sambuc  *
579433d6423SLionel Sambuc  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
580433d6423SLionel Sambuc  *              StartObject         - Handle in namespace where search begins
581433d6423SLionel Sambuc  *              MaxDepth            - Depth to which search is to reach
582*29492bb7SDavid van Moolenbroek  *              DescendingCallback  - Called during tree descent
583433d6423SLionel Sambuc  *                                    when an object of "Type" is found
584*29492bb7SDavid van Moolenbroek  *              AscendingCallback   - Called during tree ascent
585433d6423SLionel Sambuc  *                                    when an object of "Type" is found
586433d6423SLionel Sambuc  *              Context             - Passed to user function(s) above
587433d6423SLionel Sambuc  *              ReturnValue         - Location where return value of
588433d6423SLionel Sambuc  *                                    UserFunction is put if terminated early
589433d6423SLionel Sambuc  *
590433d6423SLionel Sambuc  * RETURNS      Return value from the UserFunction if terminated early.
591433d6423SLionel Sambuc  *              Otherwise, returns NULL.
592433d6423SLionel Sambuc  *
593433d6423SLionel Sambuc  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
594433d6423SLionel Sambuc  *              starting (and ending) at the object specified by StartHandle.
595433d6423SLionel Sambuc  *              The callback function is called whenever an object that matches
596433d6423SLionel Sambuc  *              the type parameter is found. If the callback function returns
597433d6423SLionel Sambuc  *              a non-zero value, the search is terminated immediately and this
598433d6423SLionel Sambuc  *              value is returned to the caller.
599433d6423SLionel Sambuc  *
600433d6423SLionel Sambuc  *              The point of this procedure is to provide a generic namespace
601433d6423SLionel Sambuc  *              walk routine that can be called from multiple places to
602433d6423SLionel Sambuc  *              provide multiple services; the callback function(s) can be
603433d6423SLionel Sambuc  *              tailored to each task, whether it is a print function,
604433d6423SLionel Sambuc  *              a compare function, etc.
605433d6423SLionel Sambuc  *
606433d6423SLionel Sambuc  ******************************************************************************/
607433d6423SLionel Sambuc 
608433d6423SLionel Sambuc ACPI_STATUS
AcpiWalkNamespace(ACPI_OBJECT_TYPE Type,ACPI_HANDLE StartObject,UINT32 MaxDepth,ACPI_WALK_CALLBACK DescendingCallback,ACPI_WALK_CALLBACK AscendingCallback,void * Context,void ** ReturnValue)609433d6423SLionel Sambuc AcpiWalkNamespace (
610433d6423SLionel Sambuc     ACPI_OBJECT_TYPE        Type,
611433d6423SLionel Sambuc     ACPI_HANDLE             StartObject,
612433d6423SLionel Sambuc     UINT32                  MaxDepth,
613*29492bb7SDavid van Moolenbroek     ACPI_WALK_CALLBACK      DescendingCallback,
614*29492bb7SDavid van Moolenbroek     ACPI_WALK_CALLBACK      AscendingCallback,
615433d6423SLionel Sambuc     void                    *Context,
616433d6423SLionel Sambuc     void                    **ReturnValue)
617433d6423SLionel Sambuc {
618433d6423SLionel Sambuc     ACPI_STATUS             Status;
619433d6423SLionel Sambuc 
620433d6423SLionel Sambuc 
621433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
622433d6423SLionel Sambuc 
623433d6423SLionel Sambuc 
624433d6423SLionel Sambuc     /* Parameter validation */
625433d6423SLionel Sambuc 
626433d6423SLionel Sambuc     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
627433d6423SLionel Sambuc         (!MaxDepth)                  ||
628*29492bb7SDavid van Moolenbroek         (!DescendingCallback && !AscendingCallback))
629433d6423SLionel Sambuc     {
630433d6423SLionel Sambuc         return_ACPI_STATUS (AE_BAD_PARAMETER);
631433d6423SLionel Sambuc     }
632433d6423SLionel Sambuc 
633433d6423SLionel Sambuc     /*
634433d6423SLionel Sambuc      * Need to acquire the namespace reader lock to prevent interference
635433d6423SLionel Sambuc      * with any concurrent table unloads (which causes the deletion of
636433d6423SLionel Sambuc      * namespace objects). We cannot allow the deletion of a namespace node
637433d6423SLionel Sambuc      * while the user function is using it. The exception to this are the
638433d6423SLionel Sambuc      * nodes created and deleted during control method execution -- these
639433d6423SLionel Sambuc      * nodes are marked as temporary nodes and are ignored by the namespace
640433d6423SLionel Sambuc      * walk. Thus, control methods can be executed while holding the
641433d6423SLionel Sambuc      * namespace deletion lock (and the user function can execute control
642433d6423SLionel Sambuc      * methods.)
643433d6423SLionel Sambuc      */
644433d6423SLionel Sambuc     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
645433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
646433d6423SLionel Sambuc     {
647*29492bb7SDavid van Moolenbroek         return_ACPI_STATUS (Status);
648433d6423SLionel Sambuc     }
649433d6423SLionel Sambuc 
650433d6423SLionel Sambuc     /*
651433d6423SLionel Sambuc      * Lock the namespace around the walk. The namespace will be
652433d6423SLionel Sambuc      * unlocked/locked around each call to the user function - since the user
653433d6423SLionel Sambuc      * function must be allowed to make ACPICA calls itself (for example, it
654433d6423SLionel Sambuc      * will typically execute control methods during device enumeration.)
655433d6423SLionel Sambuc      */
656433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
657433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
658433d6423SLionel Sambuc     {
659433d6423SLionel Sambuc         goto UnlockAndExit;
660433d6423SLionel Sambuc     }
661433d6423SLionel Sambuc 
662*29492bb7SDavid van Moolenbroek     /* Now we can validate the starting node */
663433d6423SLionel Sambuc 
664*29492bb7SDavid van Moolenbroek     if (!AcpiNsValidateHandle (StartObject))
665*29492bb7SDavid van Moolenbroek     {
666*29492bb7SDavid van Moolenbroek         Status = AE_BAD_PARAMETER;
667*29492bb7SDavid van Moolenbroek         goto UnlockAndExit2;
668*29492bb7SDavid van Moolenbroek     }
669*29492bb7SDavid van Moolenbroek 
670*29492bb7SDavid van Moolenbroek     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
671*29492bb7SDavid van Moolenbroek                 ACPI_NS_WALK_UNLOCK, DescendingCallback,
672*29492bb7SDavid van Moolenbroek                 AscendingCallback, Context, ReturnValue);
673*29492bb7SDavid van Moolenbroek 
674*29492bb7SDavid van Moolenbroek UnlockAndExit2:
675433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
676433d6423SLionel Sambuc 
677433d6423SLionel Sambuc UnlockAndExit:
678433d6423SLionel Sambuc     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
679433d6423SLionel Sambuc     return_ACPI_STATUS (Status);
680433d6423SLionel Sambuc }
681433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiWalkNamespace)682433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
683433d6423SLionel Sambuc 
684433d6423SLionel Sambuc 
685433d6423SLionel Sambuc /*******************************************************************************
686433d6423SLionel Sambuc  *
687433d6423SLionel Sambuc  * FUNCTION:    AcpiNsGetDeviceCallback
688433d6423SLionel Sambuc  *
689433d6423SLionel Sambuc  * PARAMETERS:  Callback from AcpiGetDevice
690433d6423SLionel Sambuc  *
691433d6423SLionel Sambuc  * RETURN:      Status
692433d6423SLionel Sambuc  *
693433d6423SLionel Sambuc  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
694433d6423SLionel Sambuc  *              present devices, or if they specified a HID, it filters based
695433d6423SLionel Sambuc  *              on that.
696433d6423SLionel Sambuc  *
697433d6423SLionel Sambuc  ******************************************************************************/
698433d6423SLionel Sambuc 
699433d6423SLionel Sambuc static ACPI_STATUS
700433d6423SLionel Sambuc AcpiNsGetDeviceCallback (
701433d6423SLionel Sambuc     ACPI_HANDLE             ObjHandle,
702433d6423SLionel Sambuc     UINT32                  NestingLevel,
703433d6423SLionel Sambuc     void                    *Context,
704433d6423SLionel Sambuc     void                    **ReturnValue)
705433d6423SLionel Sambuc {
706433d6423SLionel Sambuc     ACPI_GET_DEVICES_INFO   *Info = Context;
707433d6423SLionel Sambuc     ACPI_STATUS             Status;
708433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
709433d6423SLionel Sambuc     UINT32                  Flags;
710*29492bb7SDavid van Moolenbroek     ACPI_PNP_DEVICE_ID      *Hid;
711*29492bb7SDavid van Moolenbroek     ACPI_PNP_DEVICE_ID_LIST *Cid;
712433d6423SLionel Sambuc     UINT32                  i;
713433d6423SLionel Sambuc     BOOLEAN                 Found;
714433d6423SLionel Sambuc     int                     NoMatch;
715433d6423SLionel Sambuc 
716433d6423SLionel Sambuc 
717433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
718433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
719433d6423SLionel Sambuc     {
720433d6423SLionel Sambuc         return (Status);
721433d6423SLionel Sambuc     }
722433d6423SLionel Sambuc 
723433d6423SLionel Sambuc     Node = AcpiNsValidateHandle (ObjHandle);
724433d6423SLionel Sambuc     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
725433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
726433d6423SLionel Sambuc     {
727433d6423SLionel Sambuc         return (Status);
728433d6423SLionel Sambuc     }
729433d6423SLionel Sambuc 
730433d6423SLionel Sambuc     if (!Node)
731433d6423SLionel Sambuc     {
732433d6423SLionel Sambuc         return (AE_BAD_PARAMETER);
733433d6423SLionel Sambuc     }
734433d6423SLionel Sambuc 
735433d6423SLionel Sambuc     /*
736433d6423SLionel Sambuc      * First, filter based on the device HID and CID.
737433d6423SLionel Sambuc      *
738433d6423SLionel Sambuc      * 01/2010: For this case where a specific HID is requested, we don't
739433d6423SLionel Sambuc      * want to run _STA until we have an actual HID match. Thus, we will
740433d6423SLionel Sambuc      * not unnecessarily execute _STA on devices for which the caller
741433d6423SLionel Sambuc      * doesn't care about. Previously, _STA was executed unconditionally
742433d6423SLionel Sambuc      * on all devices found here.
743433d6423SLionel Sambuc      *
744433d6423SLionel Sambuc      * A side-effect of this change is that now we will continue to search
745433d6423SLionel Sambuc      * for a matching HID even under device trees where the parent device
746433d6423SLionel Sambuc      * would have returned a _STA that indicates it is not present or
747433d6423SLionel Sambuc      * not functioning (thus aborting the search on that branch).
748433d6423SLionel Sambuc      */
749433d6423SLionel Sambuc     if (Info->Hid != NULL)
750433d6423SLionel Sambuc     {
751433d6423SLionel Sambuc         Status = AcpiUtExecute_HID (Node, &Hid);
752433d6423SLionel Sambuc         if (Status == AE_NOT_FOUND)
753433d6423SLionel Sambuc         {
754433d6423SLionel Sambuc             return (AE_OK);
755433d6423SLionel Sambuc         }
756433d6423SLionel Sambuc         else if (ACPI_FAILURE (Status))
757433d6423SLionel Sambuc         {
758433d6423SLionel Sambuc             return (AE_CTRL_DEPTH);
759433d6423SLionel Sambuc         }
760433d6423SLionel Sambuc 
761433d6423SLionel Sambuc         NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
762433d6423SLionel Sambuc         ACPI_FREE (Hid);
763433d6423SLionel Sambuc 
764433d6423SLionel Sambuc         if (NoMatch)
765433d6423SLionel Sambuc         {
766433d6423SLionel Sambuc             /*
767433d6423SLionel Sambuc              * HID does not match, attempt match within the
768433d6423SLionel Sambuc              * list of Compatible IDs (CIDs)
769433d6423SLionel Sambuc              */
770433d6423SLionel Sambuc             Status = AcpiUtExecute_CID (Node, &Cid);
771433d6423SLionel Sambuc             if (Status == AE_NOT_FOUND)
772433d6423SLionel Sambuc             {
773433d6423SLionel Sambuc                 return (AE_OK);
774433d6423SLionel Sambuc             }
775433d6423SLionel Sambuc             else if (ACPI_FAILURE (Status))
776433d6423SLionel Sambuc             {
777433d6423SLionel Sambuc                 return (AE_CTRL_DEPTH);
778433d6423SLionel Sambuc             }
779433d6423SLionel Sambuc 
780433d6423SLionel Sambuc             /* Walk the CID list */
781433d6423SLionel Sambuc 
782433d6423SLionel Sambuc             Found = FALSE;
783433d6423SLionel Sambuc             for (i = 0; i < Cid->Count; i++)
784433d6423SLionel Sambuc             {
785433d6423SLionel Sambuc                 if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
786433d6423SLionel Sambuc                 {
787433d6423SLionel Sambuc                     /* Found a matching CID */
788433d6423SLionel Sambuc 
789433d6423SLionel Sambuc                     Found = TRUE;
790433d6423SLionel Sambuc                     break;
791433d6423SLionel Sambuc                 }
792433d6423SLionel Sambuc             }
793433d6423SLionel Sambuc 
794433d6423SLionel Sambuc             ACPI_FREE (Cid);
795433d6423SLionel Sambuc             if (!Found)
796433d6423SLionel Sambuc             {
797433d6423SLionel Sambuc                 return (AE_OK);
798433d6423SLionel Sambuc             }
799433d6423SLionel Sambuc         }
800433d6423SLionel Sambuc     }
801433d6423SLionel Sambuc 
802433d6423SLionel Sambuc     /* Run _STA to determine if device is present */
803433d6423SLionel Sambuc 
804433d6423SLionel Sambuc     Status = AcpiUtExecute_STA (Node, &Flags);
805433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
806433d6423SLionel Sambuc     {
807433d6423SLionel Sambuc         return (AE_CTRL_DEPTH);
808433d6423SLionel Sambuc     }
809433d6423SLionel Sambuc 
810433d6423SLionel Sambuc     if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
811433d6423SLionel Sambuc         !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
812433d6423SLionel Sambuc     {
813433d6423SLionel Sambuc         /*
814433d6423SLionel Sambuc          * Don't examine the children of the device only when the
815433d6423SLionel Sambuc          * device is neither present nor functional. See ACPI spec,
816433d6423SLionel Sambuc          * description of _STA for more information.
817433d6423SLionel Sambuc          */
818433d6423SLionel Sambuc         return (AE_CTRL_DEPTH);
819433d6423SLionel Sambuc     }
820433d6423SLionel Sambuc 
821433d6423SLionel Sambuc     /* We have a valid device, invoke the user function */
822433d6423SLionel Sambuc 
823433d6423SLionel Sambuc     Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
824433d6423SLionel Sambuc                 ReturnValue);
825433d6423SLionel Sambuc     return (Status);
826433d6423SLionel Sambuc }
827433d6423SLionel Sambuc 
828433d6423SLionel Sambuc 
829433d6423SLionel Sambuc /*******************************************************************************
830433d6423SLionel Sambuc  *
831433d6423SLionel Sambuc  * FUNCTION:    AcpiGetDevices
832433d6423SLionel Sambuc  *
833433d6423SLionel Sambuc  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
834433d6423SLionel Sambuc  *              UserFunction        - Called when a matching object is found
835433d6423SLionel Sambuc  *              Context             - Passed to user function
836433d6423SLionel Sambuc  *              ReturnValue         - Location where return value of
837433d6423SLionel Sambuc  *                                    UserFunction is put if terminated early
838433d6423SLionel Sambuc  *
839433d6423SLionel Sambuc  * RETURNS      Return value from the UserFunction if terminated early.
840433d6423SLionel Sambuc  *              Otherwise, returns NULL.
841433d6423SLionel Sambuc  *
842433d6423SLionel Sambuc  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
843433d6423SLionel Sambuc  *              starting (and ending) at the object specified by StartHandle.
844433d6423SLionel Sambuc  *              The UserFunction is called whenever an object of type
845433d6423SLionel Sambuc  *              Device is found. If the user function returns
846433d6423SLionel Sambuc  *              a non-zero value, the search is terminated immediately and this
847433d6423SLionel Sambuc  *              value is returned to the caller.
848433d6423SLionel Sambuc  *
849433d6423SLionel Sambuc  *              This is a wrapper for WalkNamespace, but the callback performs
850433d6423SLionel Sambuc  *              additional filtering. Please see AcpiNsGetDeviceCallback.
851433d6423SLionel Sambuc  *
852433d6423SLionel Sambuc  ******************************************************************************/
853433d6423SLionel Sambuc 
854433d6423SLionel Sambuc ACPI_STATUS
AcpiGetDevices(char * HID,ACPI_WALK_CALLBACK UserFunction,void * Context,void ** ReturnValue)855433d6423SLionel Sambuc AcpiGetDevices (
856433d6423SLionel Sambuc     char                    *HID,
857433d6423SLionel Sambuc     ACPI_WALK_CALLBACK      UserFunction,
858433d6423SLionel Sambuc     void                    *Context,
859433d6423SLionel Sambuc     void                    **ReturnValue)
860433d6423SLionel Sambuc {
861433d6423SLionel Sambuc     ACPI_STATUS             Status;
862433d6423SLionel Sambuc     ACPI_GET_DEVICES_INFO   Info;
863433d6423SLionel Sambuc 
864433d6423SLionel Sambuc 
865433d6423SLionel Sambuc     ACPI_FUNCTION_TRACE (AcpiGetDevices);
866433d6423SLionel Sambuc 
867433d6423SLionel Sambuc 
868433d6423SLionel Sambuc     /* Parameter validation */
869433d6423SLionel Sambuc 
870433d6423SLionel Sambuc     if (!UserFunction)
871433d6423SLionel Sambuc     {
872433d6423SLionel Sambuc         return_ACPI_STATUS (AE_BAD_PARAMETER);
873433d6423SLionel Sambuc     }
874433d6423SLionel Sambuc 
875433d6423SLionel Sambuc     /*
876433d6423SLionel Sambuc      * We're going to call their callback from OUR callback, so we need
877433d6423SLionel Sambuc      * to know what it is, and their context parameter.
878433d6423SLionel Sambuc      */
879433d6423SLionel Sambuc     Info.Hid          = HID;
880433d6423SLionel Sambuc     Info.Context      = Context;
881433d6423SLionel Sambuc     Info.UserFunction = UserFunction;
882433d6423SLionel Sambuc 
883433d6423SLionel Sambuc     /*
884433d6423SLionel Sambuc      * Lock the namespace around the walk.
885433d6423SLionel Sambuc      * The namespace will be unlocked/locked around each call
886433d6423SLionel Sambuc      * to the user function - since this function
887433d6423SLionel Sambuc      * must be allowed to make Acpi calls itself.
888433d6423SLionel Sambuc      */
889433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
890433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
891433d6423SLionel Sambuc     {
892433d6423SLionel Sambuc         return_ACPI_STATUS (Status);
893433d6423SLionel Sambuc     }
894433d6423SLionel Sambuc 
895433d6423SLionel Sambuc     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
896433d6423SLionel Sambuc                 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
897433d6423SLionel Sambuc                 AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
898433d6423SLionel Sambuc 
899433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
900433d6423SLionel Sambuc     return_ACPI_STATUS (Status);
901433d6423SLionel Sambuc }
902433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiGetDevices)903433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiGetDevices)
904433d6423SLionel Sambuc 
905433d6423SLionel Sambuc 
906433d6423SLionel Sambuc /*******************************************************************************
907433d6423SLionel Sambuc  *
908433d6423SLionel Sambuc  * FUNCTION:    AcpiAttachData
909433d6423SLionel Sambuc  *
910433d6423SLionel Sambuc  * PARAMETERS:  ObjHandle           - Namespace node
911433d6423SLionel Sambuc  *              Handler             - Handler for this attachment
912433d6423SLionel Sambuc  *              Data                - Pointer to data to be attached
913433d6423SLionel Sambuc  *
914433d6423SLionel Sambuc  * RETURN:      Status
915433d6423SLionel Sambuc  *
916433d6423SLionel Sambuc  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
917433d6423SLionel Sambuc  *
918433d6423SLionel Sambuc  ******************************************************************************/
919433d6423SLionel Sambuc 
920433d6423SLionel Sambuc ACPI_STATUS
921433d6423SLionel Sambuc AcpiAttachData (
922433d6423SLionel Sambuc     ACPI_HANDLE             ObjHandle,
923433d6423SLionel Sambuc     ACPI_OBJECT_HANDLER     Handler,
924433d6423SLionel Sambuc     void                    *Data)
925433d6423SLionel Sambuc {
926433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
927433d6423SLionel Sambuc     ACPI_STATUS             Status;
928433d6423SLionel Sambuc 
929433d6423SLionel Sambuc 
930433d6423SLionel Sambuc     /* Parameter validation */
931433d6423SLionel Sambuc 
932433d6423SLionel Sambuc     if (!ObjHandle  ||
933433d6423SLionel Sambuc         !Handler    ||
934433d6423SLionel Sambuc         !Data)
935433d6423SLionel Sambuc     {
936433d6423SLionel Sambuc         return (AE_BAD_PARAMETER);
937433d6423SLionel Sambuc     }
938433d6423SLionel Sambuc 
939433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
940433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
941433d6423SLionel Sambuc     {
942433d6423SLionel Sambuc         return (Status);
943433d6423SLionel Sambuc     }
944433d6423SLionel Sambuc 
945433d6423SLionel Sambuc     /* Convert and validate the handle */
946433d6423SLionel Sambuc 
947433d6423SLionel Sambuc     Node = AcpiNsValidateHandle (ObjHandle);
948433d6423SLionel Sambuc     if (!Node)
949433d6423SLionel Sambuc     {
950433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
951433d6423SLionel Sambuc         goto UnlockAndExit;
952433d6423SLionel Sambuc     }
953433d6423SLionel Sambuc 
954433d6423SLionel Sambuc     Status = AcpiNsAttachData (Node, Handler, Data);
955433d6423SLionel Sambuc 
956433d6423SLionel Sambuc UnlockAndExit:
957433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
958433d6423SLionel Sambuc     return (Status);
959433d6423SLionel Sambuc }
960433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiAttachData)961433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiAttachData)
962433d6423SLionel Sambuc 
963433d6423SLionel Sambuc 
964433d6423SLionel Sambuc /*******************************************************************************
965433d6423SLionel Sambuc  *
966433d6423SLionel Sambuc  * FUNCTION:    AcpiDetachData
967433d6423SLionel Sambuc  *
968433d6423SLionel Sambuc  * PARAMETERS:  ObjHandle           - Namespace node handle
969433d6423SLionel Sambuc  *              Handler             - Handler used in call to AcpiAttachData
970433d6423SLionel Sambuc  *
971433d6423SLionel Sambuc  * RETURN:      Status
972433d6423SLionel Sambuc  *
973433d6423SLionel Sambuc  * DESCRIPTION: Remove data that was previously attached to a node.
974433d6423SLionel Sambuc  *
975433d6423SLionel Sambuc  ******************************************************************************/
976433d6423SLionel Sambuc 
977433d6423SLionel Sambuc ACPI_STATUS
978433d6423SLionel Sambuc AcpiDetachData (
979433d6423SLionel Sambuc     ACPI_HANDLE             ObjHandle,
980433d6423SLionel Sambuc     ACPI_OBJECT_HANDLER     Handler)
981433d6423SLionel Sambuc {
982433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
983433d6423SLionel Sambuc     ACPI_STATUS             Status;
984433d6423SLionel Sambuc 
985433d6423SLionel Sambuc 
986433d6423SLionel Sambuc     /* Parameter validation */
987433d6423SLionel Sambuc 
988433d6423SLionel Sambuc     if (!ObjHandle  ||
989433d6423SLionel Sambuc         !Handler)
990433d6423SLionel Sambuc     {
991433d6423SLionel Sambuc         return (AE_BAD_PARAMETER);
992433d6423SLionel Sambuc     }
993433d6423SLionel Sambuc 
994433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
995433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
996433d6423SLionel Sambuc     {
997433d6423SLionel Sambuc         return (Status);
998433d6423SLionel Sambuc     }
999433d6423SLionel Sambuc 
1000433d6423SLionel Sambuc     /* Convert and validate the handle */
1001433d6423SLionel Sambuc 
1002433d6423SLionel Sambuc     Node = AcpiNsValidateHandle (ObjHandle);
1003433d6423SLionel Sambuc     if (!Node)
1004433d6423SLionel Sambuc     {
1005433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
1006433d6423SLionel Sambuc         goto UnlockAndExit;
1007433d6423SLionel Sambuc     }
1008433d6423SLionel Sambuc 
1009433d6423SLionel Sambuc     Status = AcpiNsDetachData (Node, Handler);
1010433d6423SLionel Sambuc 
1011433d6423SLionel Sambuc UnlockAndExit:
1012433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1013433d6423SLionel Sambuc     return (Status);
1014433d6423SLionel Sambuc }
1015433d6423SLionel Sambuc 
ACPI_EXPORT_SYMBOL(AcpiDetachData)1016433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiDetachData)
1017433d6423SLionel Sambuc 
1018433d6423SLionel Sambuc 
1019433d6423SLionel Sambuc /*******************************************************************************
1020433d6423SLionel Sambuc  *
1021433d6423SLionel Sambuc  * FUNCTION:    AcpiGetData
1022433d6423SLionel Sambuc  *
1023433d6423SLionel Sambuc  * PARAMETERS:  ObjHandle           - Namespace node
1024433d6423SLionel Sambuc  *              Handler             - Handler used in call to AttachData
1025433d6423SLionel Sambuc  *              Data                - Where the data is returned
1026433d6423SLionel Sambuc  *
1027433d6423SLionel Sambuc  * RETURN:      Status
1028433d6423SLionel Sambuc  *
1029433d6423SLionel Sambuc  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
1030433d6423SLionel Sambuc  *
1031433d6423SLionel Sambuc  ******************************************************************************/
1032433d6423SLionel Sambuc 
1033433d6423SLionel Sambuc ACPI_STATUS
1034433d6423SLionel Sambuc AcpiGetData (
1035433d6423SLionel Sambuc     ACPI_HANDLE             ObjHandle,
1036433d6423SLionel Sambuc     ACPI_OBJECT_HANDLER     Handler,
1037433d6423SLionel Sambuc     void                    **Data)
1038433d6423SLionel Sambuc {
1039433d6423SLionel Sambuc     ACPI_NAMESPACE_NODE     *Node;
1040433d6423SLionel Sambuc     ACPI_STATUS             Status;
1041433d6423SLionel Sambuc 
1042433d6423SLionel Sambuc 
1043433d6423SLionel Sambuc     /* Parameter validation */
1044433d6423SLionel Sambuc 
1045433d6423SLionel Sambuc     if (!ObjHandle  ||
1046433d6423SLionel Sambuc         !Handler    ||
1047433d6423SLionel Sambuc         !Data)
1048433d6423SLionel Sambuc     {
1049433d6423SLionel Sambuc         return (AE_BAD_PARAMETER);
1050433d6423SLionel Sambuc     }
1051433d6423SLionel Sambuc 
1052433d6423SLionel Sambuc     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1053433d6423SLionel Sambuc     if (ACPI_FAILURE (Status))
1054433d6423SLionel Sambuc     {
1055433d6423SLionel Sambuc         return (Status);
1056433d6423SLionel Sambuc     }
1057433d6423SLionel Sambuc 
1058433d6423SLionel Sambuc     /* Convert and validate the handle */
1059433d6423SLionel Sambuc 
1060433d6423SLionel Sambuc     Node = AcpiNsValidateHandle (ObjHandle);
1061433d6423SLionel Sambuc     if (!Node)
1062433d6423SLionel Sambuc     {
1063433d6423SLionel Sambuc         Status = AE_BAD_PARAMETER;
1064433d6423SLionel Sambuc         goto UnlockAndExit;
1065433d6423SLionel Sambuc     }
1066433d6423SLionel Sambuc 
1067433d6423SLionel Sambuc     Status = AcpiNsGetAttachedData (Node, Handler, Data);
1068433d6423SLionel Sambuc 
1069433d6423SLionel Sambuc UnlockAndExit:
1070433d6423SLionel Sambuc     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1071433d6423SLionel Sambuc     return (Status);
1072433d6423SLionel Sambuc }
1073433d6423SLionel Sambuc 
1074433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiGetData)
1075