Ported ACPI CA (from the nice guys at Intel) to ReactOS (ACPI bus driver).
[reactos.git] / reactos / drivers / bus / acpi / executer / amresop.c
1
2 /******************************************************************************
3 *
4 * Module Name: amresop - AML Interpreter operand/object resolution
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 "amlcode.h"
30 #include "acparser.h"
31 #include "acdispat.h"
32 #include "acinterp.h"
33 #include "acnamesp.h"
34 #include "actables.h"
35 #include "acevents.h"
36
37
38 #define _COMPONENT ACPI_EXECUTER
39 MODULE_NAME ("amresop")
40
41
42 /*******************************************************************************
43 *
44 * FUNCTION: Acpi_aml_check_object_type
45 *
46 * PARAMETERS: Type_needed Object type needed
47 * This_type Actual object type
48 * Object Object pointer
49 *
50 * RETURN: Status
51 *
52 * DESCRIPTION: Check required type against actual type
53 *
54 ******************************************************************************/
55
56 ACPI_STATUS
57 acpi_aml_check_object_type (
58 ACPI_OBJECT_TYPE type_needed,
59 ACPI_OBJECT_TYPE this_type,
60 void *object)
61 {
62
63
64 if (type_needed == ACPI_TYPE_ANY) {
65 /* All types OK, so we don't perform any typechecks */
66
67 return (AE_OK);
68 }
69
70
71 if (type_needed != this_type) {
72 return (AE_AML_OPERAND_TYPE);
73 }
74
75
76 return (AE_OK);
77 }
78
79
80 /*******************************************************************************
81 *
82 * FUNCTION: Acpi_aml_resolve_operands
83 *
84 * PARAMETERS: Opcode Opcode being interpreted
85 * Stack_ptr Top of operand stack
86 *
87 * RETURN: Status
88 *
89 * DESCRIPTION: Convert stack entries to required types
90 *
91 * Each nibble in Arg_types represents one required operand
92 * and indicates the required Type:
93 *
94 * The corresponding stack entry will be converted to the
95 * required type if possible, else return an exception
96 *
97 ******************************************************************************/
98
99 ACPI_STATUS
100 acpi_aml_resolve_operands (
101 u16 opcode,
102 ACPI_OPERAND_OBJECT **stack_ptr,
103 ACPI_WALK_STATE *walk_state)
104 {
105 ACPI_OPERAND_OBJECT *obj_desc;
106 ACPI_STATUS status = AE_OK;
107 u8 object_type;
108 ACPI_HANDLE temp_handle;
109 u32 arg_types;
110 ACPI_OPCODE_INFO *op_info;
111 u32 this_arg_type;
112 ACPI_OBJECT_TYPE type_needed;
113
114
115 op_info = acpi_ps_get_opcode_info (opcode);
116 if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
117 return (AE_AML_BAD_OPCODE);
118 }
119
120
121 arg_types = op_info->runtime_args;
122 if (arg_types == ARGI_INVALID_OPCODE) {
123 return (AE_AML_INTERNAL);
124 }
125
126
127 /*
128 * Normal exit is with *Types == '\0' at end of string.
129 * Function will return an exception from within the loop upon
130 * finding an entry which is not, and cannot be converted
131 * to, the required type; if stack underflows; or upon
132 * finding a NULL stack entry (which "should never happen").
133 */
134
135 while (GET_CURRENT_ARG_TYPE (arg_types)) {
136 if (!stack_ptr || !*stack_ptr) {
137 return (AE_AML_INTERNAL);
138 }
139
140 /* Extract useful items */
141
142 obj_desc = *stack_ptr;
143
144 /* Decode the descriptor type */
145
146 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
147 /* Node */
148
149 object_type = ((ACPI_NAMESPACE_NODE *) obj_desc)->type;
150 }
151
152 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
153 /* ACPI internal object */
154
155 object_type = obj_desc->common.type;
156
157 /* Check for bad ACPI_OBJECT_TYPE */
158
159 if (!acpi_aml_validate_object_type (object_type)) {
160 return (AE_AML_OPERAND_TYPE);
161 }
162
163 if (object_type == (u8) INTERNAL_TYPE_REFERENCE) {
164 /*
165 * Decode the Reference
166 */
167
168 op_info = acpi_ps_get_opcode_info (opcode);
169 if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
170 return (AE_AML_BAD_OPCODE);
171 }
172
173
174 switch (obj_desc->reference.opcode) {
175 case AML_ZERO_OP:
176 case AML_ONE_OP:
177 case AML_ONES_OP:
178 case AML_DEBUG_OP:
179 case AML_NAME_OP:
180 case AML_INDEX_OP:
181 case AML_ARG_OP:
182 case AML_LOCAL_OP:
183
184 break;
185
186 default:
187 return (AE_AML_OPERAND_TYPE);
188 break;
189 }
190 }
191 }
192
193 else {
194 /* Invalid descriptor */
195
196 return (AE_AML_OPERAND_TYPE);
197 }
198
199
200 /*
201 * Get one argument type, point to the next
202 */
203
204 this_arg_type = GET_CURRENT_ARG_TYPE (arg_types);
205 INCREMENT_ARG_LIST (arg_types);
206
207
208 /*
209 * Handle cases where the object does not need to be
210 * resolved to a value
211 */
212
213 switch (this_arg_type) {
214
215 case ARGI_REFERENCE: /* References */
216 case ARGI_INTEGER_REF:
217 case ARGI_OBJECT_REF:
218 case ARGI_DEVICE_REF:
219 case ARGI_TARGETREF: /* TBD: must implement implicit conversion rules before store */
220 case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
221 case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
222
223 /* Need an operand of type INTERNAL_TYPE_REFERENCE */
224
225 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ {
226 goto next_operand;
227 }
228
229 status = acpi_aml_check_object_type (INTERNAL_TYPE_REFERENCE,
230 object_type, obj_desc);
231 if (ACPI_FAILURE (status)) {
232 return (status);
233 }
234
235
236 if (AML_NAME_OP == obj_desc->reference.opcode) {
237 /*
238 * Convert an indirect name ptr to direct name ptr and put
239 * it on the stack
240 */
241
242 temp_handle = obj_desc->reference.object;
243 acpi_cm_remove_reference (obj_desc);
244 (*stack_ptr) = temp_handle;
245 }
246
247 goto next_operand;
248 break;
249
250
251 case ARGI_ANYTYPE:
252
253 /*
254 * We don't want to resolve Index_op reference objects during
255 * a store because this would be an implicit De_ref_of operation.
256 * Instead, we just want to store the reference object.
257 * -- All others must be resolved below.
258 */
259
260 if ((opcode == AML_STORE_OP) &&
261 ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) &&
262 ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
263 goto next_operand;
264 }
265 break;
266 }
267
268
269 /*
270 * Resolve this object to a value
271 */
272
273 status = acpi_aml_resolve_to_value (stack_ptr, walk_state);
274 if (ACPI_FAILURE (status)) {
275 return (status);
276 }
277
278
279 /*
280 * Check the resulting object (value) type
281 */
282 switch (this_arg_type) {
283 /*
284 * For the simple cases, only one type of resolved object
285 * is allowed
286 */
287 case ARGI_MUTEX:
288
289 /* Need an operand of type ACPI_TYPE_MUTEX */
290
291 type_needed = ACPI_TYPE_MUTEX;
292 break;
293
294 case ARGI_EVENT:
295
296 /* Need an operand of type ACPI_TYPE_EVENT */
297
298 type_needed = ACPI_TYPE_EVENT;
299 break;
300
301 case ARGI_REGION:
302
303 /* Need an operand of type ACPI_TYPE_REGION */
304
305 type_needed = ACPI_TYPE_REGION;
306 break;
307
308 case ARGI_IF: /* If */
309
310 /* Need an operand of type INTERNAL_TYPE_IF */
311
312 type_needed = INTERNAL_TYPE_IF;
313 break;
314
315 case ARGI_PACKAGE: /* Package */
316
317 /* Need an operand of type ACPI_TYPE_PACKAGE */
318
319 type_needed = ACPI_TYPE_PACKAGE;
320 break;
321
322 case ARGI_ANYTYPE:
323
324 /* Any operand type will do */
325
326 type_needed = ACPI_TYPE_ANY;
327 break;
328
329
330 /*
331 * The more complex cases allow multiple resolved object types
332 */
333
334 case ARGI_INTEGER: /* Number */
335
336 /*
337 * Need an operand of type ACPI_TYPE_INTEGER,
338 * But we can implicitly convert from a STRING or BUFFER
339 */
340 status = acpi_aml_convert_to_integer (stack_ptr, walk_state);
341 if (ACPI_FAILURE (status)) {
342 if (status == AE_TYPE) {
343 return (AE_AML_OPERAND_TYPE);
344 }
345
346 return (status);
347 }
348
349 goto next_operand;
350 break;
351
352
353 case ARGI_BUFFER:
354
355 /*
356 * Need an operand of type ACPI_TYPE_BUFFER,
357 * But we can implicitly convert from a STRING or INTEGER
358 */
359 status = acpi_aml_convert_to_buffer (stack_ptr, walk_state);
360 if (ACPI_FAILURE (status)) {
361 if (status == AE_TYPE) {
362 return (AE_AML_OPERAND_TYPE);
363 }
364
365 return (status);
366 }
367
368 goto next_operand;
369 break;
370
371
372 case ARGI_STRING:
373
374 /*
375 * Need an operand of type ACPI_TYPE_STRING,
376 * But we can implicitly convert from a BUFFER or INTEGER
377 */
378 status = acpi_aml_convert_to_string (stack_ptr, walk_state);
379 if (ACPI_FAILURE (status)) {
380 if (status == AE_TYPE) {
381 return (AE_AML_OPERAND_TYPE);
382 }
383
384 return (status);
385 }
386
387 goto next_operand;
388 break;
389
390
391 case ARGI_COMPUTEDATA:
392
393 /* Need an operand of type INTEGER, STRING or BUFFER */
394
395 if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) &&
396 (ACPI_TYPE_STRING != (*stack_ptr)->common.type) &&
397 (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) {
398 return (AE_AML_OPERAND_TYPE);
399 }
400 goto next_operand;
401 break;
402
403
404 case ARGI_DATAOBJECT:
405 /*
406 * ARGI_DATAOBJECT is only used by the Size_of operator.
407 *
408 * The ACPI specification allows Size_of to return the size of
409 * a Buffer, String or Package. However, the MS ACPI.SYS AML
410 * Interpreter also allows an Node reference to return without
411 * error with a size of 4.
412 */
413
414 /* Need a buffer, string, package or Node reference */
415
416 if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) &&
417 ((*stack_ptr)->common.type != ACPI_TYPE_STRING) &&
418 ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) &&
419 ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) {
420 return (AE_AML_OPERAND_TYPE);
421 }
422
423 /*
424 * If this is a reference, only allow a reference to an Node.
425 */
426 if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) {
427 if (!(*stack_ptr)->reference.node) {
428 return (AE_AML_OPERAND_TYPE);
429 }
430 }
431 goto next_operand;
432 break;
433
434
435 case ARGI_COMPLEXOBJ:
436
437 /* Need a buffer or package */
438
439 if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) &&
440 ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) {
441 return (AE_AML_OPERAND_TYPE);
442 }
443 goto next_operand;
444 break;
445
446
447 default:
448
449 /* Unknown type */
450
451 return (AE_BAD_PARAMETER);
452 }
453
454
455 /*
456 * Make sure that the original object was resolved to the
457 * required object type (Simple cases only).
458 */
459 status = acpi_aml_check_object_type (type_needed,
460 (*stack_ptr)->common.type, *stack_ptr);
461 if (ACPI_FAILURE (status)) {
462 return (status);
463 }
464
465
466 next_operand:
467 /*
468 * If more operands needed, decrement Stack_ptr to point
469 * to next operand on stack
470 */
471 if (GET_CURRENT_ARG_TYPE (arg_types)) {
472 stack_ptr--;
473 }
474
475 } /* while (*Types) */
476
477
478 return (status);
479 }
480
481