1
2/******************************************************************************
3 *
4 * Module Name: exutils - interpreter/scanner utilities
5 *              $Revision: 1.1.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/*
29 * DEFINE_AML_GLOBALS is tested in amlcode.h
30 * to determine whether certain global names should be "defined" or only
31 * "declared" in the current compilation.  This enhances maintainability
32 * by enabling a single header file to embody all knowledge of the names
33 * in question.
34 *
35 * Exactly one module of any executable should #define DEFINE_GLOBALS
36 * before #including the header files which use this convention.  The
37 * names in question will be defined and initialized in that module,
38 * and declared as extern in all other modules which #include those
39 * header files.
40 */
41
42#define DEFINE_AML_GLOBALS
43
44#include "acpi.h"
45#include "acparser.h"
46#include "acinterp.h"
47#include "amlcode.h"
48#include "acnamesp.h"
49#include "acevents.h"
50#include "acparser.h"
51
52#define _COMPONENT          ACPI_EXECUTER
53	 MODULE_NAME         ("exutils")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION:    Acpi_ex_enter_interpreter
59 *
60 * PARAMETERS:  None
61 *
62 * DESCRIPTION: Enter the interpreter execution region
63 *              TBD: should be a macro
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_ex_enter_interpreter (void)
69{
70	acpi_status             status;
71
72	FUNCTION_TRACE ("Ex_enter_interpreter");
73
74
75	status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE);
76	return_ACPI_STATUS (status);
77}
78
79
80/*******************************************************************************
81 *
82 * FUNCTION:    Acpi_ex_exit_interpreter
83 *
84 * PARAMETERS:  None
85 *
86 * DESCRIPTION: Exit the interpreter execution region
87 *
88 * Cases where the interpreter is unlocked:
89 *      1) Completion of the execution of a control method
90 *      2) Method blocked on a Sleep() AML opcode
91 *      3) Method blocked on an Acquire() AML opcode
92 *      4) Method blocked on a Wait() AML opcode
93 *      5) Method blocked to acquire the global lock
94 *      6) Method blocked to execute a serialized control method that is
95 *          already executing
96 *      7) About to invoke a user-installed opregion handler
97 *
98 *              TBD: should be a macro
99 *
100 ******************************************************************************/
101
102void
103acpi_ex_exit_interpreter (void)
104{
105	FUNCTION_TRACE ("Ex_exit_interpreter");
106
107
108	acpi_ut_release_mutex (ACPI_MTX_EXECUTE);
109
110	return_VOID;
111}
112
113
114/*******************************************************************************
115 *
116 * FUNCTION:    Acpi_ex_validate_object_type
117 *
118 * PARAMETERS:  Type            Object type to validate
119 *
120 * DESCRIPTION: Determine if a type is a valid ACPI object type
121 *
122 ******************************************************************************/
123
124u8
125acpi_ex_validate_object_type (
126	acpi_object_type        type)
127{
128
129	FUNCTION_ENTRY ();
130
131
132	if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) ||
133		(type > INTERNAL_TYPE_MAX)) {
134		return (FALSE);
135	}
136
137	return (TRUE);
138}
139
140
141/*******************************************************************************
142 *
143 * FUNCTION:    Acpi_ex_truncate_for32bit_table
144 *
145 * PARAMETERS:  Obj_desc        - Object to be truncated
146 *              Walk_state      - Current walk state
147 *                                (A method must be executing)
148 *
149 * RETURN:      none
150 *
151 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
152 *              belongs to a 32-bit ACPI table.
153 *
154 ******************************************************************************/
155
156void
157acpi_ex_truncate_for32bit_table (
158	acpi_operand_object     *obj_desc,
159	acpi_walk_state         *walk_state)
160{
161
162	FUNCTION_ENTRY ();
163
164
165	/*
166	 * Object must be a valid number and we must be executing
167	 * a control method
168	 */
169	if ((!obj_desc) ||
170		(obj_desc->common.type != ACPI_TYPE_INTEGER) ||
171		(!walk_state->method_node)) {
172		return;
173	}
174
175	if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
176		/*
177		 * We are running a method that exists in a 32-bit ACPI table.
178		 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
179		 */
180		obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX;
181	}
182}
183
184
185/*******************************************************************************
186 *
187 * FUNCTION:    Acpi_ex_acquire_global_lock
188 *
189 * PARAMETERS:  Rule            - Lock rule: Always_lock, Never_lock
190 *
191 * RETURN:      TRUE/FALSE indicating whether the lock was actually acquired
192 *
193 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
194 *              methods.  A global variable keeps the state of the lock, and
195 *              the state is returned to the caller.
196 *
197 ******************************************************************************/
198
199u8
200acpi_ex_acquire_global_lock (
201	u32                     rule)
202{
203	u8                      locked = FALSE;
204	acpi_status             status;
205
206
207	FUNCTION_TRACE ("Ex_acquire_global_lock");
208
209
210	/* Only attempt lock if the Rule says so */
211
212	if (rule == (u32) GLOCK_ALWAYS_LOCK) {
213		/* We should attempt to get the lock */
214
215		status = acpi_ev_acquire_global_lock ();
216		if (ACPI_SUCCESS (status)) {
217			locked = TRUE;
218		}
219
220		else {
221			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not acquire Global Lock, %s\n",
222				acpi_format_exception (status)));
223		}
224	}
225
226	return_VALUE (locked);
227}
228
229
230/*******************************************************************************
231 *
232 * FUNCTION:    Acpi_ex_release_global_lock
233 *
234 * PARAMETERS:  Locked_by_me    - Return value from corresponding call to
235 *                                Acquire_global_lock.
236 *
237 * RETURN:      Status
238 *
239 * DESCRIPTION: Release the global lock if it is locked.
240 *
241 ******************************************************************************/
242
243acpi_status
244acpi_ex_release_global_lock (
245	u8                      locked_by_me)
246{
247
248	FUNCTION_TRACE ("Ex_release_global_lock");
249
250
251	/* Only attempt unlock if the caller locked it */
252
253	if (locked_by_me) {
254		/* OK, now release the lock */
255
256		acpi_ev_release_global_lock ();
257	}
258
259
260	return_ACPI_STATUS (AE_OK);
261}
262
263
264/*******************************************************************************
265 *
266 * FUNCTION:    Acpi_ex_digits_needed
267 *
268 * PARAMETERS:  Value           - Value to be represented
269 *              Base            - Base of representation
270 *
271 * RETURN:      the number of digits needed to represent Value in Base
272 *
273 ******************************************************************************/
274
275u32
276acpi_ex_digits_needed (
277	acpi_integer            value,
278	u32                     base)
279{
280	u32                     num_digits = 0;
281
282
283	FUNCTION_TRACE ("Ex_digits_needed");
284
285
286	if (base < 1) {
287		REPORT_ERROR (("Ex_digits_needed: Internal error - Invalid base\n"));
288	}
289
290	else {
291		/*
292		 * acpi_integer is unsigned, which is why we don't worry about a '-'
293		 */
294		for (num_digits = 1;
295			(acpi_ut_short_divide (&value, base, &value, NULL));
296			++num_digits) { ; }
297	}
298
299	return_VALUE (num_digits);
300}
301
302
303/*******************************************************************************
304 *
305 * FUNCTION:    ntohl
306 *
307 * PARAMETERS:  Value           - Value to be converted
308 *
309 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
310 *
311 ******************************************************************************/
312
313static u32
314_ntohl (
315	u32                     value)
316{
317	union {
318		u32                 value;
319		u8                  bytes[4];
320	} out;
321
322	union {
323		u32                 value;
324		u8                  bytes[4];
325	} in;
326
327
328	FUNCTION_ENTRY ();
329
330
331	in.value = value;
332
333	out.bytes[0] = in.bytes[3];
334	out.bytes[1] = in.bytes[2];
335	out.bytes[2] = in.bytes[1];
336	out.bytes[3] = in.bytes[0];
337
338	return (out.value);
339}
340
341
342/*******************************************************************************
343 *
344 * FUNCTION:    Acpi_ex_eisa_id_to_string
345 *
346 * PARAMETERS:  Numeric_id      - EISA ID to be converted
347 *              Out_string      - Where to put the converted string (8 bytes)
348 *
349 * DESCRIPTION: Convert a numeric EISA ID to string representation
350 *
351 ******************************************************************************/
352
353acpi_status
354acpi_ex_eisa_id_to_string (
355	u32                     numeric_id,
356	NATIVE_CHAR             *out_string)
357{
358	u32                     id;
359
360
361	FUNCTION_ENTRY ();
362
363
364	/* swap to big-endian to get contiguous bits */
365
366	id = _ntohl (numeric_id);
367
368	out_string[0] = (char) ('@' + ((id >> 26) & 0x1f));
369	out_string[1] = (char) ('@' + ((id >> 21) & 0x1f));
370	out_string[2] = (char) ('@' + ((id >> 16) & 0x1f));
371	out_string[3] = acpi_ut_hex_to_ascii_char (id, 12);
372	out_string[4] = acpi_ut_hex_to_ascii_char (id, 8);
373	out_string[5] = acpi_ut_hex_to_ascii_char (id, 4);
374	out_string[6] = acpi_ut_hex_to_ascii_char (id, 0);
375	out_string[7] = 0;
376
377	return (AE_OK);
378}
379
380
381/*******************************************************************************
382 *
383 * FUNCTION:    Acpi_ex_unsigned_integer_to_string
384 *
385 * PARAMETERS:  Value           - Value to be converted
386 *              Out_string      - Where to put the converted string (8 bytes)
387 *
388 * RETURN:      Convert a number to string representation
389 *
390 ******************************************************************************/
391
392acpi_status
393acpi_ex_unsigned_integer_to_string (
394	acpi_integer            value,
395	NATIVE_CHAR             *out_string)
396{
397	u32                     count;
398	u32                     digits_needed;
399	u32                     remainder;
400
401
402	FUNCTION_ENTRY ();
403
404
405	digits_needed = acpi_ex_digits_needed (value, 10);
406	out_string[digits_needed] = 0;
407
408	for (count = digits_needed; count > 0; count--) {
409		acpi_ut_short_divide (&value, 10, &value, &remainder);
410		out_string[count-1] = (NATIVE_CHAR) ('0' + remainder);
411	}
412
413	return (AE_OK);
414}
415
416
417