2 /******************************************************************************
4 * Module Name: amstorob - AML Interpreter object store support, store to object
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 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
37 #define _COMPONENT ACPI_EXECUTER
38 MODULE_NAME ("amstorob")
41 /*******************************************************************************
43 * FUNCTION: Acpi_aml_copy_buffer_to_buffer
45 * PARAMETERS: Source_desc - Source object to copy
46 * Target_desc - Destination object of the copy
50 * DESCRIPTION: Copy a buffer object to another buffer object.
52 ******************************************************************************/
55 acpi_aml_copy_buffer_to_buffer (
56 ACPI_OPERAND_OBJECT *source_desc,
57 ACPI_OPERAND_OBJECT *target_desc)
64 * We know that Source_desc is a buffer by now
66 buffer = (u8 *) source_desc->buffer.pointer;
67 length = source_desc->buffer.length;
70 * If target is a buffer of length zero, allocate a new
71 * buffer of the proper length
73 if (target_desc->buffer.length == 0) {
74 target_desc->buffer.pointer = acpi_cm_allocate (length);
75 if (!target_desc->buffer.pointer) {
76 return (AE_NO_MEMORY);
79 target_desc->buffer.length = length;
83 * Buffer is a static allocation,
84 * only place what will fit in the buffer.
86 if (length <= target_desc->buffer.length) {
87 /* Clear existing buffer and copy in the new one */
89 MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length);
90 MEMCPY(target_desc->buffer.pointer, buffer, length);
95 * Truncate the source, copy only what will fit
97 MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length);
105 /*******************************************************************************
107 * FUNCTION: Acpi_aml_copy_string_to_string
109 * PARAMETERS: Source_desc - Source object to copy
110 * Target_desc - Destination object of the copy
114 * DESCRIPTION: Copy a String object to another String object
116 ******************************************************************************/
119 acpi_aml_copy_string_to_string (
120 ACPI_OPERAND_OBJECT *source_desc,
121 ACPI_OPERAND_OBJECT *target_desc)
128 * We know that Source_desc is a string by now.
130 buffer = (u8 *) source_desc->string.pointer;
131 length = source_desc->string.length;
134 * Setting a string value replaces the old string
136 if (length < target_desc->string.length) {
137 /* Clear old string and copy in the new one */
139 MEMSET(target_desc->string.pointer, 0, target_desc->string.length);
140 MEMCPY(target_desc->string.pointer, buffer, length);
145 * Free the current buffer, then allocate a buffer
146 * large enough to hold the value
148 if (target_desc->string.pointer &&
149 !acpi_tb_system_table_pointer (target_desc->string.pointer)) {
151 * Only free if not a pointer into the DSDT
153 acpi_cm_free(target_desc->string.pointer);
156 target_desc->string.pointer = acpi_cm_allocate (length + 1);
157 if (!target_desc->string.pointer) {
158 return (AE_NO_MEMORY);
160 target_desc->string.length = length;
163 MEMCPY(target_desc->string.pointer, buffer, length);
170 /*******************************************************************************
172 * FUNCTION: Acpi_aml_copy_integer_to_index_field
174 * PARAMETERS: Source_desc - Source object to copy
175 * Target_desc - Destination object of the copy
179 * DESCRIPTION: Write an Integer to an Index Field
181 ******************************************************************************/
184 acpi_aml_copy_integer_to_index_field (
185 ACPI_OPERAND_OBJECT *source_desc,
186 ACPI_OPERAND_OBJECT *target_desc)
193 * Get the global lock if needed
195 locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
198 * Set Index value to select proper Data register
199 * perform the update (Set index)
201 status = acpi_aml_access_named_field (ACPI_WRITE,
202 target_desc->index_field.index,
203 &target_desc->index_field.value,
204 sizeof (target_desc->index_field.value));
205 if (ACPI_SUCCESS (status)) {
206 /* Set_index was successful, next set Data value */
208 status = acpi_aml_access_named_field (ACPI_WRITE,
209 target_desc->index_field.data,
210 &source_desc->integer.value,
211 sizeof (source_desc->integer.value));
218 * Release global lock if we acquired it earlier
220 acpi_aml_release_global_lock (locked);
226 /*******************************************************************************
228 * FUNCTION: Acpi_aml_copy_integer_to_bank_field
230 * PARAMETERS: Source_desc - Source object to copy
231 * Target_desc - Destination object of the copy
235 * DESCRIPTION: Write an Integer to a Bank Field
237 ******************************************************************************/
240 acpi_aml_copy_integer_to_bank_field (
241 ACPI_OPERAND_OBJECT *source_desc,
242 ACPI_OPERAND_OBJECT *target_desc)
249 * Get the global lock if needed
251 locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
255 * Set Bank value to select proper Bank
256 * Perform the update (Set Bank Select)
259 status = acpi_aml_access_named_field (ACPI_WRITE,
260 target_desc->bank_field.bank_select,
261 &target_desc->bank_field.value,
262 sizeof (target_desc->bank_field.value));
263 if (ACPI_SUCCESS (status)) {
264 /* Set bank select successful, set data value */
266 status = acpi_aml_access_named_field (ACPI_WRITE,
267 target_desc->bank_field.bank_select,
268 &source_desc->bank_field.value,
269 sizeof (source_desc->bank_field.value));
275 * Release global lock if we acquired it earlier
277 acpi_aml_release_global_lock (locked);
283 /*******************************************************************************
285 * FUNCTION: Acpi_aml_copy_data_to_named_field
287 * PARAMETERS: Source_desc - Source object to copy
288 * Node - Destination Namespace node
292 * DESCRIPTION: Copy raw data to a Named Field. No implicit conversion
293 * is performed on the source object
295 ******************************************************************************/
298 acpi_aml_copy_data_to_named_field (
299 ACPI_OPERAND_OBJECT *source_desc,
300 ACPI_NAMESPACE_NODE *node)
309 * Named fields (Create_xxx_field) - We don't perform any conversions on the
310 * source operand, just use the raw data
312 switch (source_desc->common.type) {
313 case ACPI_TYPE_INTEGER:
314 buffer = (u8 *) &source_desc->integer.value;
315 length = sizeof (source_desc->integer.value);
318 case ACPI_TYPE_BUFFER:
319 buffer = (u8 *) source_desc->buffer.pointer;
320 length = source_desc->buffer.length;
323 case ACPI_TYPE_STRING:
324 buffer = (u8 *) source_desc->string.pointer;
325 length = source_desc->string.length;
333 * Get the global lock if needed before the update
336 locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule);
338 status = acpi_aml_access_named_field (ACPI_WRITE,
339 node, buffer, length);
341 acpi_aml_release_global_lock (locked);
347 /*******************************************************************************
349 * FUNCTION: Acpi_aml_copy_integer_to_field_unit
351 * PARAMETERS: Source_desc - Source object to copy
352 * Target_desc - Destination object of the copy
356 * DESCRIPTION: Write an Integer to a Field Unit.
358 ******************************************************************************/
361 acpi_aml_copy_integer_to_field_unit (
362 ACPI_OPERAND_OBJECT *source_desc,
363 ACPI_OPERAND_OBJECT *target_desc)
365 ACPI_STATUS status = AE_OK;
373 * If the Field Buffer and Index have not been previously evaluated,
374 * evaluate them and save the results.
376 if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) {
377 status = acpi_ds_get_field_unit_arguments (target_desc);
378 if (ACPI_FAILURE (status)) {
383 if ((!target_desc->field_unit.container ||
384 ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type)) {
385 return (AE_AML_INTERNAL);
389 * Get the global lock if needed
391 locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule);
394 * TBD: [Unhandled] REMOVE this limitation
395 * Make sure the operation is within the limits of our implementation
396 * this is not a Spec limitation!!
398 if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) {
399 return (AE_NOT_IMPLEMENTED);
402 /* Field location is (base of buffer) + (byte offset) */
404 location = target_desc->field_unit.container->buffer.pointer
405 + target_desc->field_unit.offset;
408 * Construct Mask with 1 bits where the field is,
411 mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1
412 << target_desc->field_unit.bit_offset);
414 /* Zero out the field in the buffer */
416 MOVE_UNALIGNED32_TO_32 (&new_value, location);
420 * Shift and mask the new value into position,
421 * and or it into the buffer.
423 new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) &
426 /* Store back the value */
428 MOVE_UNALIGNED32_TO_32 (location, &new_value);