- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / interpreter / amstore.c
blob8887e09978433b532d212b3b9c3da7b48cb58236
2 /******************************************************************************
4 * Module Name: amstore - AML Interpreter object store support
5 * $Revision: 117 $
7 *****************************************************************************/
9 /*
10 * Copyright (C) 2000 R. Byron Moore
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.
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.
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
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "acdispat.h"
31 #include "acinterp.h"
32 #include "amlcode.h"
33 #include "acnamesp.h"
34 #include "actables.h"
37 #define _COMPONENT INTERPRETER
38 MODULE_NAME ("amstore")
41 /*******************************************************************************
43 * FUNCTION: Acpi_aml_exec_store
45 * PARAMETERS: *Val_desc - Value to be stored
46 * *Dest_desc - Where to store it 0 Must be (ACPI_HANDLE)
47 * or an ACPI_OPERAND_OBJECT of type
48 * Reference; if the latter the descriptor
49 * will be either reused or deleted.
51 * RETURN: Status
53 * DESCRIPTION: Store the value described by Val_desc into the location
54 * described by Dest_desc. Called by various interpreter
55 * functions to store the result of an operation into
56 * the destination operand.
58 ******************************************************************************/
60 ACPI_STATUS
61 acpi_aml_exec_store (
62 ACPI_OPERAND_OBJECT *val_desc,
63 ACPI_OPERAND_OBJECT *dest_desc,
64 ACPI_WALK_STATE *walk_state)
66 ACPI_STATUS status = AE_OK;
67 ACPI_OPERAND_OBJECT *delete_dest_desc = NULL;
68 ACPI_OPERAND_OBJECT *tmp_desc;
69 ACPI_NAMESPACE_NODE *node = NULL;
70 u8 value = 0;
71 u32 length;
72 u32 i;
75 /* Validate parameters */
77 if (!val_desc || !dest_desc) {
78 return (AE_AML_NO_OPERAND);
81 /* Examine the datatype of the Dest_desc */
83 if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) {
84 /* Dest is an ACPI_HANDLE, create a new object */
86 node = (ACPI_NAMESPACE_NODE *) dest_desc;
87 dest_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
88 if (!dest_desc) {
89 /* Allocation failure */
91 return (AE_NO_MEMORY);
94 /* Build a new Reference wrapper around the handle */
96 dest_desc->reference.op_code = AML_NAME_OP;
97 dest_desc->reference.object = node;
101 /* Destination object must be of type Reference */
103 if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) {
104 /* Destination is not an Reference */
106 return (AE_AML_OPERAND_TYPE);
109 /* Examine the Reference opcode */
111 switch (dest_desc->reference.op_code)
114 case AML_NAME_OP:
117 * Storing into a Name
119 delete_dest_desc = dest_desc;
120 status = acpi_aml_store_object_to_node (val_desc, dest_desc->reference.object,
121 walk_state);
123 break; /* Case Name_op */
126 case AML_INDEX_OP:
128 delete_dest_desc = dest_desc;
131 * Valid source value and destination reference pointer.
133 * ACPI Specification 1.0B section 15.2.3.4.2.13:
134 * Destination should point to either a buffer or a package
138 * Actually, storing to a package is not so simple. The source must be
139 * evaluated and converted to the type of the destination and then the
140 * source is copied into the destination - we can't just point to the
141 * source object.
143 if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) {
145 * The object at *(Dest_desc->Reference.Where) is the
146 * element within the package that is to be modified.
148 tmp_desc = *(dest_desc->reference.where);
149 if (tmp_desc) {
151 * If the Destination element is a package, we will delete
152 * that object and construct a new one.
154 * TBD: [Investigate] Should both the src and dest be required
155 * to be packages?
156 * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE)
158 if (tmp_desc->common.type == ACPI_TYPE_PACKAGE) {
160 * Take away the reference for being part of a package and
161 * delete
163 acpi_cm_remove_reference (tmp_desc);
164 acpi_cm_remove_reference (tmp_desc);
166 tmp_desc = NULL;
170 if (!tmp_desc) {
172 * If the Tmp_desc is NULL, that means an uninitialized package
173 * has been used as a destination, therefore, we must create
174 * the destination element to match the type of the source
175 * element NOTE: Val_desc can be of any type.
177 tmp_desc = acpi_cm_create_internal_object (val_desc->common.type);
178 if (!tmp_desc) {
179 status = AE_NO_MEMORY;
180 goto cleanup;
184 * If the source is a package, copy the source to the new dest
186 if (ACPI_TYPE_PACKAGE == tmp_desc->common.type) {
187 status = acpi_aml_build_copy_internal_package_object (
188 val_desc, tmp_desc, walk_state);
189 if (ACPI_FAILURE (status)) {
190 acpi_cm_remove_reference (tmp_desc);
191 tmp_desc = NULL;
192 goto cleanup;
197 * Install the new descriptor into the package and add a
198 * reference to the newly created descriptor for now being
199 * part of the parent package
202 *(dest_desc->reference.where) = tmp_desc;
203 acpi_cm_add_reference (tmp_desc);
206 if (ACPI_TYPE_PACKAGE != tmp_desc->common.type) {
208 * The destination element is not a package, so we need to
209 * convert the contents of the source (Val_desc) and copy into
210 * the destination (Tmp_desc)
212 status = acpi_aml_store_object_to_object (val_desc, tmp_desc,
213 walk_state);
214 if (ACPI_FAILURE (status)) {
216 * An error occurrered when copying the internal object
217 * so delete the reference.
219 status = AE_AML_OPERAND_TYPE;
223 break;
227 * Check that the destination is a Buffer Field type
229 if (dest_desc->reference.target_type != ACPI_TYPE_BUFFER_FIELD) {
230 status = AE_AML_OPERAND_TYPE;
231 break;
235 * Storing into a buffer at a location defined by an Index.
237 * Each 8-bit element of the source object is written to the
238 * 8-bit Buffer Field of the Index destination object.
242 * Set the Tmp_desc to the destination object and type check.
244 tmp_desc = dest_desc->reference.object;
246 if (tmp_desc->common.type != ACPI_TYPE_BUFFER) {
247 status = AE_AML_OPERAND_TYPE;
248 break;
252 * The assignment of the individual elements will be slightly
253 * different for each source type.
256 switch (val_desc->common.type)
259 * If the type is Integer, the Length is 4.
260 * This loop to assign each of the elements is somewhat
261 * backward because of the Big Endian-ness of IA-64
263 case ACPI_TYPE_NUMBER:
264 length = 4;
265 for (i = length; i != 0; i--) {
266 value = (u8)(val_desc->number.value >> (MUL_8 (i - 1)));
267 tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
269 break;
272 * If the type is Buffer, the Length is in the structure.
273 * Just loop through the elements and assign each one in turn.
275 case ACPI_TYPE_BUFFER:
276 length = val_desc->buffer.length;
277 for (i = 0; i < length; i++) {
278 value = *(val_desc->buffer.pointer + i);
279 tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
281 break;
284 * If the type is String, the Length is in the structure.
285 * Just loop through the elements and assign each one in turn.
287 case ACPI_TYPE_STRING:
288 length = val_desc->string.length;
289 for (i = 0; i < length; i++) {
290 value = *(val_desc->string.pointer + i);
291 tmp_desc->buffer.pointer[dest_desc->reference.offset] = value;
293 break;
296 * If source is not a valid type so return an error.
298 default:
299 status = AE_AML_OPERAND_TYPE;
300 break;
304 * If we had an error, break out of this case statement.
306 if (ACPI_FAILURE (status)) {
307 break;
311 * Set the return pointer
313 dest_desc = tmp_desc;
315 break;
317 case AML_ZERO_OP:
318 case AML_ONE_OP:
319 case AML_ONES_OP:
322 * Storing to a constant is a no-op -- see ACPI Specification
323 * Delete the result descriptor.
326 delete_dest_desc = dest_desc;
327 break;
330 case AML_LOCAL_OP:
332 status = acpi_ds_method_data_set_value (MTH_TYPE_LOCAL,
333 (dest_desc->reference.offset), val_desc, walk_state);
334 delete_dest_desc = dest_desc;
335 break;
338 case AML_ARG_OP:
340 status = acpi_ds_method_data_set_value (MTH_TYPE_ARG,
341 (dest_desc->reference.offset), val_desc, walk_state);
342 delete_dest_desc = dest_desc;
343 break;
346 case AML_DEBUG_OP:
349 * Storing to the Debug object causes the value stored to be
350 * displayed and otherwise has no effect -- see ACPI Specification
353 delete_dest_desc = dest_desc;
354 break;
357 default:
359 /* TBD: [Restructure] use object dump routine !! */
361 delete_dest_desc = dest_desc;
362 status = AE_AML_INTERNAL;
364 } /* switch(Dest_desc->Reference.Op_code) */
367 cleanup:
369 /* Cleanup and exit*/
371 if (delete_dest_desc) {
372 acpi_cm_remove_reference (delete_dest_desc);
375 return (status);