scroll mode for very long start menus
[reactos.git] / reactos / drivers / bus / acpi / executer / amstorob.c
1
2 /******************************************************************************
3 *
4 * Module Name: amstorob - AML Interpreter object store support, store to object
5 * $Revision: 1.1 $
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