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
31 #define _COMPONENT ACPI_EXECUTER
32 MODULE_NAME ("amstorob")
35 /*******************************************************************************
37 * FUNCTION: Acpi_aml_copy_buffer_to_buffer
39 * PARAMETERS: Source_desc - Source object to copy
40 * Target_desc - Destination object of the copy
44 * DESCRIPTION: Copy a buffer object to another buffer object.
46 ******************************************************************************/
49 acpi_aml_copy_buffer_to_buffer (
50 ACPI_OPERAND_OBJECT
*source_desc
,
51 ACPI_OPERAND_OBJECT
*target_desc
)
58 * We know that Source_desc is a buffer by now
60 buffer
= (u8
*) source_desc
->buffer
.pointer
;
61 length
= source_desc
->buffer
.length
;
64 * If target is a buffer of length zero, allocate a new
65 * buffer of the proper length
67 if (target_desc
->buffer
.length
== 0) {
68 target_desc
->buffer
.pointer
= acpi_cm_allocate (length
);
69 if (!target_desc
->buffer
.pointer
) {
70 return (AE_NO_MEMORY
);
73 target_desc
->buffer
.length
= length
;
77 * Buffer is a static allocation,
78 * only place what will fit in the buffer.
80 if (length
<= target_desc
->buffer
.length
) {
81 /* Clear existing buffer and copy in the new one */
83 MEMSET(target_desc
->buffer
.pointer
, 0, target_desc
->buffer
.length
);
84 MEMCPY(target_desc
->buffer
.pointer
, buffer
, length
);
89 * Truncate the source, copy only what will fit
91 MEMCPY(target_desc
->buffer
.pointer
, buffer
, target_desc
->buffer
.length
);
99 /*******************************************************************************
101 * FUNCTION: Acpi_aml_copy_string_to_string
103 * PARAMETERS: Source_desc - Source object to copy
104 * Target_desc - Destination object of the copy
108 * DESCRIPTION: Copy a String object to another String object
110 ******************************************************************************/
113 acpi_aml_copy_string_to_string (
114 ACPI_OPERAND_OBJECT
*source_desc
,
115 ACPI_OPERAND_OBJECT
*target_desc
)
122 * We know that Source_desc is a string by now.
124 buffer
= (u8
*) source_desc
->string
.pointer
;
125 length
= source_desc
->string
.length
;
128 * Setting a string value replaces the old string
130 if (length
< target_desc
->string
.length
) {
131 /* Clear old string and copy in the new one */
133 MEMSET(target_desc
->string
.pointer
, 0, target_desc
->string
.length
);
134 MEMCPY(target_desc
->string
.pointer
, buffer
, length
);
139 * Free the current buffer, then allocate a buffer
140 * large enough to hold the value
142 if (target_desc
->string
.pointer
&&
143 !acpi_tb_system_table_pointer (target_desc
->string
.pointer
)) {
145 * Only free if not a pointer into the DSDT
147 acpi_cm_free(target_desc
->string
.pointer
);
150 target_desc
->string
.pointer
= acpi_cm_allocate (length
+ 1);
151 if (!target_desc
->string
.pointer
) {
152 return (AE_NO_MEMORY
);
154 target_desc
->string
.length
= length
;
157 MEMCPY(target_desc
->string
.pointer
, buffer
, length
);
164 /*******************************************************************************
166 * FUNCTION: Acpi_aml_copy_integer_to_index_field
168 * PARAMETERS: Source_desc - Source object to copy
169 * Target_desc - Destination object of the copy
173 * DESCRIPTION: Write an Integer to an Index Field
175 ******************************************************************************/
178 acpi_aml_copy_integer_to_index_field (
179 ACPI_OPERAND_OBJECT
*source_desc
,
180 ACPI_OPERAND_OBJECT
*target_desc
)
187 * Get the global lock if needed
189 locked
= acpi_aml_acquire_global_lock (target_desc
->index_field
.lock_rule
);
192 * Set Index value to select proper Data register
193 * perform the update (Set index)
195 status
= acpi_aml_access_named_field (ACPI_WRITE
,
196 target_desc
->index_field
.index
,
197 &target_desc
->index_field
.value
,
198 sizeof (target_desc
->index_field
.value
));
199 if (ACPI_SUCCESS (status
)) {
200 /* Set_index was successful, next set Data value */
202 status
= acpi_aml_access_named_field (ACPI_WRITE
,
203 target_desc
->index_field
.data
,
204 &source_desc
->integer
.value
,
205 sizeof (source_desc
->integer
.value
));
212 * Release global lock if we acquired it earlier
214 acpi_aml_release_global_lock (locked
);
220 /*******************************************************************************
222 * FUNCTION: Acpi_aml_copy_integer_to_bank_field
224 * PARAMETERS: Source_desc - Source object to copy
225 * Target_desc - Destination object of the copy
229 * DESCRIPTION: Write an Integer to a Bank Field
231 ******************************************************************************/
234 acpi_aml_copy_integer_to_bank_field (
235 ACPI_OPERAND_OBJECT
*source_desc
,
236 ACPI_OPERAND_OBJECT
*target_desc
)
243 * Get the global lock if needed
245 locked
= acpi_aml_acquire_global_lock (target_desc
->index_field
.lock_rule
);
249 * Set Bank value to select proper Bank
250 * Perform the update (Set Bank Select)
253 status
= acpi_aml_access_named_field (ACPI_WRITE
,
254 target_desc
->bank_field
.bank_select
,
255 &target_desc
->bank_field
.value
,
256 sizeof (target_desc
->bank_field
.value
));
257 if (ACPI_SUCCESS (status
)) {
258 /* Set bank select successful, set data value */
260 status
= acpi_aml_access_named_field (ACPI_WRITE
,
261 target_desc
->bank_field
.bank_select
,
262 &source_desc
->bank_field
.value
,
263 sizeof (source_desc
->bank_field
.value
));
269 * Release global lock if we acquired it earlier
271 acpi_aml_release_global_lock (locked
);
277 /*******************************************************************************
279 * FUNCTION: Acpi_aml_copy_data_to_named_field
281 * PARAMETERS: Source_desc - Source object to copy
282 * Node - Destination Namespace node
286 * DESCRIPTION: Copy raw data to a Named Field. No implicit conversion
287 * is performed on the source object
289 ******************************************************************************/
292 acpi_aml_copy_data_to_named_field (
293 ACPI_OPERAND_OBJECT
*source_desc
,
294 ACPI_NAMESPACE_NODE
*node
)
303 * Named fields (Create_xxx_field) - We don't perform any conversions on the
304 * source operand, just use the raw data
306 switch (source_desc
->common
.type
) {
307 case ACPI_TYPE_INTEGER
:
308 buffer
= (u8
*) &source_desc
->integer
.value
;
309 length
= sizeof (source_desc
->integer
.value
);
312 case ACPI_TYPE_BUFFER
:
313 buffer
= (u8
*) source_desc
->buffer
.pointer
;
314 length
= source_desc
->buffer
.length
;
317 case ACPI_TYPE_STRING
:
318 buffer
= (u8
*) source_desc
->string
.pointer
;
319 length
= source_desc
->string
.length
;
327 * Get the global lock if needed before the update
330 locked
= acpi_aml_acquire_global_lock (source_desc
->field
.lock_rule
);
332 status
= acpi_aml_access_named_field (ACPI_WRITE
,
333 node
, buffer
, length
);
335 acpi_aml_release_global_lock (locked
);
341 /*******************************************************************************
343 * FUNCTION: Acpi_aml_copy_integer_to_field_unit
345 * PARAMETERS: Source_desc - Source object to copy
346 * Target_desc - Destination object of the copy
350 * DESCRIPTION: Write an Integer to a Field Unit.
352 ******************************************************************************/
355 acpi_aml_copy_integer_to_field_unit (
356 ACPI_OPERAND_OBJECT
*source_desc
,
357 ACPI_OPERAND_OBJECT
*target_desc
)
359 ACPI_STATUS status
= AE_OK
;
367 * If the Field Buffer and Index have not been previously evaluated,
368 * evaluate them and save the results.
370 if (!(target_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
371 status
= acpi_ds_get_field_unit_arguments (target_desc
);
372 if (ACPI_FAILURE (status
)) {
377 if ((!target_desc
->field_unit
.container
||
378 ACPI_TYPE_BUFFER
!= target_desc
->field_unit
.container
->common
.type
)) {
379 return (AE_AML_INTERNAL
);
383 * Get the global lock if needed
385 locked
= acpi_aml_acquire_global_lock (target_desc
->field_unit
.lock_rule
);
388 * TBD: [Unhandled] REMOVE this limitation
389 * Make sure the operation is within the limits of our implementation
390 * this is not a Spec limitation!!
392 if (target_desc
->field_unit
.length
+ target_desc
->field_unit
.bit_offset
> 32) {
393 return (AE_NOT_IMPLEMENTED
);
396 /* Field location is (base of buffer) + (byte offset) */
398 location
= target_desc
->field_unit
.container
->buffer
.pointer
399 + target_desc
->field_unit
.offset
;
402 * Construct Mask with 1 bits where the field is,
405 mask
= ((u32
) 1 << target_desc
->field_unit
.length
) - ((u32
)1
406 << target_desc
->field_unit
.bit_offset
);
408 /* Zero out the field in the buffer */
410 MOVE_UNALIGNED32_TO_32 (&new_value
, location
);
414 * Shift and mask the new value into position,
415 * and or it into the buffer.
417 new_value
|= (source_desc
->integer
.value
<< target_desc
->field_unit
.bit_offset
) &
420 /* Store back the value */
422 MOVE_UNALIGNED32_TO_32 (location
, &new_value
);