:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / executer / amstorob.c
1
2 /******************************************************************************
3  *
4  * Module Name: amstorob - AML Interpreter object store support, store to object
5  *              $Revision$
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 #include "acparser.h"
30 #include "acdispat.h"
31 #include "acinterp.h"
32 #include "amlcode.h"
33 #include "acnamesp.h"
34 #include "actables.h"
35
36
37 #define _COMPONENT          ACPI_EXECUTER
38          MODULE_NAME         ("amstorob")
39
40
41 /*******************************************************************************
42  *
43  * FUNCTION:    Acpi_aml_copy_buffer_to_buffer
44  *
45  * PARAMETERS:  Source_desc         - Source object to copy
46  *              Target_desc         - Destination object of the copy
47  *
48  * RETURN:      Status
49  *
50  * DESCRIPTION: Copy a buffer object to another buffer object.
51  *
52  ******************************************************************************/
53
54 ACPI_STATUS
55 acpi_aml_copy_buffer_to_buffer (
56         ACPI_OPERAND_OBJECT     *source_desc,
57         ACPI_OPERAND_OBJECT     *target_desc)
58 {
59         u32                     length;
60         u8                      *buffer;
61
62
63         /*
64          * We know that Source_desc is a buffer by now
65          */
66         buffer = (u8 *) source_desc->buffer.pointer;
67         length = source_desc->buffer.length;
68
69         /*
70          * If target is a buffer of length zero, allocate a new
71          * buffer of the proper length
72          */
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);
77                 }
78
79                 target_desc->buffer.length = length;
80         }
81
82         /*
83          * Buffer is a static allocation,
84          * only place what will fit in the buffer.
85          */
86         if (length <= target_desc->buffer.length) {
87                 /* Clear existing buffer and copy in the new one */
88
89                 MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length);
90                 MEMCPY(target_desc->buffer.pointer, buffer, length);
91         }
92
93         else {
94                 /*
95                  * Truncate the source, copy only what will fit
96                  */
97                 MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length);
98
99         }
100
101         return (AE_OK);
102 }
103
104
105 /*******************************************************************************
106  *
107  * FUNCTION:    Acpi_aml_copy_string_to_string
108  *
109  * PARAMETERS:  Source_desc         - Source object to copy
110  *              Target_desc         - Destination object of the copy
111  *
112  * RETURN:      Status
113  *
114  * DESCRIPTION: Copy a String object to another String object
115  *
116  ******************************************************************************/
117
118 ACPI_STATUS
119 acpi_aml_copy_string_to_string (
120         ACPI_OPERAND_OBJECT     *source_desc,
121         ACPI_OPERAND_OBJECT     *target_desc)
122 {
123         u32                     length;
124         u8                      *buffer;
125
126
127         /*
128          * We know that Source_desc is a string by now.
129          */
130         buffer = (u8 *) source_desc->string.pointer;
131         length = source_desc->string.length;
132
133         /*
134          * Setting a string value replaces the old string
135          */
136         if (length < target_desc->string.length) {
137                 /* Clear old string and copy in the new one */
138
139                 MEMSET(target_desc->string.pointer, 0, target_desc->string.length);
140                 MEMCPY(target_desc->string.pointer, buffer, length);
141         }
142
143         else {
144                 /*
145                  * Free the current buffer, then allocate a buffer
146                  * large enough to hold the value
147                  */
148                 if (target_desc->string.pointer &&
149                         !acpi_tb_system_table_pointer (target_desc->string.pointer)) {
150                         /*
151                          * Only free if not a pointer into the DSDT
152                          */
153                         acpi_cm_free(target_desc->string.pointer);
154                 }
155
156                 target_desc->string.pointer = acpi_cm_allocate (length + 1);
157                 if (!target_desc->string.pointer) {
158                         return (AE_NO_MEMORY);
159                 }
160                 target_desc->string.length = length;
161
162
163                 MEMCPY(target_desc->string.pointer, buffer, length);
164         }
165
166         return (AE_OK);
167 }
168
169
170 /*******************************************************************************
171  *
172  * FUNCTION:    Acpi_aml_copy_integer_to_index_field
173  *
174  * PARAMETERS:  Source_desc         - Source object to copy
175  *              Target_desc         - Destination object of the copy
176  *
177  * RETURN:      Status
178  *
179  * DESCRIPTION: Write an Integer to an Index Field
180  *
181  ******************************************************************************/
182
183 ACPI_STATUS
184 acpi_aml_copy_integer_to_index_field (
185         ACPI_OPERAND_OBJECT     *source_desc,
186         ACPI_OPERAND_OBJECT     *target_desc)
187 {
188         ACPI_STATUS             status;
189         u8                      locked;
190
191
192         /*
193          * Get the global lock if needed
194          */
195         locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
196
197         /*
198          * Set Index value to select proper Data register
199          * perform the update (Set index)
200          */
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 */
207
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));
212
213         }
214
215
216
217         /*
218          * Release global lock if we acquired it earlier
219          */
220         acpi_aml_release_global_lock (locked);
221
222         return (status);
223 }
224
225
226 /*******************************************************************************
227  *
228  * FUNCTION:    Acpi_aml_copy_integer_to_bank_field
229  *
230  * PARAMETERS:  Source_desc         - Source object to copy
231  *              Target_desc         - Destination object of the copy
232  *
233  * RETURN:      Status
234  *
235  * DESCRIPTION: Write an Integer to a Bank Field
236  *
237  ******************************************************************************/
238
239 ACPI_STATUS
240 acpi_aml_copy_integer_to_bank_field (
241         ACPI_OPERAND_OBJECT     *source_desc,
242         ACPI_OPERAND_OBJECT     *target_desc)
243 {
244         ACPI_STATUS             status;
245         u8                      locked;
246
247
248         /*
249          * Get the global lock if needed
250          */
251         locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule);
252
253
254         /*
255          * Set Bank value to select proper Bank
256          * Perform the update (Set Bank Select)
257          */
258
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  */
265
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));
270         }
271
272
273
274         /*
275          * Release global lock if we acquired it earlier
276          */
277         acpi_aml_release_global_lock (locked);
278
279         return (status);
280 }
281
282
283 /*******************************************************************************
284  *
285  * FUNCTION:    Acpi_aml_copy_data_to_named_field
286  *
287  * PARAMETERS:  Source_desc         - Source object to copy
288  *              Node                - Destination Namespace node
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: Copy raw data to a Named Field.  No implicit conversion
293  *              is performed on the source object
294  *
295  ******************************************************************************/
296
297 ACPI_STATUS
298 acpi_aml_copy_data_to_named_field (
299         ACPI_OPERAND_OBJECT     *source_desc,
300         ACPI_NAMESPACE_NODE     *node)
301 {
302         ACPI_STATUS             status;
303         u8                      locked;
304         u32                     length;
305         u8                      *buffer;
306
307
308         /*
309          * Named fields (Create_xxx_field) - We don't perform any conversions on the
310          * source operand, just use the raw data
311          */
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);
316                 break;
317
318         case ACPI_TYPE_BUFFER:
319                 buffer = (u8 *) source_desc->buffer.pointer;
320                 length = source_desc->buffer.length;
321                 break;
322
323         case ACPI_TYPE_STRING:
324                 buffer = (u8 *) source_desc->string.pointer;
325                 length = source_desc->string.length;
326                 break;
327
328         default:
329                 return (AE_TYPE);
330         }
331
332         /*
333          * Get the global lock if needed before the update
334          * TBD: not needed!
335          */
336         locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule);
337
338         status = acpi_aml_access_named_field (ACPI_WRITE,
339                           node, buffer, length);
340
341         acpi_aml_release_global_lock (locked);
342
343         return (status);
344 }
345
346
347 /*******************************************************************************
348  *
349  * FUNCTION:    Acpi_aml_copy_integer_to_field_unit
350  *
351  * PARAMETERS:  Source_desc         - Source object to copy
352  *              Target_desc         - Destination object of the copy
353  *
354  * RETURN:      Status
355  *
356  * DESCRIPTION: Write an Integer to a Field Unit.
357  *
358  ******************************************************************************/
359
360 ACPI_STATUS
361 acpi_aml_copy_integer_to_field_unit (
362         ACPI_OPERAND_OBJECT     *source_desc,
363         ACPI_OPERAND_OBJECT     *target_desc)
364 {
365         ACPI_STATUS             status = AE_OK;
366         u8                      *location = NULL;
367         u32                     mask;
368         u32                     new_value;
369         u8                      locked = FALSE;
370
371
372         /*
373          * If the Field Buffer and Index have not been previously evaluated,
374          * evaluate them and save the results.
375          */
376         if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) {
377                 status = acpi_ds_get_field_unit_arguments (target_desc);
378                 if (ACPI_FAILURE (status)) {
379                         return (status);
380                 }
381         }
382
383         if ((!target_desc->field_unit.container ||
384                 ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type)) {
385                 return (AE_AML_INTERNAL);
386         }
387
388         /*
389          * Get the global lock if needed
390          */
391         locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule);
392
393         /*
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!!
397          */
398         if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) {
399                 return (AE_NOT_IMPLEMENTED);
400         }
401
402         /* Field location is (base of buffer) + (byte offset) */
403
404         location = target_desc->field_unit.container->buffer.pointer
405                           + target_desc->field_unit.offset;
406
407         /*
408          * Construct Mask with 1 bits where the field is,
409          * 0 bits elsewhere
410          */
411         mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1
412                            << target_desc->field_unit.bit_offset);
413
414         /* Zero out the field in the buffer */
415
416         MOVE_UNALIGNED32_TO_32 (&new_value, location);
417         new_value &= ~mask;
418
419         /*
420          * Shift and mask the new value into position,
421          * and or it into the buffer.
422          */
423         new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) &
424                          mask;
425
426         /* Store back the value */
427
428         MOVE_UNALIGNED32_TO_32 (location, &new_value);
429
430         return (AE_OK);
431 }
432
433