- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / interpreter / amutils.c
blob2c5e803fb74f6d88a42e3c8e7edfc327883a2f91
2 /******************************************************************************
4 * Module Name: amutils - interpreter/scanner utilities
5 * $Revision: 64 $
7 *****************************************************************************/
9 /*
10 * Copyright (C) 2000 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
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "acinterp.h"
31 #include "amlcode.h"
32 #include "acnamesp.h"
33 #include "acevents.h"
35 #define _COMPONENT INTERPRETER
36 MODULE_NAME ("amutils")
39 typedef struct internal_search_st
41 ACPI_OPERAND_OBJECT *dest_obj;
42 u32 index;
43 ACPI_OPERAND_OBJECT *source_obj;
45 } INTERNAL_PKG_SEARCH_INFO;
48 /* Used to traverse nested packages when copying*/
50 INTERNAL_PKG_SEARCH_INFO copy_level[MAX_PACKAGE_DEPTH];
53 static NATIVE_CHAR hex[] =
54 {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
57 /*******************************************************************************
59 * FUNCTION: Acpi_aml_enter_interpreter
61 * PARAMETERS: None
63 * DESCRIPTION: Enter the interpreter execution region
65 ******************************************************************************/
67 void
68 acpi_aml_enter_interpreter (void)
71 acpi_cm_acquire_mutex (ACPI_MTX_EXECUTE);
73 return;
77 /*******************************************************************************
79 * FUNCTION: Acpi_aml_exit_interpreter
81 * PARAMETERS: None
83 * DESCRIPTION: Exit the interpreter execution region
85 * Cases where the interpreter is unlocked:
86 * 1) Completion of the execution of a control method
87 * 2) Method blocked on a Sleep() AML opcode
88 * 3) Method blocked on an Acquire() AML opcode
89 * 4) Method blocked on a Wait() AML opcode
90 * 5) Method blocked to acquire the global lock
91 * 6) Method blocked to execute a serialized control method that is
92 * already executing
93 * 7) About to invoke a user-installed opregion handler
95 ******************************************************************************/
97 void
98 acpi_aml_exit_interpreter (void)
101 acpi_cm_release_mutex (ACPI_MTX_EXECUTE);
103 return;
107 /*******************************************************************************
109 * FUNCTION: Acpi_aml_validate_object_type
111 * PARAMETERS: Type Object type to validate
113 * DESCRIPTION: Determine if a type is a valid ACPI object type
115 ******************************************************************************/
118 acpi_aml_validate_object_type (
119 ACPI_OBJECT_TYPE type)
122 if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) ||
123 (type > INTERNAL_TYPE_MAX))
125 return (FALSE);
128 return (TRUE);
132 /*******************************************************************************
134 * FUNCTION: Acpi_aml_truncate_for32bit_table
136 * PARAMETERS: Obj_desc - Object to be truncated
137 * Walk_state - Current walk state
138 * (A method must be executing)
140 * RETURN: none
142 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
143 * belongs to a 32-bit ACPI table.
145 ******************************************************************************/
147 void
148 acpi_aml_truncate_for32bit_table (
149 ACPI_OPERAND_OBJECT *obj_desc,
150 ACPI_WALK_STATE *walk_state)
154 * Object must be a valid number and we must be executing
155 * a control method
158 if ((!obj_desc) ||
159 (obj_desc->common.type != ACPI_TYPE_NUMBER) ||
160 (!walk_state->method_node))
162 return;
165 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
167 * We are running a method that exists in a 32-bit ACPI table.
168 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
170 obj_desc->number.value &= (UINT64) ACPI_UINT32_MAX;
175 /*******************************************************************************
177 * FUNCTION: Acpi_aml_acquire_global_lock
179 * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock
181 * RETURN: TRUE/FALSE indicating whether the lock was actually acquired
183 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
184 * methods. A global variable keeps the state of the lock, and
185 * the state is returned to the caller.
187 ******************************************************************************/
190 acpi_aml_acquire_global_lock (
191 u32 rule)
193 u8 locked = FALSE;
194 ACPI_STATUS status;
197 /* Only attempt lock if the Rule says so */
199 if (rule == (u32) GLOCK_ALWAYS_LOCK) {
200 /* OK to get the lock */
202 status = acpi_ev_acquire_global_lock ();
204 if (ACPI_SUCCESS (status)) {
205 acpi_gbl_global_lock_set = TRUE;
206 locked = TRUE;
210 return (locked);
214 /*******************************************************************************
216 * FUNCTION: Acpi_aml_release_global_lock
218 * PARAMETERS: Locked_by_me - Return value from corresponding call to
219 * Acquire_global_lock.
221 * RETURN: Status
223 * DESCRIPTION: Release the global lock if it is locked.
225 ******************************************************************************/
227 ACPI_STATUS
228 acpi_aml_release_global_lock (
229 u8 locked_by_me)
233 /* Only attempt unlock if the caller locked it */
235 if (locked_by_me) {
236 /* Double check against the global flag */
238 if (acpi_gbl_global_lock_set) {
239 /* OK, now release the lock */
241 acpi_ev_release_global_lock ();
242 acpi_gbl_global_lock_set = FALSE;
248 return (AE_OK);
252 /*******************************************************************************
254 * FUNCTION: Acpi_aml_digits_needed
256 * PARAMETERS: val - Value to be represented
257 * base - Base of representation
259 * RETURN: the number of digits needed to represent val in base
261 ******************************************************************************/
264 acpi_aml_digits_needed (
265 ACPI_INTEGER val,
266 u32 base)
268 u32 num_digits = 0;
271 if (base < 1) {
272 REPORT_ERROR (("Aml_digits_needed: Internal error - Invalid base\n"));
275 else {
276 for (num_digits = 1 + (val < 0); (val = ACPI_DIVIDE (val,base)); ++num_digits) { ; }
279 return (num_digits);
283 /*******************************************************************************
285 * FUNCTION: ntohl
287 * PARAMETERS: Value - Value to be converted
289 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
291 ******************************************************************************/
293 static u32
294 _ntohl (
295 u32 value)
297 union
299 u32 value;
300 u8 bytes[4];
301 } out;
303 union
305 u32 value;
306 u8 bytes[4];
307 } in;
310 in.value = value;
312 out.bytes[0] = in.bytes[3];
313 out.bytes[1] = in.bytes[2];
314 out.bytes[2] = in.bytes[1];
315 out.bytes[3] = in.bytes[0];
317 return (out.value);
321 /*******************************************************************************
323 * FUNCTION: Acpi_aml_eisa_id_to_string
325 * PARAMETERS: Numeric_id - EISA ID to be converted
326 * Out_string - Where to put the converted string (8 bytes)
328 * DESCRIPTION: Convert a numeric EISA ID to string representation
330 ******************************************************************************/
332 ACPI_STATUS
333 acpi_aml_eisa_id_to_string (
334 u32 numeric_id,
335 NATIVE_CHAR *out_string)
337 u32 id;
339 /* swap to big-endian to get contiguous bits */
341 id = _ntohl (numeric_id);
343 out_string[0] = (char) ('@' + ((id >> 26) & 0x1f));
344 out_string[1] = (char) ('@' + ((id >> 21) & 0x1f));
345 out_string[2] = (char) ('@' + ((id >> 16) & 0x1f));
346 out_string[3] = hex[(id >> 12) & 0xf];
347 out_string[4] = hex[(id >> 8) & 0xf];
348 out_string[5] = hex[(id >> 4) & 0xf];
349 out_string[6] = hex[id & 0xf];
350 out_string[7] = 0;
352 return (AE_OK);
356 /*******************************************************************************
358 * FUNCTION: Acpi_aml_unsigned_integer_to_string
360 * PARAMETERS: Value - Value to be converted
361 * Out_string - Where to put the converted string (8 bytes)
363 * RETURN: Convert a number to string representation
365 ******************************************************************************/
367 ACPI_STATUS
368 acpi_aml_unsigned_integer_to_string (
369 ACPI_INTEGER value,
370 NATIVE_CHAR *out_string)
372 u32 count;
373 u32 digits_needed;
376 digits_needed = acpi_aml_digits_needed (value, 10);
378 out_string[digits_needed] = '\0';
380 for (count = digits_needed; count > 0; count--) {
381 out_string[count-1] = (NATIVE_CHAR) ('0' + (ACPI_MODULO (value, 10)));
382 value = ACPI_DIVIDE (value, 10);
385 return (AE_OK);
389 /*******************************************************************************
391 * FUNCTION: Acpi_aml_build_copy_internal_package_object
393 * PARAMETERS: *Source_obj - Pointer to the source package object
394 * *Dest_obj - Where the internal object is returned
396 * RETURN: Status - the status of the call
398 * DESCRIPTION: This function is called to copy an internal package object
399 * into another internal package object.
401 ******************************************************************************/
403 ACPI_STATUS
404 acpi_aml_build_copy_internal_package_object (
405 ACPI_OPERAND_OBJECT *source_obj,
406 ACPI_OPERAND_OBJECT *dest_obj,
407 ACPI_WALK_STATE *walk_state)
409 u32 current_depth = 0;
410 ACPI_STATUS status = AE_OK;
411 u32 length = 0;
412 u32 this_index;
413 u32 object_space = 0;
414 ACPI_OPERAND_OBJECT *this_dest_obj;
415 ACPI_OPERAND_OBJECT *this_source_obj;
416 INTERNAL_PKG_SEARCH_INFO *level_ptr;
420 * Initialize the working variables
423 MEMSET ((void *) copy_level, 0, sizeof(copy_level));
425 copy_level[0].dest_obj = dest_obj;
426 copy_level[0].source_obj = source_obj;
427 level_ptr = &copy_level[0];
428 current_depth = 0;
430 dest_obj->common.type = source_obj->common.type;
431 dest_obj->package.count = source_obj->package.count;
435 * Build an array of ACPI_OBJECTS in the buffer
436 * and move the free space past it
439 dest_obj->package.elements = acpi_cm_callocate (
440 (dest_obj->package.count + 1) *
441 sizeof (void *));
442 if (!dest_obj->package.elements) {
443 /* Package vector allocation failure */
445 REPORT_ERROR (("Aml_build_copy_internal_package_object: Package vector allocation failure\n"));
446 return (AE_NO_MEMORY);
449 dest_obj->package.next_element = dest_obj->package.elements;
452 while (1) {
453 this_index = level_ptr->index;
454 this_dest_obj = (ACPI_OPERAND_OBJECT *) level_ptr->dest_obj->package.elements[this_index];
455 this_source_obj = (ACPI_OPERAND_OBJECT *) level_ptr->source_obj->package.elements[this_index];
457 if (IS_THIS_OBJECT_TYPE (this_source_obj, ACPI_TYPE_PACKAGE)) {
459 * If this object is a package then we go one deeper
461 if (current_depth >= MAX_PACKAGE_DEPTH-1) {
463 * Too many nested levels of packages for us to handle
465 return (AE_LIMIT);
469 * Build the package object
471 this_dest_obj = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
472 level_ptr->dest_obj->package.elements[this_index] = this_dest_obj;
475 this_dest_obj->common.type = ACPI_TYPE_PACKAGE;
476 this_dest_obj->package.count = this_dest_obj->package.count;
479 * Save space for the array of objects (Package elements)
480 * update the buffer length counter
482 object_space = this_dest_obj->package.count *
483 sizeof (ACPI_OPERAND_OBJECT);
484 length += object_space;
485 current_depth++;
486 level_ptr = &copy_level[current_depth];
487 level_ptr->dest_obj = this_dest_obj;
488 level_ptr->source_obj = this_source_obj;
489 level_ptr->index = 0;
491 } /* if object is a package */
493 else {
495 this_dest_obj = acpi_cm_create_internal_object (
496 this_source_obj->common.type);
497 level_ptr->dest_obj->package.elements[this_index] = this_dest_obj;
499 status = acpi_aml_store_object_to_object(this_source_obj, this_dest_obj, walk_state);
501 if (ACPI_FAILURE (status)) {
503 * Failure get out
505 return (status);
508 length +=object_space;
510 level_ptr->index++;
511 while (level_ptr->index >= level_ptr->dest_obj->package.count) {
513 * We've handled all of the objects at this level, This means
514 * that we have just completed a package. That package may
515 * have contained one or more packages itself
517 if (current_depth == 0) {
519 * We have handled all of the objects in the top level
520 * package just add the length of the package objects
521 * and exit
523 return (AE_OK);
527 * Go back up a level and move the index past the just
528 * completed package object.
530 current_depth--;
531 level_ptr = &copy_level[current_depth];
532 level_ptr->index++;
534 } /* else object is NOT a package */
535 } /* while (1) */