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
);