:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / executer / amconvrt.c
1 /******************************************************************************
2  *
3  * Module Name: amconvrt - Object conversion routines
4  *              $Revision$
5  *
6  *****************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "acparser.h"
29 #include "acnamesp.h"
30 #include "acinterp.h"
31 #include "acevents.h"
32 #include "amlcode.h"
33 #include "acdispat.h"
34
35
36 #define _COMPONENT          ACPI_EXECUTER
37          MODULE_NAME         ("amconvrt")
38
39
40 /*******************************************************************************
41  *
42  * FUNCTION:    Acpi_aml_convert_to_integer
43  *
44  * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
45  *                                Integer, Buffer, or String
46  *              Walk_state      - Current method state
47  *
48  * RETURN:      Status
49  *
50  * DESCRIPTION: Convert an ACPI Object to an integer.
51  *
52  ******************************************************************************/
53
54 ACPI_STATUS
55 acpi_aml_convert_to_integer (
56         ACPI_OPERAND_OBJECT     **obj_desc,
57         ACPI_WALK_STATE         *walk_state)
58 {
59         u32                     i;
60         ACPI_OPERAND_OBJECT     *ret_desc;
61         u32                     count;
62         char                    *pointer;
63         ACPI_INTEGER            result;
64         u32                     integer_size = sizeof (ACPI_INTEGER);
65
66
67         switch ((*obj_desc)->common.type) {
68         case ACPI_TYPE_INTEGER:
69                 return (AE_OK);
70
71         case ACPI_TYPE_STRING:
72                 pointer = (*obj_desc)->string.pointer;
73                 count = (*obj_desc)->string.length;
74                 break;
75
76         case ACPI_TYPE_BUFFER:
77                 pointer = (char *) (*obj_desc)->buffer.pointer;
78                 count = (*obj_desc)->buffer.length;
79                 break;
80
81         default:
82                 return (AE_TYPE);
83         }
84
85         /*
86          * Create a new integer
87          */
88         ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
89         if (!ret_desc) {
90                 return (AE_NO_MEMORY);
91         }
92
93
94         /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
95
96         if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
97                 /*
98                  * We are running a method that exists in a 32-bit ACPI table.
99                  * Truncate the value to 32 bits by zeroing out the upper 32-bit field
100                  */
101                 integer_size = sizeof (u32);
102         }
103
104
105         /*
106          * Convert the buffer/string to an integer.  Note that both buffers and
107          * strings are treated as raw data - we don't convert ascii to hex for
108          * strings.
109          *
110          * There are two terminating conditions for the loop:
111          * 1) The size of an integer has been reached, or
112          * 2) The end of the buffer or string has been reached
113          */
114         result = 0;
115
116         /* Transfer no more than an integer's worth of data */
117
118         if (count > integer_size) {
119                 count = integer_size;
120         }
121
122         /*
123          * String conversion is different than Buffer conversion
124          */
125         switch ((*obj_desc)->common.type) {
126         case ACPI_TYPE_STRING:
127
128                 /* TBD: Need to use 64-bit STRTOUL */
129
130                 /*
131                  * Convert string to an integer
132                  * String must be hexadecimal as per the ACPI specification
133                  */
134
135                 result = STRTOUL (pointer, NULL, 16);
136                 break;
137
138
139         case ACPI_TYPE_BUFFER:
140
141                 /*
142                  * Buffer conversion - we simply grab enough raw data from the
143                  * buffer to fill an integer
144                  */
145                 for (i = 0; i < count; i++) {
146                         /*
147                          * Get next byte and shift it into the Result.
148                          * Little endian is used, meaning that the first byte of the buffer
149                          * is the LSB of the integer
150                          */
151                         result |= (((ACPI_INTEGER) pointer[i]) << (i * 8));
152                 }
153
154                 break;
155         }
156
157         /* Save the Result, delete original descriptor, store new descriptor */
158
159         ret_desc->integer.value = result;
160
161         if (walk_state->opcode != AML_STORE_OP) {
162                 acpi_cm_remove_reference (*obj_desc);
163         }
164
165         *obj_desc = ret_desc;
166
167         return (AE_OK);
168 }
169
170
171 /*******************************************************************************
172  *
173  * FUNCTION:    Acpi_aml_convert_to_buffer
174  *
175  * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
176  *                                Integer, Buffer, or String
177  *              Walk_state      - Current method state
178  *
179  * RETURN:      Status
180  *
181  * DESCRIPTION: Convert an ACPI Object to an Buffer
182  *
183  ******************************************************************************/
184
185 ACPI_STATUS
186 acpi_aml_convert_to_buffer (
187         ACPI_OPERAND_OBJECT     **obj_desc,
188         ACPI_WALK_STATE         *walk_state)
189 {
190         ACPI_OPERAND_OBJECT     *ret_desc;
191         u32                     i;
192         u32                     integer_size = sizeof (ACPI_INTEGER);
193         u8                      *new_buf;
194
195
196         switch ((*obj_desc)->common.type) {
197         case ACPI_TYPE_INTEGER:
198
199                 /*
200                  * Create a new Buffer
201                  */
202                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
203                 if (!ret_desc) {
204                         return (AE_NO_MEMORY);
205                 }
206
207                 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
208
209                 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
210                         /*
211                          * We are running a method that exists in a 32-bit ACPI table.
212                          * Truncate the value to 32 bits by zeroing out the upper
213                          * 32-bit field
214                          */
215                         integer_size = sizeof (u32);
216                 }
217
218                 /* Need enough space for one integers */
219
220                 ret_desc->buffer.length = integer_size;
221                 new_buf = acpi_cm_callocate (integer_size);
222                 if (!new_buf) {
223                         REPORT_ERROR
224                                 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
225                         acpi_cm_remove_reference (ret_desc);
226                         return (AE_NO_MEMORY);
227                 }
228
229                 /* Copy the integer to the buffer */
230
231                 for (i = 0; i < integer_size; i++) {
232                         new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8));
233                 }
234                 ret_desc->buffer.pointer = new_buf;
235
236                 /* Return the new buffer descriptor */
237
238                 if (walk_state->opcode != AML_STORE_OP) {
239                         acpi_cm_remove_reference (*obj_desc);
240                 }
241                 *obj_desc = ret_desc;
242                 break;
243
244
245         case ACPI_TYPE_STRING:
246                 break;
247
248
249         case ACPI_TYPE_BUFFER:
250                 break;
251
252
253         default:
254                 return (AE_TYPE);
255                 break;
256    }
257
258         return (AE_OK);
259 }
260
261
262 /*******************************************************************************
263  *
264  * FUNCTION:    Acpi_aml_convert_to_string
265  *
266  * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
267  *                                Integer, Buffer, or String
268  *              Walk_state      - Current method state
269  *
270  * RETURN:      Status
271  *
272  * DESCRIPTION: Convert an ACPI Object to a string
273  *
274  ******************************************************************************/
275
276 ACPI_STATUS
277 acpi_aml_convert_to_string (
278         ACPI_OPERAND_OBJECT     **obj_desc,
279         ACPI_WALK_STATE         *walk_state)
280 {
281         ACPI_OPERAND_OBJECT     *ret_desc;
282         u32                     i;
283         u32                     index;
284         u32                     integer_size = sizeof (ACPI_INTEGER);
285         u8                      *new_buf;
286         u8                      *pointer;
287
288
289         switch ((*obj_desc)->common.type) {
290         case ACPI_TYPE_INTEGER:
291
292                 /*
293                  * Create a new String
294                  */
295                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
296                 if (!ret_desc) {
297                         return (AE_NO_MEMORY);
298                 }
299
300                 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
301
302                 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
303                         /*
304                          * We are running a method that exists in a 32-bit ACPI table.
305                          * Truncate the value to 32 bits by zeroing out the upper
306                          * 32-bit field
307                          */
308                         integer_size = sizeof (u32);
309                 }
310
311                 /* Need enough space for one ASCII integer plus null terminator */
312
313                 ret_desc->string.length = (integer_size * 2) + 1;
314                 new_buf = acpi_cm_callocate (ret_desc->string.length);
315                 if (!new_buf) {
316                         REPORT_ERROR
317                                 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
318                         acpi_cm_remove_reference (ret_desc);
319                         return (AE_NO_MEMORY);
320                 }
321
322                 /* Copy the integer to the buffer */
323
324                 for (i = 0; i < (integer_size * 2); i++) {
325                         new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF];
326                 }
327
328                 /* Null terminate */
329
330                 new_buf [i] = 0;
331                 ret_desc->buffer.pointer = new_buf;
332
333                 /* Return the new buffer descriptor */
334
335                 if (walk_state->opcode != AML_STORE_OP) {
336                         acpi_cm_remove_reference (*obj_desc);
337                 }
338                 *obj_desc = ret_desc;
339
340                 return (AE_OK);
341
342
343         case ACPI_TYPE_BUFFER:
344
345                 if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) {
346                         return (AE_AML_STRING_LIMIT);
347                 }
348
349                 /*
350                  * Create a new String
351                  */
352                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
353                 if (!ret_desc) {
354                         return (AE_NO_MEMORY);
355                 }
356
357                 /* Need enough space for one ASCII integer plus null terminator */
358
359                 ret_desc->string.length = (*obj_desc)->buffer.length * 3;
360                 new_buf = acpi_cm_callocate (ret_desc->string.length + 1);
361                 if (!new_buf) {
362                         REPORT_ERROR
363                                 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
364                         acpi_cm_remove_reference (ret_desc);
365                         return (AE_NO_MEMORY);
366                 }
367
368                 /*
369                  * Convert each byte of the buffer to two ASCII characters plus a space.
370                  */
371                 pointer = (*obj_desc)->buffer.pointer;
372                 index = 0;
373                 for (i = 0; i < (*obj_desc)->buffer.length; i++) {
374                         new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F];
375                         new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F];
376                         new_buf[index + 2] = ' ';
377                         index += 3;
378                 }
379
380                 /* Null terminate */
381
382                 new_buf [index] = 0;
383                 ret_desc->buffer.pointer = new_buf;
384
385                 /* Return the new buffer descriptor */
386
387                 if (walk_state->opcode != AML_STORE_OP) {
388                         acpi_cm_remove_reference (*obj_desc);
389                 }
390                 *obj_desc = ret_desc;
391                 break;
392
393
394         case ACPI_TYPE_STRING:
395                 break;
396
397
398         default:
399                 return (AE_TYPE);
400                 break;
401    }
402
403         return (AE_OK);
404 }
405
406
407 /*******************************************************************************
408  *
409  * FUNCTION:    Acpi_aml_convert_to_target_type
410  *
411  * PARAMETERS:  *Obj_desc       - Object to be converted.
412  *              Walk_state      - Current method state
413  *
414  * RETURN:      Status
415  *
416  * DESCRIPTION:
417  *
418  ******************************************************************************/
419
420 ACPI_STATUS
421 acpi_aml_convert_to_target_type (
422         OBJECT_TYPE_INTERNAL    destination_type,
423         ACPI_OPERAND_OBJECT     **obj_desc,
424         ACPI_WALK_STATE         *walk_state)
425 {
426         ACPI_STATUS             status = AE_OK;
427
428
429         /*
430          * If required by the target,
431          * perform implicit conversion on the source before we store it.
432          */
433
434         switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
435         case ARGI_SIMPLE_TARGET:
436         case ARGI_FIXED_TARGET:
437         case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
438
439                 switch (destination_type) {
440                 case INTERNAL_TYPE_DEF_FIELD:
441                         /*
442                          * Named field can always handle conversions
443                          */
444                         break;
445
446                 default:
447                         /* No conversion allowed for these types */
448
449                         if (destination_type != (*obj_desc)->common.type) {
450                                 status = AE_TYPE;
451                         }
452                 }
453                 break;
454
455
456         case ARGI_TARGETREF:
457
458                 switch (destination_type) {
459                 case ACPI_TYPE_INTEGER:
460                 case ACPI_TYPE_FIELD_UNIT:
461                 case INTERNAL_TYPE_BANK_FIELD:
462                 case INTERNAL_TYPE_INDEX_FIELD:
463                         /*
464                          * These types require an Integer operand.  We can convert
465                          * a Buffer or a String to an Integer if necessary.
466                          */
467                         status = acpi_aml_convert_to_integer (obj_desc, walk_state);
468                         break;
469
470
471                 case ACPI_TYPE_STRING:
472
473                         /*
474                          * The operand must be a String.  We can convert an
475                          * Integer or Buffer if necessary
476                          */
477                         status = acpi_aml_convert_to_string (obj_desc, walk_state);
478                         break;
479
480
481                 case ACPI_TYPE_BUFFER:
482
483                         /*
484                          * The operand must be a String.  We can convert an
485                          * Integer or Buffer if necessary
486                          */
487                         status = acpi_aml_convert_to_buffer (obj_desc, walk_state);
488                         break;
489                 }
490                 break;
491
492
493         case ARGI_REFERENCE:
494                 /*
495                  * Create_xxxx_field cases - we are storing the field object into the name
496                  */
497                 break;
498
499
500         default:
501                 status = AE_AML_INTERNAL;
502         }
503
504
505         /*
506          * Source-to-Target conversion semantics:
507          *
508          * If conversion to the target type cannot be performed, then simply
509          * overwrite the target with the new object and type.
510          */
511         if (status == AE_TYPE) {
512                 status = AE_OK;
513         }
514
515         return (status);
516 }
517
518