OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [acpi/] [dispatcher/] [dsutils.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*******************************************************************************
2
 *
3
 * Module Name: dsutils - Dispatcher utilities
4
 *
5
 ******************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2004, 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/amlcode.h>
48
#include <acpi/acdispat.h>
49
#include <acpi/acinterp.h>
50
#include <acpi/acnamesp.h>
51
#include <acpi/acdebug.h>
52
 
53
#define _COMPONENT          ACPI_DISPATCHER
54
         ACPI_MODULE_NAME    ("dsutils")
55
 
56
 
57
#ifndef ACPI_NO_METHOD_EXECUTION
58
 
59
/*******************************************************************************
60
 *
61
 * FUNCTION:    acpi_ds_is_result_used
62
 *
63
 * PARAMETERS:  Op
64
 *              result_obj
65
 *              walk_state
66
 *
67
 * RETURN:      Status
68
 *
69
 * DESCRIPTION: Check if a result object will be used by the parent
70
 *
71
 ******************************************************************************/
72
 
73
u8
74
acpi_ds_is_result_used (
75
        union acpi_parse_object         *op,
76
        struct acpi_walk_state          *walk_state)
77
{
78
        const struct acpi_opcode_info   *parent_info;
79
 
80
 
81
        ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
82
 
83
 
84
        /* Must have both an Op and a Result Object */
85
 
86
        if (!op) {
87
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
88
                return_VALUE (TRUE);
89
        }
90
 
91
        /*
92
         * If there is no parent, the result can't possibly be used!
93
         * (An executing method typically has no parent, since each
94
         * method is parsed separately)  However, a method that is
95
         * invoked from another method has a parent.
96
         */
97
        if (!op->common.parent) {
98
                return_VALUE (FALSE);
99
        }
100
 
101
        /*
102
         * Get info on the parent.  The root Op is AML_SCOPE
103
         */
104
        parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
105
        if (parent_info->class == AML_CLASS_UNKNOWN) {
106
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
107
                return_VALUE (FALSE);
108
        }
109
 
110
        /*
111
         * Decide what to do with the result based on the parent.  If
112
         * the parent opcode will not use the result, delete the object.
113
         * Otherwise leave it as is, it will be deleted when it is used
114
         * as an operand later.
115
         */
116
        switch (parent_info->class) {
117
        case AML_CLASS_CONTROL:
118
 
119
                switch (op->common.parent->common.aml_opcode) {
120
                case AML_RETURN_OP:
121
 
122
                        /* Never delete the return value associated with a return opcode */
123
 
124
                        goto result_used;
125
 
126
                case AML_IF_OP:
127
                case AML_WHILE_OP:
128
 
129
                        /*
130
                         * If we are executing the predicate AND this is the predicate op,
131
                         * we will use the return value
132
                         */
133
                        if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) &&
134
                                (walk_state->control_state->control.predicate_op == op)) {
135
                                goto result_used;
136
                        }
137
                        break;
138
 
139
                default:
140
                        /* Ignore other control opcodes */
141
                        break;
142
                }
143
 
144
                /* The general control opcode returns no result */
145
 
146
                goto result_not_used;
147
 
148
 
149
        case AML_CLASS_CREATE:
150
 
151
                /*
152
                 * These opcodes allow term_arg(s) as operands and therefore
153
                 * the operands can be method calls.  The result is used.
154
                 */
155
                goto result_used;
156
 
157
 
158
        case AML_CLASS_NAMED_OBJECT:
159
 
160
                if ((op->common.parent->common.aml_opcode == AML_REGION_OP)      ||
161
                        (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
162
                        (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)     ||
163
                        (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
164
                        (op->common.parent->common.aml_opcode == AML_BUFFER_OP)      ||
165
                        (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) {
166
                        /*
167
                         * These opcodes allow term_arg(s) as operands and therefore
168
                         * the operands can be method calls.  The result is used.
169
                         */
170
                        goto result_used;
171
                }
172
 
173
                goto result_not_used;
174
 
175
 
176
        default:
177
 
178
                /*
179
                 * In all other cases. the parent will actually use the return
180
                 * object, so keep it.
181
                 */
182
                goto result_used;
183
        }
184
 
185
 
186
result_used:
187
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n",
188
                        acpi_ps_get_opcode_name (op->common.aml_opcode),
189
                        acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
190
 
191
        return_VALUE (TRUE);
192
 
193
 
194
result_not_used:
195
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n",
196
                        acpi_ps_get_opcode_name (op->common.aml_opcode),
197
                        acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
198
 
199
        return_VALUE (FALSE);
200
}
201
 
202
 
203
/*******************************************************************************
204
 *
205
 * FUNCTION:    acpi_ds_delete_result_if_not_used
206
 *
207
 * PARAMETERS:  Op
208
 *              result_obj
209
 *              walk_state
210
 *
211
 * RETURN:      Status
212
 *
213
 * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
214
 *              result descriptor, check if the parent opcode will actually use
215
 *              this result.  If not, delete the result now so that it will
216
 *              not become orphaned.
217
 *
218
 ******************************************************************************/
219
 
220
void
221
acpi_ds_delete_result_if_not_used (
222
        union acpi_parse_object         *op,
223
        union acpi_operand_object       *result_obj,
224
        struct acpi_walk_state          *walk_state)
225
{
226
        union acpi_operand_object       *obj_desc;
227
        acpi_status                     status;
228
 
229
 
230
        ACPI_FUNCTION_TRACE_PTR ("ds_delete_result_if_not_used", result_obj);
231
 
232
 
233
        if (!op) {
234
                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
235
                return_VOID;
236
        }
237
 
238
        if (!result_obj) {
239
                return_VOID;
240
        }
241
 
242
        if (!acpi_ds_is_result_used (op, walk_state)) {
243
                /*
244
                 * Must pop the result stack (obj_desc should be equal to result_obj)
245
                 */
246
                status = acpi_ds_result_pop (&obj_desc, walk_state);
247
                if (ACPI_SUCCESS (status)) {
248
                        acpi_ut_remove_reference (result_obj);
249
                }
250
        }
251
 
252
        return_VOID;
253
}
254
 
255
 
256
/*******************************************************************************
257
 *
258
 * FUNCTION:    acpi_ds_resolve_operands
259
 *
260
 * PARAMETERS:  walk_state          - Current walk state with operands on stack
261
 *
262
 * RETURN:      Status
263
 *
264
 * DESCRIPTION: Resolve all operands to their values.  Used to prepare
265
 *              arguments to a control method invocation (a call from one
266
 *              method to another.)
267
 *
268
 ******************************************************************************/
269
 
270
acpi_status
271
acpi_ds_resolve_operands (
272
        struct acpi_walk_state          *walk_state)
273
{
274
        u32                             i;
275
        acpi_status                     status = AE_OK;
276
 
277
 
278
        ACPI_FUNCTION_TRACE_PTR ("ds_resolve_operands", walk_state);
279
 
280
 
281
        /*
282
         * Attempt to resolve each of the valid operands
283
         * Method arguments are passed by reference, not by value.  This means
284
         * that the actual objects are passed, not copies of the objects.
285
         */
286
        for (i = 0; i < walk_state->num_operands; i++) {
287
                status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
288
                if (ACPI_FAILURE (status)) {
289
                        break;
290
                }
291
        }
292
 
293
        return_ACPI_STATUS (status);
294
}
295
 
296
 
297
/*******************************************************************************
298
 *
299
 * FUNCTION:    acpi_ds_clear_operands
300
 *
301
 * PARAMETERS:  walk_state          - Current walk state with operands on stack
302
 *
303
 * RETURN:      None
304
 *
305
 * DESCRIPTION: Clear all operands on the current walk state operand stack.
306
 *
307
 ******************************************************************************/
308
 
309
void
310
acpi_ds_clear_operands (
311
        struct acpi_walk_state          *walk_state)
312
{
313
        u32                             i;
314
 
315
 
316
        ACPI_FUNCTION_TRACE_PTR ("acpi_ds_clear_operands", walk_state);
317
 
318
 
319
        /*
320
         * Remove a reference on each operand on the stack
321
         */
322
        for (i = 0; i < walk_state->num_operands; i++) {
323
                /*
324
                 * Remove a reference to all operands, including both
325
                 * "Arguments" and "Targets".
326
                 */
327
                acpi_ut_remove_reference (walk_state->operands[i]);
328
                walk_state->operands[i] = NULL;
329
        }
330
 
331
        walk_state->num_operands = 0;
332
        return_VOID;
333
}
334
#endif
335
 
336
 
337
/*******************************************************************************
338
 *
339
 * FUNCTION:    acpi_ds_create_operand
340
 *
341
 * PARAMETERS:  walk_state
342
 *              Arg
343
 *
344
 * RETURN:      Status
345
 *
346
 * DESCRIPTION: Translate a parse tree object that is an argument to an AML
347
 *              opcode to the equivalent interpreter object.  This may include
348
 *              looking up a name or entering a new name into the internal
349
 *              namespace.
350
 *
351
 ******************************************************************************/
352
 
353
acpi_status
354
acpi_ds_create_operand (
355
        struct acpi_walk_state          *walk_state,
356
        union acpi_parse_object         *arg,
357
        u32                             arg_index)
358
{
359
        acpi_status                     status = AE_OK;
360
        char                            *name_string;
361
        u32                             name_length;
362
        union acpi_operand_object       *obj_desc;
363
        union acpi_parse_object         *parent_op;
364
        u16                             opcode;
365
        acpi_interpreter_mode           interpreter_mode;
366
        const struct acpi_opcode_info   *op_info;
367
 
368
 
369
        ACPI_FUNCTION_TRACE_PTR ("ds_create_operand", arg);
370
 
371
 
372
        /* A valid name must be looked up in the namespace */
373
 
374
        if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
375
                (arg->common.value.string)) {
376
                ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg));
377
 
378
                /* Get the entire name string from the AML stream */
379
 
380
                status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer,
381
                                  &name_string, &name_length);
382
 
383
                if (ACPI_FAILURE (status)) {
384
                        return_ACPI_STATUS (status);
385
                }
386
 
387
                /*
388
                 * All prefixes have been handled, and the name is
389
                 * in name_string
390
                 */
391
 
392
 
393
                /*
394
                 * Special handling for buffer_field declarations. This is a deferred
395
                 * opcode that unfortunately defines the field name as the last
396
                 * parameter instead of the first.  We get here when we are performing
397
                 * the deferred execution, so the actual name of the field is already
398
                 * in the namespace.  We don't want to attempt to look it up again
399
                 * because we may be executing in a different scope than where the
400
                 * actual opcode exists.
401
                 */
402
                if ((walk_state->deferred_node) &&
403
                        (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
404
                        (arg_index != 0)) {
405
                        obj_desc = ACPI_CAST_PTR (union acpi_operand_object, walk_state->deferred_node);
406
                        status = AE_OK;
407
                }
408
                else    /* All other opcodes */ {
409
                        /*
410
                         * Differentiate between a namespace "create" operation
411
                         * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
412
                         * IMODE_EXECUTE) in order to support the creation of
413
                         * namespace objects during the execution of control methods.
414
                         */
415
                        parent_op = arg->common.parent;
416
                        op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
417
                        if ((op_info->flags & AML_NSNODE) &&
418
                                (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
419
                                (parent_op->common.aml_opcode != AML_REGION_OP) &&
420
                                (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
421
                                /* Enter name into namespace if not found */
422
 
423
                                interpreter_mode = ACPI_IMODE_LOAD_PASS2;
424
                        }
425
                        else {
426
                                /* Return a failure if name not found */
427
 
428
                                interpreter_mode = ACPI_IMODE_EXECUTE;
429
                        }
430
 
431
                        status = acpi_ns_lookup (walk_state->scope_info, name_string,
432
                                         ACPI_TYPE_ANY, interpreter_mode,
433
                                         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
434
                                         walk_state,
435
                                         ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
436
                        /*
437
                         * The only case where we pass through (ignore) a NOT_FOUND
438
                         * error is for the cond_ref_of opcode.
439
                         */
440
                        if (status == AE_NOT_FOUND) {
441
                                if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
442
                                        /*
443
                                         * For the Conditional Reference op, it's OK if
444
                                         * the name is not found;  We just need a way to
445
                                         * indicate this to the interpreter, set the
446
                                         * object to the root
447
                                         */
448
                                        obj_desc = ACPI_CAST_PTR (union acpi_operand_object, acpi_gbl_root_node);
449
                                        status = AE_OK;
450
                                }
451
                                else {
452
                                        /*
453
                                         * We just plain didn't find it -- which is a
454
                                         * very serious error at this point
455
                                         */
456
                                        status = AE_AML_NAME_NOT_FOUND;
457
                                }
458
                        }
459
 
460
                        if (ACPI_FAILURE (status)) {
461
                                ACPI_REPORT_NSERROR (name_string, status);
462
                        }
463
                }
464
 
465
                /* Free the namestring created above */
466
 
467
                ACPI_MEM_FREE (name_string);
468
 
469
                /* Check status from the lookup */
470
 
471
                if (ACPI_FAILURE (status)) {
472
                        return_ACPI_STATUS (status);
473
                }
474
 
475
                /* Put the resulting object onto the current object stack */
476
 
477
                status = acpi_ds_obj_stack_push (obj_desc, walk_state);
478
                if (ACPI_FAILURE (status)) {
479
                        return_ACPI_STATUS (status);
480
                }
481
                ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
482
        }
483
        else {
484
                /* Check for null name case */
485
 
486
                if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
487
                        /*
488
                         * If the name is null, this means that this is an
489
                         * optional result parameter that was not specified
490
                         * in the original ASL.  Create a Zero Constant for a
491
                         * placeholder.  (Store to a constant is a Noop.)
492
                         */
493
                        opcode = AML_ZERO_OP;       /* Has no arguments! */
494
 
495
                        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", arg));
496
                }
497
                else {
498
                        opcode = arg->common.aml_opcode;
499
                }
500
 
501
                /* Get the object type of the argument */
502
 
503
                op_info = acpi_ps_get_opcode_info (opcode);
504
                if (op_info->object_type == ACPI_TYPE_INVALID) {
505
                        return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
506
                }
507
 
508
                if (op_info->flags & AML_HAS_RETVAL) {
509
                        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
510
                                "Argument previously created, already stacked \n"));
511
 
512
                        ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (
513
                                walk_state->operands [walk_state->num_operands - 1], walk_state));
514
 
515
                        /*
516
                         * Use value that was already previously returned
517
                         * by the evaluation of this argument
518
                         */
519
                        status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
520
                        if (ACPI_FAILURE (status)) {
521
                                /*
522
                                 * Only error is underflow, and this indicates
523
                                 * a missing or null operand!
524
                                 */
525
                                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Missing or null operand, %s\n",
526
                                        acpi_format_exception (status)));
527
                                return_ACPI_STATUS (status);
528
                        }
529
                }
530
                else {
531
                        /* Create an ACPI_INTERNAL_OBJECT for the argument */
532
 
533
                        obj_desc = acpi_ut_create_internal_object (op_info->object_type);
534
                        if (!obj_desc) {
535
                                return_ACPI_STATUS (AE_NO_MEMORY);
536
                        }
537
 
538
                        /* Initialize the new object */
539
 
540
                        status = acpi_ds_init_object_from_op (walk_state, arg,
541
                                         opcode, &obj_desc);
542
                        if (ACPI_FAILURE (status)) {
543
                                acpi_ut_delete_object_desc (obj_desc);
544
                                return_ACPI_STATUS (status);
545
                        }
546
                }
547
 
548
                /* Put the operand object on the object stack */
549
 
550
                status = acpi_ds_obj_stack_push (obj_desc, walk_state);
551
                if (ACPI_FAILURE (status)) {
552
                        return_ACPI_STATUS (status);
553
                }
554
 
555
                ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
556
        }
557
 
558
        return_ACPI_STATUS (AE_OK);
559
}
560
 
561
 
562
/*******************************************************************************
563
 *
564
 * FUNCTION:    acpi_ds_create_operands
565
 *
566
 * PARAMETERS:  first_arg           - First argument of a parser argument tree
567
 *
568
 * RETURN:      Status
569
 *
570
 * DESCRIPTION: Convert an operator's arguments from a parse tree format to
571
 *              namespace objects and place those argument object on the object
572
 *              stack in preparation for evaluation by the interpreter.
573
 *
574
 ******************************************************************************/
575
 
576
acpi_status
577
acpi_ds_create_operands (
578
        struct acpi_walk_state          *walk_state,
579
        union acpi_parse_object         *first_arg)
580
{
581
        acpi_status                     status = AE_OK;
582
        union acpi_parse_object         *arg;
583
        u32                             arg_count = 0;
584
 
585
 
586
        ACPI_FUNCTION_TRACE_PTR ("ds_create_operands", first_arg);
587
 
588
 
589
        /* For all arguments in the list... */
590
 
591
        arg = first_arg;
592
        while (arg) {
593
                status = acpi_ds_create_operand (walk_state, arg, arg_count);
594
                if (ACPI_FAILURE (status)) {
595
                        goto cleanup;
596
                }
597
 
598
                ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%d (%p) done, Arg1=%p\n",
599
                        arg_count, arg, first_arg));
600
 
601
                /* Move on to next argument, if any */
602
 
603
                arg = arg->common.next;
604
                arg_count++;
605
        }
606
 
607
        return_ACPI_STATUS (status);
608
 
609
 
610
cleanup:
611
        /*
612
         * We must undo everything done above; meaning that we must
613
         * pop everything off of the operand stack and delete those
614
         * objects
615
         */
616
        (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
617
 
618
        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
619
                (arg_count + 1), acpi_format_exception (status)));
620
        return_ACPI_STATUS (status);
621
}
622
 
623
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.