diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dswstate.c')
-rw-r--r-- | drivers/acpi/dispatcher/dswstate.c | 1100 |
1 files changed, 1100 insertions, 0 deletions
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c new file mode 100644 index 000000000000..e555b3fbd5e5 --- /dev/null +++ b/drivers/acpi/dispatcher/dswstate.c | |||
@@ -0,0 +1,1100 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswstate - Dispatcher parse tree walk management routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/acparser.h> | ||
47 | #include <acpi/acdispat.h> | ||
48 | #include <acpi/acnamesp.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_DISPATCHER | ||
51 | ACPI_MODULE_NAME ("dswstate") | ||
52 | |||
53 | |||
54 | #ifdef ACPI_FUTURE_USAGE | ||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ds_result_insert | ||
59 | * | ||
60 | * PARAMETERS: Object - Object to push | ||
61 | * Index - Where to insert the object | ||
62 | * walk_state - Current Walk state | ||
63 | * | ||
64 | * RETURN: Status | ||
65 | * | ||
66 | * DESCRIPTION: Insert an object onto this walk's result stack | ||
67 | * | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | acpi_status | ||
71 | acpi_ds_result_insert ( | ||
72 | void *object, | ||
73 | u32 index, | ||
74 | struct acpi_walk_state *walk_state) | ||
75 | { | ||
76 | union acpi_generic_state *state; | ||
77 | |||
78 | |||
79 | ACPI_FUNCTION_NAME ("ds_result_insert"); | ||
80 | |||
81 | |||
82 | state = walk_state->results; | ||
83 | if (!state) { | ||
84 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n", | ||
85 | walk_state)); | ||
86 | return (AE_NOT_EXIST); | ||
87 | } | ||
88 | |||
89 | if (index >= ACPI_OBJ_NUM_OPERANDS) { | ||
90 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
91 | "Index out of range: %X Obj=%p State=%p Num=%X\n", | ||
92 | index, object, walk_state, state->results.num_results)); | ||
93 | return (AE_BAD_PARAMETER); | ||
94 | } | ||
95 | |||
96 | if (!object) { | ||
97 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
98 | "Null Object! Index=%X Obj=%p State=%p Num=%X\n", | ||
99 | index, object, walk_state, state->results.num_results)); | ||
100 | return (AE_BAD_PARAMETER); | ||
101 | } | ||
102 | |||
103 | state->results.obj_desc [index] = object; | ||
104 | state->results.num_results++; | ||
105 | |||
106 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
107 | "Obj=%p [%s] State=%p Num=%X Cur=%X\n", | ||
108 | object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL", | ||
109 | walk_state, state->results.num_results, walk_state->current_result)); | ||
110 | |||
111 | return (AE_OK); | ||
112 | } | ||
113 | |||
114 | |||
115 | /******************************************************************************* | ||
116 | * | ||
117 | * FUNCTION: acpi_ds_result_remove | ||
118 | * | ||
119 | * PARAMETERS: Object - Where to return the popped object | ||
120 | * Index - Where to extract the object | ||
121 | * walk_state - Current Walk state | ||
122 | * | ||
123 | * RETURN: Status | ||
124 | * | ||
125 | * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In | ||
126 | * other words, this is a FIFO. | ||
127 | * | ||
128 | ******************************************************************************/ | ||
129 | |||
130 | acpi_status | ||
131 | acpi_ds_result_remove ( | ||
132 | union acpi_operand_object **object, | ||
133 | u32 index, | ||
134 | struct acpi_walk_state *walk_state) | ||
135 | { | ||
136 | union acpi_generic_state *state; | ||
137 | |||
138 | |||
139 | ACPI_FUNCTION_NAME ("ds_result_remove"); | ||
140 | |||
141 | |||
142 | state = walk_state->results; | ||
143 | if (!state) { | ||
144 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n", | ||
145 | walk_state)); | ||
146 | return (AE_NOT_EXIST); | ||
147 | } | ||
148 | |||
149 | if (index >= ACPI_OBJ_MAX_OPERAND) { | ||
150 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
151 | "Index out of range: %X State=%p Num=%X\n", | ||
152 | index, walk_state, state->results.num_results)); | ||
153 | } | ||
154 | |||
155 | /* Check for a valid result object */ | ||
156 | |||
157 | if (!state->results.obj_desc [index]) { | ||
158 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
159 | "Null operand! State=%p #Ops=%X, Index=%X\n", | ||
160 | walk_state, state->results.num_results, index)); | ||
161 | return (AE_AML_NO_RETURN_VALUE); | ||
162 | } | ||
163 | |||
164 | /* Remove the object */ | ||
165 | |||
166 | state->results.num_results--; | ||
167 | |||
168 | *object = state->results.obj_desc [index]; | ||
169 | state->results.obj_desc [index] = NULL; | ||
170 | |||
171 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
172 | "Obj=%p [%s] Index=%X State=%p Num=%X\n", | ||
173 | *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL", | ||
174 | index, walk_state, state->results.num_results)); | ||
175 | |||
176 | return (AE_OK); | ||
177 | } | ||
178 | |||
179 | #endif /* ACPI_FUTURE_USAGE */ | ||
180 | |||
181 | |||
182 | /******************************************************************************* | ||
183 | * | ||
184 | * FUNCTION: acpi_ds_result_pop | ||
185 | * | ||
186 | * PARAMETERS: Object - Where to return the popped object | ||
187 | * walk_state - Current Walk state | ||
188 | * | ||
189 | * RETURN: Status | ||
190 | * | ||
191 | * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In | ||
192 | * other words, this is a FIFO. | ||
193 | * | ||
194 | ******************************************************************************/ | ||
195 | |||
196 | acpi_status | ||
197 | acpi_ds_result_pop ( | ||
198 | union acpi_operand_object **object, | ||
199 | struct acpi_walk_state *walk_state) | ||
200 | { | ||
201 | acpi_native_uint index; | ||
202 | union acpi_generic_state *state; | ||
203 | |||
204 | |||
205 | ACPI_FUNCTION_NAME ("ds_result_pop"); | ||
206 | |||
207 | |||
208 | state = walk_state->results; | ||
209 | if (!state) { | ||
210 | return (AE_OK); | ||
211 | } | ||
212 | |||
213 | if (!state->results.num_results) { | ||
214 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Result stack is empty! State=%p\n", | ||
215 | walk_state)); | ||
216 | return (AE_AML_NO_RETURN_VALUE); | ||
217 | } | ||
218 | |||
219 | /* Remove top element */ | ||
220 | |||
221 | state->results.num_results--; | ||
222 | |||
223 | for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { | ||
224 | /* Check for a valid result object */ | ||
225 | |||
226 | if (state->results.obj_desc [index -1]) { | ||
227 | *object = state->results.obj_desc [index -1]; | ||
228 | state->results.obj_desc [index -1] = NULL; | ||
229 | |||
230 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n", | ||
231 | *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL", | ||
232 | (u32) index -1, walk_state, state->results.num_results)); | ||
233 | |||
234 | return (AE_OK); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state)); | ||
239 | return (AE_AML_NO_RETURN_VALUE); | ||
240 | } | ||
241 | |||
242 | |||
243 | /******************************************************************************* | ||
244 | * | ||
245 | * FUNCTION: acpi_ds_result_pop_from_bottom | ||
246 | * | ||
247 | * PARAMETERS: Object - Where to return the popped object | ||
248 | * walk_state - Current Walk state | ||
249 | * | ||
250 | * RETURN: Status | ||
251 | * | ||
252 | * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In | ||
253 | * other words, this is a FIFO. | ||
254 | * | ||
255 | ******************************************************************************/ | ||
256 | |||
257 | acpi_status | ||
258 | acpi_ds_result_pop_from_bottom ( | ||
259 | union acpi_operand_object **object, | ||
260 | struct acpi_walk_state *walk_state) | ||
261 | { | ||
262 | acpi_native_uint index; | ||
263 | union acpi_generic_state *state; | ||
264 | |||
265 | |||
266 | ACPI_FUNCTION_NAME ("ds_result_pop_from_bottom"); | ||
267 | |||
268 | |||
269 | state = walk_state->results; | ||
270 | if (!state) { | ||
271 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
272 | "Warning: No result object pushed! State=%p\n", walk_state)); | ||
273 | return (AE_NOT_EXIST); | ||
274 | } | ||
275 | |||
276 | if (!state->results.num_results) { | ||
277 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state)); | ||
278 | return (AE_AML_NO_RETURN_VALUE); | ||
279 | } | ||
280 | |||
281 | /* Remove Bottom element */ | ||
282 | |||
283 | *object = state->results.obj_desc [0]; | ||
284 | |||
285 | /* Push entire stack down one element */ | ||
286 | |||
287 | for (index = 0; index < state->results.num_results; index++) { | ||
288 | state->results.obj_desc [index] = state->results.obj_desc [index + 1]; | ||
289 | } | ||
290 | |||
291 | state->results.num_results--; | ||
292 | |||
293 | /* Check for a valid result object */ | ||
294 | |||
295 | if (!*object) { | ||
296 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null operand! State=%p #Ops=%X, Index=%X\n", | ||
297 | walk_state, state->results.num_results, (u32) index)); | ||
298 | return (AE_AML_NO_RETURN_VALUE); | ||
299 | } | ||
300 | |||
301 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n", | ||
302 | *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL", | ||
303 | state, walk_state)); | ||
304 | |||
305 | return (AE_OK); | ||
306 | } | ||
307 | |||
308 | |||
309 | /******************************************************************************* | ||
310 | * | ||
311 | * FUNCTION: acpi_ds_result_push | ||
312 | * | ||
313 | * PARAMETERS: Object - Where to return the popped object | ||
314 | * walk_state - Current Walk state | ||
315 | * | ||
316 | * RETURN: Status | ||
317 | * | ||
318 | * DESCRIPTION: Push an object onto the current result stack | ||
319 | * | ||
320 | ******************************************************************************/ | ||
321 | |||
322 | acpi_status | ||
323 | acpi_ds_result_push ( | ||
324 | union acpi_operand_object *object, | ||
325 | struct acpi_walk_state *walk_state) | ||
326 | { | ||
327 | union acpi_generic_state *state; | ||
328 | |||
329 | |||
330 | ACPI_FUNCTION_NAME ("ds_result_push"); | ||
331 | |||
332 | |||
333 | state = walk_state->results; | ||
334 | if (!state) { | ||
335 | ACPI_REPORT_ERROR (("No result stack frame during push\n")); | ||
336 | return (AE_AML_INTERNAL); | ||
337 | } | ||
338 | |||
339 | if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) { | ||
340 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
341 | "Result stack overflow: Obj=%p State=%p Num=%X\n", | ||
342 | object, walk_state, state->results.num_results)); | ||
343 | return (AE_STACK_OVERFLOW); | ||
344 | } | ||
345 | |||
346 | if (!object) { | ||
347 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Object! Obj=%p State=%p Num=%X\n", | ||
348 | object, walk_state, state->results.num_results)); | ||
349 | return (AE_BAD_PARAMETER); | ||
350 | } | ||
351 | |||
352 | state->results.obj_desc [state->results.num_results] = object; | ||
353 | state->results.num_results++; | ||
354 | |||
355 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", | ||
356 | object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL", | ||
357 | walk_state, state->results.num_results, walk_state->current_result)); | ||
358 | |||
359 | return (AE_OK); | ||
360 | } | ||
361 | |||
362 | |||
363 | /******************************************************************************* | ||
364 | * | ||
365 | * FUNCTION: acpi_ds_result_stack_push | ||
366 | * | ||
367 | * PARAMETERS: walk_state - Current Walk state | ||
368 | * | ||
369 | * RETURN: Status | ||
370 | * | ||
371 | * DESCRIPTION: Push an object onto the walk_state result stack. | ||
372 | * | ||
373 | ******************************************************************************/ | ||
374 | |||
375 | acpi_status | ||
376 | acpi_ds_result_stack_push ( | ||
377 | struct acpi_walk_state *walk_state) | ||
378 | { | ||
379 | union acpi_generic_state *state; | ||
380 | |||
381 | ACPI_FUNCTION_NAME ("ds_result_stack_push"); | ||
382 | |||
383 | |||
384 | state = acpi_ut_create_generic_state (); | ||
385 | if (!state) { | ||
386 | return (AE_NO_MEMORY); | ||
387 | } | ||
388 | |||
389 | state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT; | ||
390 | acpi_ut_push_generic_state (&walk_state->results, state); | ||
391 | |||
392 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n", | ||
393 | state, walk_state)); | ||
394 | |||
395 | return (AE_OK); | ||
396 | } | ||
397 | |||
398 | |||
399 | /******************************************************************************* | ||
400 | * | ||
401 | * FUNCTION: acpi_ds_result_stack_pop | ||
402 | * | ||
403 | * PARAMETERS: walk_state - Current Walk state | ||
404 | * | ||
405 | * RETURN: Status | ||
406 | * | ||
407 | * DESCRIPTION: Pop an object off of the walk_state result stack. | ||
408 | * | ||
409 | ******************************************************************************/ | ||
410 | |||
411 | acpi_status | ||
412 | acpi_ds_result_stack_pop ( | ||
413 | struct acpi_walk_state *walk_state) | ||
414 | { | ||
415 | union acpi_generic_state *state; | ||
416 | |||
417 | ACPI_FUNCTION_NAME ("ds_result_stack_pop"); | ||
418 | |||
419 | |||
420 | /* Check for stack underflow */ | ||
421 | |||
422 | if (walk_state->results == NULL) { | ||
423 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Underflow - State=%p\n", | ||
424 | walk_state)); | ||
425 | return (AE_AML_NO_OPERAND); | ||
426 | } | ||
427 | |||
428 | state = acpi_ut_pop_generic_state (&walk_state->results); | ||
429 | |||
430 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, | ||
431 | "Result=%p remaining_results=%X State=%p\n", | ||
432 | state, state->results.num_results, walk_state)); | ||
433 | |||
434 | acpi_ut_delete_generic_state (state); | ||
435 | |||
436 | return (AE_OK); | ||
437 | } | ||
438 | |||
439 | |||
440 | /******************************************************************************* | ||
441 | * | ||
442 | * FUNCTION: acpi_ds_obj_stack_delete_all | ||
443 | * | ||
444 | * PARAMETERS: walk_state - Current Walk state | ||
445 | * | ||
446 | * RETURN: Status | ||
447 | * | ||
448 | * DESCRIPTION: Clear the object stack by deleting all objects that are on it. | ||
449 | * Should be used with great care, if at all! | ||
450 | * | ||
451 | ******************************************************************************/ | ||
452 | #ifdef ACPI_FUTURE_USAGE | ||
453 | acpi_status | ||
454 | acpi_ds_obj_stack_delete_all ( | ||
455 | struct acpi_walk_state *walk_state) | ||
456 | { | ||
457 | u32 i; | ||
458 | |||
459 | |||
460 | ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_delete_all", walk_state); | ||
461 | |||
462 | |||
463 | /* The stack size is configurable, but fixed */ | ||
464 | |||
465 | for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) { | ||
466 | if (walk_state->operands[i]) { | ||
467 | acpi_ut_remove_reference (walk_state->operands[i]); | ||
468 | walk_state->operands[i] = NULL; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | return_ACPI_STATUS (AE_OK); | ||
473 | } | ||
474 | #endif /* ACPI_FUTURE_USAGE */ | ||
475 | |||
476 | |||
477 | /******************************************************************************* | ||
478 | * | ||
479 | * FUNCTION: acpi_ds_obj_stack_push | ||
480 | * | ||
481 | * PARAMETERS: Object - Object to push | ||
482 | * walk_state - Current Walk state | ||
483 | * | ||
484 | * RETURN: Status | ||
485 | * | ||
486 | * DESCRIPTION: Push an object onto this walk's object/operand stack | ||
487 | * | ||
488 | ******************************************************************************/ | ||
489 | |||
490 | acpi_status | ||
491 | acpi_ds_obj_stack_push ( | ||
492 | void *object, | ||
493 | struct acpi_walk_state *walk_state) | ||
494 | { | ||
495 | ACPI_FUNCTION_NAME ("ds_obj_stack_push"); | ||
496 | |||
497 | |||
498 | /* Check for stack overflow */ | ||
499 | |||
500 | if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { | ||
501 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
502 | "overflow! Obj=%p State=%p #Ops=%X\n", | ||
503 | object, walk_state, walk_state->num_operands)); | ||
504 | return (AE_STACK_OVERFLOW); | ||
505 | } | ||
506 | |||
507 | /* Put the object onto the stack */ | ||
508 | |||
509 | walk_state->operands [walk_state->num_operands] = object; | ||
510 | walk_state->num_operands++; | ||
511 | |||
512 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", | ||
513 | object, acpi_ut_get_object_type_name ((union acpi_operand_object *) object), | ||
514 | walk_state, walk_state->num_operands)); | ||
515 | |||
516 | return (AE_OK); | ||
517 | } | ||
518 | |||
519 | |||
520 | #if 0 | ||
521 | /******************************************************************************* | ||
522 | * | ||
523 | * FUNCTION: acpi_ds_obj_stack_pop_object | ||
524 | * | ||
525 | * PARAMETERS: pop_count - Number of objects/entries to pop | ||
526 | * walk_state - Current Walk state | ||
527 | * | ||
528 | * RETURN: Status | ||
529 | * | ||
530 | * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT | ||
531 | * deleted by this routine. | ||
532 | * | ||
533 | ******************************************************************************/ | ||
534 | |||
535 | acpi_status | ||
536 | acpi_ds_obj_stack_pop_object ( | ||
537 | union acpi_operand_object **object, | ||
538 | struct acpi_walk_state *walk_state) | ||
539 | { | ||
540 | ACPI_FUNCTION_NAME ("ds_obj_stack_pop_object"); | ||
541 | |||
542 | |||
543 | /* Check for stack underflow */ | ||
544 | |||
545 | if (walk_state->num_operands == 0) { | ||
546 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
547 | "Missing operand/stack empty! State=%p #Ops=%X\n", | ||
548 | walk_state, walk_state->num_operands)); | ||
549 | *object = NULL; | ||
550 | return (AE_AML_NO_OPERAND); | ||
551 | } | ||
552 | |||
553 | /* Pop the stack */ | ||
554 | |||
555 | walk_state->num_operands--; | ||
556 | |||
557 | /* Check for a valid operand */ | ||
558 | |||
559 | if (!walk_state->operands [walk_state->num_operands]) { | ||
560 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
561 | "Null operand! State=%p #Ops=%X\n", | ||
562 | walk_state, walk_state->num_operands)); | ||
563 | *object = NULL; | ||
564 | return (AE_AML_NO_OPERAND); | ||
565 | } | ||
566 | |||
567 | /* Get operand and set stack entry to null */ | ||
568 | |||
569 | *object = walk_state->operands [walk_state->num_operands]; | ||
570 | walk_state->operands [walk_state->num_operands] = NULL; | ||
571 | |||
572 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", | ||
573 | *object, acpi_ut_get_object_type_name (*object), | ||
574 | walk_state, walk_state->num_operands)); | ||
575 | |||
576 | return (AE_OK); | ||
577 | } | ||
578 | #endif | ||
579 | |||
580 | |||
581 | /******************************************************************************* | ||
582 | * | ||
583 | * FUNCTION: acpi_ds_obj_stack_pop | ||
584 | * | ||
585 | * PARAMETERS: pop_count - Number of objects/entries to pop | ||
586 | * walk_state - Current Walk state | ||
587 | * | ||
588 | * RETURN: Status | ||
589 | * | ||
590 | * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT | ||
591 | * deleted by this routine. | ||
592 | * | ||
593 | ******************************************************************************/ | ||
594 | |||
595 | acpi_status | ||
596 | acpi_ds_obj_stack_pop ( | ||
597 | u32 pop_count, | ||
598 | struct acpi_walk_state *walk_state) | ||
599 | { | ||
600 | u32 i; | ||
601 | |||
602 | ACPI_FUNCTION_NAME ("ds_obj_stack_pop"); | ||
603 | |||
604 | |||
605 | for (i = 0; i < pop_count; i++) { | ||
606 | /* Check for stack underflow */ | ||
607 | |||
608 | if (walk_state->num_operands == 0) { | ||
609 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
610 | "Underflow! Count=%X State=%p #Ops=%X\n", | ||
611 | pop_count, walk_state, walk_state->num_operands)); | ||
612 | return (AE_STACK_UNDERFLOW); | ||
613 | } | ||
614 | |||
615 | /* Just set the stack entry to null */ | ||
616 | |||
617 | walk_state->num_operands--; | ||
618 | walk_state->operands [walk_state->num_operands] = NULL; | ||
619 | } | ||
620 | |||
621 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", | ||
622 | pop_count, walk_state, walk_state->num_operands)); | ||
623 | |||
624 | return (AE_OK); | ||
625 | } | ||
626 | |||
627 | |||
628 | /******************************************************************************* | ||
629 | * | ||
630 | * FUNCTION: acpi_ds_obj_stack_pop_and_delete | ||
631 | * | ||
632 | * PARAMETERS: pop_count - Number of objects/entries to pop | ||
633 | * walk_state - Current Walk state | ||
634 | * | ||
635 | * RETURN: Status | ||
636 | * | ||
637 | * DESCRIPTION: Pop this walk's object stack and delete each object that is | ||
638 | * popped off. | ||
639 | * | ||
640 | ******************************************************************************/ | ||
641 | |||
642 | acpi_status | ||
643 | acpi_ds_obj_stack_pop_and_delete ( | ||
644 | u32 pop_count, | ||
645 | struct acpi_walk_state *walk_state) | ||
646 | { | ||
647 | u32 i; | ||
648 | union acpi_operand_object *obj_desc; | ||
649 | |||
650 | |||
651 | ACPI_FUNCTION_NAME ("ds_obj_stack_pop_and_delete"); | ||
652 | |||
653 | |||
654 | for (i = 0; i < pop_count; i++) { | ||
655 | /* Check for stack underflow */ | ||
656 | |||
657 | if (walk_state->num_operands == 0) { | ||
658 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
659 | "Underflow! Count=%X State=%p #Ops=%X\n", | ||
660 | pop_count, walk_state, walk_state->num_operands)); | ||
661 | return (AE_STACK_UNDERFLOW); | ||
662 | } | ||
663 | |||
664 | /* Pop the stack and delete an object if present in this stack entry */ | ||
665 | |||
666 | walk_state->num_operands--; | ||
667 | obj_desc = walk_state->operands [walk_state->num_operands]; | ||
668 | if (obj_desc) { | ||
669 | acpi_ut_remove_reference (walk_state->operands [walk_state->num_operands]); | ||
670 | walk_state->operands [walk_state->num_operands] = NULL; | ||
671 | } | ||
672 | } | ||
673 | |||
674 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", | ||
675 | pop_count, walk_state, walk_state->num_operands)); | ||
676 | |||
677 | return (AE_OK); | ||
678 | } | ||
679 | |||
680 | |||
681 | /******************************************************************************* | ||
682 | * | ||
683 | * FUNCTION: acpi_ds_obj_stack_get_value | ||
684 | * | ||
685 | * PARAMETERS: Index - Stack index whose value is desired. Based | ||
686 | * on the top of the stack (index=0 == top) | ||
687 | * walk_state - Current Walk state | ||
688 | * | ||
689 | * RETURN: Status | ||
690 | * | ||
691 | * DESCRIPTION: Retrieve an object from this walk's object stack. Index must | ||
692 | * be within the range of the current stack pointer. | ||
693 | * | ||
694 | ******************************************************************************/ | ||
695 | #ifdef ACPI_FUTURE_USAGE | ||
696 | void * | ||
697 | acpi_ds_obj_stack_get_value ( | ||
698 | u32 index, | ||
699 | struct acpi_walk_state *walk_state) | ||
700 | { | ||
701 | |||
702 | ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_get_value", walk_state); | ||
703 | |||
704 | |||
705 | /* Can't do it if the stack is empty */ | ||
706 | |||
707 | if (walk_state->num_operands == 0) { | ||
708 | return_PTR (NULL); | ||
709 | } | ||
710 | |||
711 | /* or if the index is past the top of the stack */ | ||
712 | |||
713 | if (index > (walk_state->num_operands - (u32) 1)) { | ||
714 | return_PTR (NULL); | ||
715 | } | ||
716 | |||
717 | return_PTR (walk_state->operands[(acpi_native_uint)(walk_state->num_operands - 1) - | ||
718 | index]); | ||
719 | } | ||
720 | #endif /* ACPI_FUTURE_USAGE */ | ||
721 | |||
722 | |||
723 | /******************************************************************************* | ||
724 | * | ||
725 | * FUNCTION: acpi_ds_get_current_walk_state | ||
726 | * | ||
727 | * PARAMETERS: Thread - Get current active state for this Thread | ||
728 | * | ||
729 | * RETURN: Pointer to the current walk state | ||
730 | * | ||
731 | * DESCRIPTION: Get the walk state that is at the head of the list (the "current" | ||
732 | * walk state.) | ||
733 | * | ||
734 | ******************************************************************************/ | ||
735 | |||
736 | struct acpi_walk_state * | ||
737 | acpi_ds_get_current_walk_state ( | ||
738 | struct acpi_thread_state *thread) | ||
739 | |||
740 | { | ||
741 | ACPI_FUNCTION_NAME ("ds_get_current_walk_state"); | ||
742 | |||
743 | |||
744 | if (!thread) { | ||
745 | return (NULL); | ||
746 | } | ||
747 | |||
748 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current walk_state %p\n", | ||
749 | thread->walk_state_list)); | ||
750 | |||
751 | return (thread->walk_state_list); | ||
752 | } | ||
753 | |||
754 | |||
755 | /******************************************************************************* | ||
756 | * | ||
757 | * FUNCTION: acpi_ds_push_walk_state | ||
758 | * | ||
759 | * PARAMETERS: walk_state - State to push | ||
760 | * walk_list - The list that owns the walk stack | ||
761 | * | ||
762 | * RETURN: None | ||
763 | * | ||
764 | * DESCRIPTION: Place the walk_state at the head of the state list. | ||
765 | * | ||
766 | ******************************************************************************/ | ||
767 | |||
768 | void | ||
769 | acpi_ds_push_walk_state ( | ||
770 | struct acpi_walk_state *walk_state, | ||
771 | struct acpi_thread_state *thread) | ||
772 | { | ||
773 | ACPI_FUNCTION_TRACE ("ds_push_walk_state"); | ||
774 | |||
775 | |||
776 | walk_state->next = thread->walk_state_list; | ||
777 | thread->walk_state_list = walk_state; | ||
778 | |||
779 | return_VOID; | ||
780 | } | ||
781 | |||
782 | |||
783 | /******************************************************************************* | ||
784 | * | ||
785 | * FUNCTION: acpi_ds_pop_walk_state | ||
786 | * | ||
787 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
788 | * | ||
789 | * RETURN: A walk_state object popped from the stack | ||
790 | * | ||
791 | * DESCRIPTION: Remove and return the walkstate object that is at the head of | ||
792 | * the walk stack for the given walk list. NULL indicates that | ||
793 | * the list is empty. | ||
794 | * | ||
795 | ******************************************************************************/ | ||
796 | |||
797 | struct acpi_walk_state * | ||
798 | acpi_ds_pop_walk_state ( | ||
799 | struct acpi_thread_state *thread) | ||
800 | { | ||
801 | struct acpi_walk_state *walk_state; | ||
802 | |||
803 | |||
804 | ACPI_FUNCTION_TRACE ("ds_pop_walk_state"); | ||
805 | |||
806 | |||
807 | walk_state = thread->walk_state_list; | ||
808 | |||
809 | if (walk_state) { | ||
810 | /* Next walk state becomes the current walk state */ | ||
811 | |||
812 | thread->walk_state_list = walk_state->next; | ||
813 | |||
814 | /* | ||
815 | * Don't clear the NEXT field, this serves as an indicator | ||
816 | * that there is a parent WALK STATE | ||
817 | * NO: walk_state->Next = NULL; | ||
818 | */ | ||
819 | } | ||
820 | |||
821 | return_PTR (walk_state); | ||
822 | } | ||
823 | |||
824 | |||
825 | /******************************************************************************* | ||
826 | * | ||
827 | * FUNCTION: acpi_ds_create_walk_state | ||
828 | * | ||
829 | * PARAMETERS: Origin - Starting point for this walk | ||
830 | * Thread - Current thread state | ||
831 | * | ||
832 | * RETURN: Pointer to the new walk state. | ||
833 | * | ||
834 | * DESCRIPTION: Allocate and initialize a new walk state. The current walk | ||
835 | * state is set to this new state. | ||
836 | * | ||
837 | ******************************************************************************/ | ||
838 | |||
839 | struct acpi_walk_state * | ||
840 | acpi_ds_create_walk_state ( | ||
841 | acpi_owner_id owner_id, | ||
842 | union acpi_parse_object *origin, | ||
843 | union acpi_operand_object *mth_desc, | ||
844 | struct acpi_thread_state *thread) | ||
845 | { | ||
846 | struct acpi_walk_state *walk_state; | ||
847 | acpi_status status; | ||
848 | |||
849 | |||
850 | ACPI_FUNCTION_TRACE ("ds_create_walk_state"); | ||
851 | |||
852 | |||
853 | walk_state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_WALK); | ||
854 | if (!walk_state) { | ||
855 | return_PTR (NULL); | ||
856 | } | ||
857 | |||
858 | walk_state->data_type = ACPI_DESC_TYPE_WALK; | ||
859 | walk_state->owner_id = owner_id; | ||
860 | walk_state->origin = origin; | ||
861 | walk_state->method_desc = mth_desc; | ||
862 | walk_state->thread = thread; | ||
863 | |||
864 | walk_state->parser_state.start_op = origin; | ||
865 | |||
866 | /* Init the method args/local */ | ||
867 | |||
868 | #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) | ||
869 | acpi_ds_method_data_init (walk_state); | ||
870 | #endif | ||
871 | |||
872 | /* Create an initial result stack entry */ | ||
873 | |||
874 | status = acpi_ds_result_stack_push (walk_state); | ||
875 | if (ACPI_FAILURE (status)) { | ||
876 | acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state); | ||
877 | return_PTR (NULL); | ||
878 | } | ||
879 | |||
880 | /* Put the new state at the head of the walk list */ | ||
881 | |||
882 | if (thread) { | ||
883 | acpi_ds_push_walk_state (walk_state, thread); | ||
884 | } | ||
885 | |||
886 | return_PTR (walk_state); | ||
887 | } | ||
888 | |||
889 | |||
890 | /******************************************************************************* | ||
891 | * | ||
892 | * FUNCTION: acpi_ds_init_aml_walk | ||
893 | * | ||
894 | * PARAMETERS: walk_state - New state to be initialized | ||
895 | * Op - Current parse op | ||
896 | * method_node - Control method NS node, if any | ||
897 | * aml_start - Start of AML | ||
898 | * aml_length - Length of AML | ||
899 | * Params - Method args, if any | ||
900 | * return_obj_desc - Where to store a return object, if any | ||
901 | * pass_number - 1, 2, or 3 | ||
902 | * | ||
903 | * RETURN: Status | ||
904 | * | ||
905 | * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk | ||
906 | * | ||
907 | ******************************************************************************/ | ||
908 | |||
909 | acpi_status | ||
910 | acpi_ds_init_aml_walk ( | ||
911 | struct acpi_walk_state *walk_state, | ||
912 | union acpi_parse_object *op, | ||
913 | struct acpi_namespace_node *method_node, | ||
914 | u8 *aml_start, | ||
915 | u32 aml_length, | ||
916 | struct acpi_parameter_info *info, | ||
917 | u32 pass_number) | ||
918 | { | ||
919 | acpi_status status; | ||
920 | struct acpi_parse_state *parser_state = &walk_state->parser_state; | ||
921 | union acpi_parse_object *extra_op; | ||
922 | |||
923 | |||
924 | ACPI_FUNCTION_TRACE ("ds_init_aml_walk"); | ||
925 | |||
926 | |||
927 | walk_state->parser_state.aml = | ||
928 | walk_state->parser_state.aml_start = aml_start; | ||
929 | walk_state->parser_state.aml_end = | ||
930 | walk_state->parser_state.pkg_end = aml_start + aml_length; | ||
931 | |||
932 | /* The next_op of the next_walk will be the beginning of the method */ | ||
933 | |||
934 | walk_state->next_op = NULL; | ||
935 | |||
936 | if (info) { | ||
937 | if (info->parameter_type == ACPI_PARAM_GPE) { | ||
938 | walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info, | ||
939 | info->parameters); | ||
940 | } | ||
941 | else { | ||
942 | walk_state->params = info->parameters; | ||
943 | walk_state->caller_return_desc = &info->return_object; | ||
944 | } | ||
945 | } | ||
946 | |||
947 | status = acpi_ps_init_scope (&walk_state->parser_state, op); | ||
948 | if (ACPI_FAILURE (status)) { | ||
949 | return_ACPI_STATUS (status); | ||
950 | } | ||
951 | |||
952 | if (method_node) { | ||
953 | walk_state->parser_state.start_node = method_node; | ||
954 | walk_state->walk_type = ACPI_WALK_METHOD; | ||
955 | walk_state->method_node = method_node; | ||
956 | walk_state->method_desc = acpi_ns_get_attached_object (method_node); | ||
957 | |||
958 | /* Push start scope on scope stack and make it current */ | ||
959 | |||
960 | status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state); | ||
961 | if (ACPI_FAILURE (status)) { | ||
962 | return_ACPI_STATUS (status); | ||
963 | } | ||
964 | |||
965 | /* Init the method arguments */ | ||
966 | |||
967 | status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state); | ||
968 | if (ACPI_FAILURE (status)) { | ||
969 | return_ACPI_STATUS (status); | ||
970 | } | ||
971 | } | ||
972 | else { | ||
973 | /* | ||
974 | * Setup the current scope. | ||
975 | * Find a Named Op that has a namespace node associated with it. | ||
976 | * search upwards from this Op. Current scope is the first | ||
977 | * Op with a namespace node. | ||
978 | */ | ||
979 | extra_op = parser_state->start_op; | ||
980 | while (extra_op && !extra_op->common.node) { | ||
981 | extra_op = extra_op->common.parent; | ||
982 | } | ||
983 | |||
984 | if (!extra_op) { | ||
985 | parser_state->start_node = NULL; | ||
986 | } | ||
987 | else { | ||
988 | parser_state->start_node = extra_op->common.node; | ||
989 | } | ||
990 | |||
991 | if (parser_state->start_node) { | ||
992 | /* Push start scope on scope stack and make it current */ | ||
993 | |||
994 | status = acpi_ds_scope_stack_push (parser_state->start_node, | ||
995 | parser_state->start_node->type, walk_state); | ||
996 | if (ACPI_FAILURE (status)) { | ||
997 | return_ACPI_STATUS (status); | ||
998 | } | ||
999 | } | ||
1000 | } | ||
1001 | |||
1002 | status = acpi_ds_init_callbacks (walk_state, pass_number); | ||
1003 | return_ACPI_STATUS (status); | ||
1004 | } | ||
1005 | |||
1006 | |||
1007 | /******************************************************************************* | ||
1008 | * | ||
1009 | * FUNCTION: acpi_ds_delete_walk_state | ||
1010 | * | ||
1011 | * PARAMETERS: walk_state - State to delete | ||
1012 | * | ||
1013 | * RETURN: Status | ||
1014 | * | ||
1015 | * DESCRIPTION: Delete a walk state including all internal data structures | ||
1016 | * | ||
1017 | ******************************************************************************/ | ||
1018 | |||
1019 | void | ||
1020 | acpi_ds_delete_walk_state ( | ||
1021 | struct acpi_walk_state *walk_state) | ||
1022 | { | ||
1023 | union acpi_generic_state *state; | ||
1024 | |||
1025 | |||
1026 | ACPI_FUNCTION_TRACE_PTR ("ds_delete_walk_state", walk_state); | ||
1027 | |||
1028 | |||
1029 | if (!walk_state) { | ||
1030 | return; | ||
1031 | } | ||
1032 | |||
1033 | if (walk_state->data_type != ACPI_DESC_TYPE_WALK) { | ||
1034 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n", walk_state)); | ||
1035 | return; | ||
1036 | } | ||
1037 | |||
1038 | if (walk_state->parser_state.scope) { | ||
1039 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", walk_state)); | ||
1040 | } | ||
1041 | |||
1042 | /* Always must free any linked control states */ | ||
1043 | |||
1044 | while (walk_state->control_state) { | ||
1045 | state = walk_state->control_state; | ||
1046 | walk_state->control_state = state->common.next; | ||
1047 | |||
1048 | acpi_ut_delete_generic_state (state); | ||
1049 | } | ||
1050 | |||
1051 | /* Always must free any linked parse states */ | ||
1052 | |||
1053 | while (walk_state->scope_info) { | ||
1054 | state = walk_state->scope_info; | ||
1055 | walk_state->scope_info = state->common.next; | ||
1056 | |||
1057 | acpi_ut_delete_generic_state (state); | ||
1058 | } | ||
1059 | |||
1060 | /* Always must free any stacked result states */ | ||
1061 | |||
1062 | while (walk_state->results) { | ||
1063 | state = walk_state->results; | ||
1064 | walk_state->results = state->common.next; | ||
1065 | |||
1066 | acpi_ut_delete_generic_state (state); | ||
1067 | } | ||
1068 | |||
1069 | acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state); | ||
1070 | return_VOID; | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | #ifdef ACPI_ENABLE_OBJECT_CACHE | ||
1075 | /****************************************************************************** | ||
1076 | * | ||
1077 | * FUNCTION: acpi_ds_delete_walk_state_cache | ||
1078 | * | ||
1079 | * PARAMETERS: None | ||
1080 | * | ||
1081 | * RETURN: Status | ||
1082 | * | ||
1083 | * DESCRIPTION: Purge the global state object cache. Used during subsystem | ||
1084 | * termination. | ||
1085 | * | ||
1086 | ******************************************************************************/ | ||
1087 | |||
1088 | void | ||
1089 | acpi_ds_delete_walk_state_cache ( | ||
1090 | void) | ||
1091 | { | ||
1092 | ACPI_FUNCTION_TRACE ("ds_delete_walk_state_cache"); | ||
1093 | |||
1094 | |||
1095 | acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK); | ||
1096 | return_VOID; | ||
1097 | } | ||
1098 | #endif | ||
1099 | |||
1100 | |||