Merge trunk HEAD (r46369)
[reactos.git] / reactos / drivers / bus / acpi / executer / amresolv.c
1
2 /******************************************************************************
3 *
4 * Module Name: amresolv - AML Interpreter 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
30
31
32 #define _COMPONENT ACPI_EXECUTER
33 MODULE_NAME ("amresolv")
34
35
36 /*******************************************************************************
37 *
38 * FUNCTION: Acpi_aml_get_field_unit_value
39 *
40 * PARAMETERS: *Field_desc - Pointer to a Field_unit
41 * *Result_desc - Pointer to an empty descriptor
42 * which will become a Number
43 * containing the field's value.
44 *
45 * RETURN: Status
46 *
47 * DESCRIPTION: Retrieve the value from a Field_unit
48 *
49 ******************************************************************************/
50
51 ACPI_STATUS
52 acpi_aml_get_field_unit_value (
53 ACPI_OPERAND_OBJECT *field_desc,
54 ACPI_OPERAND_OBJECT *result_desc)
55 {
56 ACPI_STATUS status = AE_OK;
57 u32 mask;
58 u8 *location = NULL;
59 u8 locked = FALSE;
60
61
62 if (!field_desc) {
63 status = AE_AML_NO_OPERAND;
64 }
65
66 if (!(field_desc->common.flags & AOPOBJ_DATA_VALID)) {
67 status = acpi_ds_get_field_unit_arguments (field_desc);
68 if (ACPI_FAILURE (status)) {
69 return (status);
70 }
71 }
72
73 if (!field_desc->field_unit.container) {
74 status = AE_AML_INTERNAL;
75 }
76
77 else if (ACPI_TYPE_BUFFER != field_desc->field_unit.container->common.type) {
78 status = AE_AML_OPERAND_TYPE;
79 }
80
81 else if (!result_desc) {
82 status = AE_AML_INTERNAL;
83 }
84
85 if (ACPI_FAILURE (status)) {
86 return (status);
87 }
88
89
90 /* Get the global lock if needed */
91
92 locked = acpi_aml_acquire_global_lock (field_desc->field_unit.lock_rule);
93
94 /* Field location is (base of buffer) + (byte offset) */
95
96 location = field_desc->field_unit.container->buffer.pointer
97 + field_desc->field_unit.offset;
98
99 /*
100 * Construct Mask with as many 1 bits as the field width
101 *
102 * NOTE: Only the bottom 5 bits are valid for a shift operation, so
103 * special care must be taken for any shift greater than 31 bits.
104 *
105 * TBD: [Unhandled] Fields greater than 32-bits will not work.
106 */
107
108 if (field_desc->field_unit.length < 32) {
109 mask = ((u32) 1 << field_desc->field_unit.length) - (u32) 1;
110 }
111 else {
112 mask = ACPI_UINT32_MAX;
113 }
114
115 result_desc->integer.type = (u8) ACPI_TYPE_INTEGER;
116
117 /* Get the 32 bit value at the location */
118
119 MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location);
120
121 /*
122 * Shift the 32-bit word containing the field, and mask off the
123 * resulting value
124 */
125
126 result_desc->integer.value =
127 (result_desc->integer.value >> field_desc->field_unit.bit_offset) & mask;
128
129 /* Release global lock if we acquired it earlier */
130
131 acpi_aml_release_global_lock (locked);
132
133 return (status);
134 }
135
136
137 /*******************************************************************************
138 *
139 * FUNCTION: Acpi_aml_resolve_to_value
140 *
141 * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can
142 * be either an (ACPI_OPERAND_OBJECT *)
143 * or an ACPI_HANDLE.
144 *
145 * RETURN: Status
146 *
147 * DESCRIPTION: Convert Reference objects to values
148 *
149 ******************************************************************************/
150
151 ACPI_STATUS
152 acpi_aml_resolve_to_value (
153 ACPI_OPERAND_OBJECT **stack_ptr,
154 ACPI_WALK_STATE *walk_state)
155 {
156 ACPI_STATUS status = AE_OK;
157
158
159 if (!stack_ptr || !*stack_ptr) {
160 return (AE_AML_NO_OPERAND);
161 }
162
163
164 /*
165 * The entity pointed to by the Stack_ptr can be either
166 * 1) A valid ACPI_OPERAND_OBJECT, or
167 * 2) A ACPI_NAMESPACE_NODE (Named_obj)
168 */
169
170 if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) {
171
172 status = acpi_aml_resolve_object_to_value (stack_ptr, walk_state);
173 if (ACPI_FAILURE (status)) {
174 return (status);
175 }
176 }
177
178 /*
179 * Object on the stack may have changed if Acpi_aml_resolve_object_to_value()
180 * was called (i.e., we can't use an _else_ here.)
181 */
182
183 if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) {
184 status = acpi_aml_resolve_node_to_value ((ACPI_NAMESPACE_NODE **) stack_ptr, walk_state);
185 }
186
187
188 return (status);
189 }
190
191
192 /*******************************************************************************
193 *
194 * FUNCTION: Acpi_aml_resolve_object_to_value
195 *
196 * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a
197 * ptr to an internal object.
198 *
199 * RETURN: Status
200 *
201 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
202 * uses the associated AML opcode to determine the value.
203 *
204 ******************************************************************************/
205
206 ACPI_STATUS
207 acpi_aml_resolve_object_to_value (
208 ACPI_OPERAND_OBJECT **stack_ptr,
209 ACPI_WALK_STATE *walk_state)
210 {
211 ACPI_OPERAND_OBJECT *stack_desc;
212 ACPI_STATUS status = AE_OK;
213 ACPI_HANDLE temp_handle = NULL;
214 ACPI_OPERAND_OBJECT *obj_desc = NULL;
215 u32 index = 0;
216 u16 opcode;
217
218
219 stack_desc = *stack_ptr;
220
221 /* This is an ACPI_OPERAND_OBJECT */
222
223 switch (stack_desc->common.type) {
224
225 case INTERNAL_TYPE_REFERENCE:
226
227 opcode = stack_desc->reference.opcode;
228
229 switch (opcode) {
230
231 case AML_NAME_OP:
232
233 /*
234 * Convert indirect name ptr to a direct name ptr.
235 * Then, Acpi_aml_resolve_node_to_value can be used to get the value
236 */
237
238 temp_handle = stack_desc->reference.object;
239
240 /* Delete the Reference Object */
241
242 acpi_cm_remove_reference (stack_desc);
243
244 /* Put direct name pointer onto stack and exit */
245
246 (*stack_ptr) = temp_handle;
247 status = AE_OK;
248 break;
249
250
251 case AML_LOCAL_OP:
252 case AML_ARG_OP:
253
254 index = stack_desc->reference.offset;
255
256 /*
257 * Get the local from the method's state info
258 * Note: this increments the local's object reference count
259 */
260
261 status = acpi_ds_method_data_get_value (opcode, index,
262 walk_state, &obj_desc);
263 if (ACPI_FAILURE (status)) {
264 return (status);
265 }
266
267 /*
268 * Now we can delete the original Reference Object and
269 * replace it with the resolve value
270 */
271
272 acpi_cm_remove_reference (stack_desc);
273 *stack_ptr = obj_desc;
274
275 break;
276
277
278 /*
279 * TBD: [Restructure] These next three opcodes change the type of
280 * the object, which is actually a no-no.
281 */
282
283 case AML_ZERO_OP:
284
285 stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
286 stack_desc->integer.value = 0;
287 break;
288
289
290 case AML_ONE_OP:
291
292 stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
293 stack_desc->integer.value = 1;
294 break;
295
296
297 case AML_ONES_OP:
298
299 stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
300 stack_desc->integer.value = ACPI_INTEGER_MAX;
301
302 /* Truncate value if we are executing from a 32-bit ACPI table */
303
304 acpi_aml_truncate_for32bit_table (stack_desc, walk_state);
305 break;
306
307
308 case AML_INDEX_OP:
309
310 switch (stack_desc->reference.target_type) {
311 case ACPI_TYPE_BUFFER_FIELD:
312
313 /* Just return - leave the Reference on the stack */
314 break;
315
316
317 case ACPI_TYPE_PACKAGE:
318 obj_desc = *stack_desc->reference.where;
319 if (obj_desc) {
320 /*
321 * Valid obj descriptor, copy pointer to return value
322 * (i.e., dereference the package index)
323 * Delete the ref object, increment the returned object
324 */
325 acpi_cm_remove_reference (stack_desc);
326 acpi_cm_add_reference (obj_desc);
327 *stack_ptr = obj_desc;
328 }
329
330 else {
331 /*
332 * A NULL object descriptor means an unitialized element of
333 * the package, can't deref it
334 */
335
336 status = AE_AML_UNINITIALIZED_ELEMENT;
337 }
338 break;
339
340 default:
341 /* Invalid reference OBJ*/
342
343 status = AE_AML_INTERNAL;
344 break;
345 }
346
347 break;
348
349
350 case AML_DEBUG_OP:
351
352 /* Just leave the object as-is */
353 break;
354
355
356 default:
357
358 status = AE_AML_INTERNAL;
359
360 } /* switch (Opcode) */
361
362
363 if (ACPI_FAILURE (status)) {
364 return (status);
365 }
366
367 break; /* case INTERNAL_TYPE_REFERENCE */
368
369
370 case ACPI_TYPE_FIELD_UNIT:
371
372 obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY);
373 if (!obj_desc) {
374 /* Descriptor allocation failure */
375
376 return (AE_NO_MEMORY);
377 }
378
379 status = acpi_aml_get_field_unit_value (stack_desc, obj_desc);
380 if (ACPI_FAILURE (status)) {
381 acpi_cm_remove_reference (obj_desc);
382 obj_desc = NULL;
383 }
384
385 *stack_ptr = (void *) obj_desc;
386 break;
387
388
389 case INTERNAL_TYPE_BANK_FIELD:
390
391 obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY);
392 if (!obj_desc) {
393 /* Descriptor allocation failure */
394
395 return (AE_NO_MEMORY);
396 }
397
398 status = acpi_aml_get_field_unit_value (stack_desc, obj_desc);
399 if (ACPI_FAILURE (status)) {
400 acpi_cm_remove_reference (obj_desc);
401 obj_desc = NULL;
402 }
403
404 *stack_ptr = (void *) obj_desc;
405 break;
406
407
408 /* TBD: [Future] - may need to handle Index_field, and Def_field someday */
409
410 default:
411
412 break;
413
414 } /* switch (Stack_desc->Common.Type) */
415
416
417 return (status);
418 }
419
420