scroll mode for very long start menus
[reactos.git] / reactos / drivers / bus / acpi / dispatcher / dswexec.c
1 /******************************************************************************
2 *
3 * Module Name: dswexec - Dispatcher method execution callbacks;
4 * dispatch to interpreter.
5 * $Revision: 1.1 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "amlcode.h"
31 #include "acdispat.h"
32 #include "acinterp.h"
33 #include "acnamesp.h"
34 #include "acdebug.h"
35
36
37 #define _COMPONENT ACPI_DISPATCHER
38 MODULE_NAME ("dswexec")
39
40
41 /*****************************************************************************
42 *
43 * FUNCTION: Acpi_ds_get_predicate_value
44 *
45 * PARAMETERS: Walk_state - Current state of the parse tree walk
46 *
47 * RETURN: Status
48 *
49 * DESCRIPTION: Get the result of a predicate evaluation
50 *
51 ****************************************************************************/
52
53 ACPI_STATUS
54 acpi_ds_get_predicate_value (
55 ACPI_WALK_STATE *walk_state,
56 ACPI_PARSE_OBJECT *op,
57 u32 has_result_obj)
58 {
59 ACPI_STATUS status = AE_OK;
60 ACPI_OPERAND_OBJECT *obj_desc;
61
62
63 walk_state->control_state->common.state = 0;
64
65 if (has_result_obj) {
66 status = acpi_ds_result_pop (&obj_desc, walk_state);
67 if (ACPI_FAILURE (status)) {
68 return (status);
69 }
70 }
71
72 else {
73 status = acpi_ds_create_operand (walk_state, op, 0);
74 if (ACPI_FAILURE (status)) {
75 return (status);
76 }
77
78 status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state);
79 if (ACPI_FAILURE (status)) {
80 return (status);
81 }
82
83 obj_desc = walk_state->operands [0];
84 }
85
86 if (!obj_desc) {
87 return (AE_AML_NO_OPERAND);
88 }
89
90
91 /*
92 * Result of predicate evaluation currently must
93 * be a number
94 */
95
96 if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
97 status = AE_AML_OPERAND_TYPE;
98 goto cleanup;
99 }
100
101
102 /* Truncate the predicate to 32-bits if necessary */
103
104 acpi_aml_truncate_for32bit_table (obj_desc, walk_state);
105
106 /*
107 * Save the result of the predicate evaluation on
108 * the control stack
109 */
110
111 if (obj_desc->integer.value) {
112 walk_state->control_state->common.value = TRUE;
113 }
114
115 else {
116 /*
117 * Predicate is FALSE, we will just toss the
118 * rest of the package
119 */
120
121 walk_state->control_state->common.value = FALSE;
122 status = AE_CTRL_FALSE;
123 }
124
125
126 cleanup:
127
128 /* Break to debugger to display result */
129
130 DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state));
131
132 /*
133 * Delete the predicate result object (we know that
134 * we don't need it anymore)
135 */
136
137 acpi_cm_remove_reference (obj_desc);
138
139 walk_state->control_state->common.state = CONTROL_NORMAL;
140
141 return (status);
142 }
143
144
145 /*****************************************************************************
146 *
147 * FUNCTION: Acpi_ds_exec_begin_op
148 *
149 * PARAMETERS: Walk_state - Current state of the parse tree walk
150 * Op - Op that has been just been reached in the
151 * walk; Arguments have not been evaluated yet.
152 *
153 * RETURN: Status
154 *
155 * DESCRIPTION: Descending callback used during the execution of control
156 * methods. This is where most operators and operands are
157 * dispatched to the interpreter.
158 *
159 ****************************************************************************/
160
161 ACPI_STATUS
162 acpi_ds_exec_begin_op (
163 u16 opcode,
164 ACPI_PARSE_OBJECT *op,
165 ACPI_WALK_STATE *walk_state,
166 ACPI_PARSE_OBJECT **out_op)
167 {
168 ACPI_OPCODE_INFO *op_info;
169 ACPI_STATUS status = AE_OK;
170
171
172 if (!op) {
173 status = acpi_ds_load2_begin_op (opcode, NULL, walk_state, out_op);
174 if (ACPI_FAILURE (status)) {
175 return (status);
176 }
177
178 op = *out_op;
179 }
180
181 if (op == walk_state->origin) {
182 if (out_op) {
183 *out_op = op;
184 }
185
186 return (AE_OK);
187 }
188
189 /*
190 * If the previous opcode was a conditional, this opcode
191 * must be the beginning of the associated predicate.
192 * Save this knowledge in the current scope descriptor
193 */
194
195 if ((walk_state->control_state) &&
196 (walk_state->control_state->common.state ==
197 CONTROL_CONDITIONAL_EXECUTING)) {
198 walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING;
199
200 /* Save start of predicate */
201
202 walk_state->control_state->control.predicate_op = op;
203 }
204
205
206 op_info = acpi_ps_get_opcode_info (op->opcode);
207
208 /* We want to send namepaths to the load code */
209
210 if (op->opcode == AML_NAMEPATH_OP) {
211 op_info->flags = OPTYPE_NAMED_OBJECT;
212 }
213
214
215 /*
216 * Handle the opcode based upon the opcode type
217 */
218
219 switch (ACPI_GET_OP_CLASS (op_info)) {
220 case OPTYPE_CONTROL:
221
222 status = acpi_ds_result_stack_push (walk_state);
223 if (ACPI_FAILURE (status)) {
224 return (status);
225 }
226
227 status = acpi_ds_exec_begin_control_op (walk_state, op);
228 break;
229
230
231 case OPTYPE_NAMED_OBJECT:
232
233 if (walk_state->walk_type == WALK_METHOD) {
234 /*
235 * Found a named object declaration during method
236 * execution; we must enter this object into the
237 * namespace. The created object is temporary and
238 * will be deleted upon completion of the execution
239 * of this method.
240 */
241
242 status = acpi_ds_load2_begin_op (op->opcode, op, walk_state, NULL);
243 }
244
245
246 if (op->opcode == AML_REGION_OP) {
247 status = acpi_ds_result_stack_push (walk_state);
248 }
249
250 break;
251
252
253 /* most operators with arguments */
254
255 case OPTYPE_MONADIC1:
256 case OPTYPE_DYADIC1:
257 case OPTYPE_MONADIC2:
258 case OPTYPE_MONADIC2_r:
259 case OPTYPE_DYADIC2:
260 case OPTYPE_DYADIC2_r:
261 case OPTYPE_DYADIC2_s:
262 case OPTYPE_RECONFIGURATION:
263 case OPTYPE_INDEX:
264 case OPTYPE_MATCH:
265 case OPTYPE_FATAL:
266 case OPTYPE_CREATE_FIELD:
267
268 /* Start a new result/operand state */
269
270 status = acpi_ds_result_stack_push (walk_state);
271 break;
272
273
274 default:
275 break;
276 }
277
278 /* Nothing to do here during method execution */
279
280 return (status);
281 }
282
283
284 /*****************************************************************************
285 *
286 * FUNCTION: Acpi_ds_exec_end_op
287 *
288 * PARAMETERS: Walk_state - Current state of the parse tree walk
289 * Op - Op that has been just been completed in the
290 * walk; Arguments have now been evaluated.
291 *
292 * RETURN: Status
293 *
294 * DESCRIPTION: Ascending callback used during the execution of control
295 * methods. The only thing we really need to do here is to
296 * notice the beginning of IF, ELSE, and WHILE blocks.
297 *
298 ****************************************************************************/
299
300 ACPI_STATUS
301 acpi_ds_exec_end_op (
302 ACPI_WALK_STATE *walk_state,
303 ACPI_PARSE_OBJECT *op)
304 {
305 ACPI_STATUS status = AE_OK;
306 u16 opcode;
307 u8 optype;
308 ACPI_PARSE_OBJECT *next_op;
309 ACPI_NAMESPACE_NODE *node;
310 ACPI_PARSE_OBJECT *first_arg;
311 ACPI_OPERAND_OBJECT *result_obj = NULL;
312 ACPI_OPCODE_INFO *op_info;
313 u32 operand_index;
314
315
316 opcode = (u16) op->opcode;
317
318
319 op_info = acpi_ps_get_opcode_info (op->opcode);
320 if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
321 return (AE_NOT_IMPLEMENTED);
322 }
323
324 optype = (u8) ACPI_GET_OP_CLASS (op_info);
325 first_arg = op->value.arg;
326
327 /* Init the walk state */
328
329 walk_state->num_operands = 0;
330 walk_state->return_desc = NULL;
331 walk_state->op_info = op_info;
332 walk_state->opcode = opcode;
333
334
335 /* Call debugger for single step support (DEBUG build only) */
336
337 DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, optype));
338 DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return (status);});
339
340
341 /* Decode the opcode */
342
343 switch (optype) {
344 case OPTYPE_UNDEFINED:
345
346 return (AE_NOT_IMPLEMENTED);
347 break;
348
349
350 case OPTYPE_BOGUS:
351 break;
352
353 case OPTYPE_CONSTANT: /* argument type only */
354 case OPTYPE_LITERAL: /* argument type only */
355 case OPTYPE_DATA_TERM: /* argument type only */
356 case OPTYPE_LOCAL_VARIABLE: /* argument type only */
357 case OPTYPE_METHOD_ARGUMENT: /* argument type only */
358 break;
359
360
361 /* most operators with arguments */
362
363 case OPTYPE_MONADIC1:
364 case OPTYPE_DYADIC1:
365 case OPTYPE_MONADIC2:
366 case OPTYPE_MONADIC2_r:
367 case OPTYPE_DYADIC2:
368 case OPTYPE_DYADIC2_r:
369 case OPTYPE_DYADIC2_s:
370 case OPTYPE_RECONFIGURATION:
371 case OPTYPE_INDEX:
372 case OPTYPE_MATCH:
373 case OPTYPE_FATAL:
374
375
376 /* Build resolved operand stack */
377
378 status = acpi_ds_create_operands (walk_state, first_arg);
379 if (ACPI_FAILURE (status)) {
380 goto cleanup;
381 }
382
383 operand_index = walk_state->num_operands - 1;
384
385
386 /* Done with this result state (Now that operand stack is built) */
387
388 status = acpi_ds_result_stack_pop (walk_state);
389 if (ACPI_FAILURE (status)) {
390 goto cleanup;
391 }
392
393 switch (optype) {
394 case OPTYPE_MONADIC1:
395
396 /* 1 Operand, 0 External_result, 0 Internal_result */
397
398 status = acpi_aml_exec_monadic1 (opcode, walk_state);
399 break;
400
401
402 case OPTYPE_MONADIC2:
403
404 /* 1 Operand, 0 External_result, 1 Internal_result */
405
406 status = acpi_aml_exec_monadic2 (opcode, walk_state, &result_obj);
407 break;
408
409
410 case OPTYPE_MONADIC2_r:
411
412 /* 1 Operand, 1 External_result, 1 Internal_result */
413
414 status = acpi_aml_exec_monadic2_r (opcode, walk_state, &result_obj);
415 break;
416
417
418 case OPTYPE_DYADIC1:
419
420 /* 2 Operands, 0 External_result, 0 Internal_result */
421
422 status = acpi_aml_exec_dyadic1 (opcode, walk_state);
423 break;
424
425
426 case OPTYPE_DYADIC2:
427
428 /* 2 Operands, 0 External_result, 1 Internal_result */
429
430 status = acpi_aml_exec_dyadic2 (opcode, walk_state, &result_obj);
431 break;
432
433
434 case OPTYPE_DYADIC2_r:
435
436 /* 2 Operands, 1 or 2 External_results, 1 Internal_result */
437
438 status = acpi_aml_exec_dyadic2_r (opcode, walk_state, &result_obj);
439 break;
440
441
442 case OPTYPE_DYADIC2_s: /* Synchronization Operator */
443
444 /* 2 Operands, 0 External_result, 1 Internal_result */
445
446 status = acpi_aml_exec_dyadic2_s (opcode, walk_state, &result_obj);
447 break;
448
449
450 case OPTYPE_INDEX: /* Type 2 opcode with 3 operands */
451
452 /* 3 Operands, 1 External_result, 1 Internal_result */
453
454 status = acpi_aml_exec_index (walk_state, &result_obj);
455 break;
456
457
458 case OPTYPE_MATCH: /* Type 2 opcode with 6 operands */
459
460 /* 6 Operands, 0 External_result, 1 Internal_result */
461
462 status = acpi_aml_exec_match (walk_state, &result_obj);
463 break;
464
465
466 case OPTYPE_RECONFIGURATION:
467
468 /* 1 or 2 operands, 0 Internal Result */
469
470 status = acpi_aml_exec_reconfiguration (opcode, walk_state);
471 break;
472
473
474 case OPTYPE_FATAL:
475
476 /* 3 Operands, 0 External_result, 0 Internal_result */
477
478 status = acpi_aml_exec_fatal (walk_state);
479 break;
480 }
481
482 /*
483 * If a result object was returned from above, push it on the
484 * current result stack
485 */
486 if (ACPI_SUCCESS (status) &&
487 result_obj) {
488 status = acpi_ds_result_push (result_obj, walk_state);
489 }
490
491 break;
492
493
494 case OPTYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
495
496 /* 1 Operand, 0 External_result, 0 Internal_result */
497
498 status = acpi_ds_exec_end_control_op (walk_state, op);
499
500 acpi_ds_result_stack_pop (walk_state);
501 break;
502
503
504 case OPTYPE_METHOD_CALL:
505
506 /*
507 * (AML_METHODCALL) Op->Value->Arg->Node contains
508 * the method Node pointer
509 */
510 /* Next_op points to the op that holds the method name */
511
512 next_op = first_arg;
513 node = next_op->node;
514
515 /* Next_op points to first argument op */
516
517 next_op = next_op->next;
518
519 /*
520 * Get the method's arguments and put them on the operand stack
521 */
522 status = acpi_ds_create_operands (walk_state, next_op);
523 if (ACPI_FAILURE (status)) {
524 break;
525 }
526
527 /*
528 * Since the operands will be passed to another
529 * control method, we must resolve all local
530 * references here (Local variables, arguments
531 * to *this* method, etc.)
532 */
533
534 status = acpi_ds_resolve_operands (walk_state);
535 if (ACPI_FAILURE (status)) {
536 break;
537 }
538
539 /*
540 * Tell the walk loop to preempt this running method and
541 * execute the new method
542 */
543 status = AE_CTRL_TRANSFER;
544
545 /*
546 * Return now; we don't want to disturb anything,
547 * especially the operand count!
548 */
549 return (status);
550 break;
551
552
553 case OPTYPE_CREATE_FIELD:
554
555 status = acpi_ds_load2_end_op (walk_state, op);
556 if (ACPI_FAILURE (status)) {
557 break;
558 }
559
560 status = acpi_ds_eval_field_unit_operands (walk_state, op);
561 break;
562
563
564 case OPTYPE_NAMED_OBJECT:
565
566 status = acpi_ds_load2_end_op (walk_state, op);
567 if (ACPI_FAILURE (status)) {
568 break;
569 }
570
571 switch (op->opcode) {
572 case AML_REGION_OP:
573
574 status = acpi_ds_eval_region_operands (walk_state, op);
575 if (ACPI_FAILURE (status)) {
576 break;
577 }
578
579 status = acpi_ds_result_stack_pop (walk_state);
580 break;
581
582
583 case AML_METHOD_OP:
584 break;
585
586
587 case AML_ALIAS_OP:
588
589 /* Alias creation was already handled by call
590 to psxload above */
591 break;
592
593
594 default:
595 /* Nothing needs to be done */
596
597 status = AE_OK;
598 break;
599 }
600
601 break;
602
603 default:
604
605 status = AE_NOT_IMPLEMENTED;
606 break;
607 }
608
609
610 /*
611 * ACPI 2.0 support for 64-bit integers:
612 * Truncate numeric result value if we are executing from a 32-bit ACPI table
613 */
614 acpi_aml_truncate_for32bit_table (result_obj, walk_state);
615
616 /*
617 * Check if we just completed the evaluation of a
618 * conditional predicate
619 */
620
621 if ((walk_state->control_state) &&
622 (walk_state->control_state->common.state ==
623 CONTROL_PREDICATE_EXECUTING) &&
624 (walk_state->control_state->control.predicate_op == op)) {
625 status = acpi_ds_get_predicate_value (walk_state, op, (u32) result_obj);
626 result_obj = NULL;
627 }
628
629
630 cleanup:
631 if (result_obj) {
632 /* Break to debugger to display result */
633
634 DEBUGGER_EXEC (acpi_db_display_result_object (result_obj, walk_state));
635
636 /*
637 * Delete the result op if and only if:
638 * Parent will not use the result -- such as any
639 * non-nested type2 op in a method (parent will be method)
640 */
641 acpi_ds_delete_result_if_not_used (op, result_obj, walk_state);
642 }
643
644 /* Always clear the object stack */
645
646 /* TBD: [Investigate] Clear stack of return value,
647 but don't delete it */
648 walk_state->num_operands = 0;
649
650 return (status);
651 }
652
653