]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | /****************************************************************************** | |
3 | * | |
4 | * Module Name: exutils - interpreter/scanner utilities | |
5 | * | |
6 | *****************************************************************************/ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | |
10 | * All rights reserved. | |
11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | |
16 | * notice, this list of conditions, and the following disclaimer, | |
17 | * without modification. | |
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
19 | * substantially similar to the "NO WARRANTY" disclaimer below | |
20 | * ("Disclaimer") and any redistribution must be conditioned upon | |
21 | * including a substantially similar Disclaimer requirement for further | |
22 | * binary redistribution. | |
23 | * 3. Neither the names of the above-listed copyright holders nor the names | |
24 | * of any contributors may be used to endorse or promote products derived | |
25 | * from this software without specific prior written permission. | |
26 | * | |
27 | * Alternatively, this software may be distributed under the terms of the | |
28 | * GNU General Public License ("GPL") version 2 as published by the Free | |
29 | * Software Foundation. | |
30 | * | |
31 | * NO WARRANTY | |
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
42 | * POSSIBILITY OF SUCH DAMAGES. | |
43 | */ | |
44 | ||
45 | ||
46 | /* | |
47 | * DEFINE_AML_GLOBALS is tested in amlcode.h | |
48 | * to determine whether certain global names should be "defined" or only | |
49 | * "declared" in the current compilation. This enhances maintainability | |
50 | * by enabling a single header file to embody all knowledge of the names | |
51 | * in question. | |
52 | * | |
53 | * Exactly one module of any executable should #define DEFINE_GLOBALS | |
54 | * before #including the header files which use this convention. The | |
55 | * names in question will be defined and initialized in that module, | |
56 | * and declared as extern in all other modules which #include those | |
57 | * header files. | |
58 | */ | |
59 | ||
60 | #define DEFINE_AML_GLOBALS | |
61 | ||
62 | #include <acpi/acpi.h> | |
63 | #include <acpi/acinterp.h> | |
64 | #include <acpi/amlcode.h> | |
65 | #include <acpi/acevents.h> | |
66 | ||
67 | #define _COMPONENT ACPI_EXECUTER | |
68 | ACPI_MODULE_NAME ("exutils") | |
69 | ||
44f6c012 | 70 | /* Local prototypes */ |
1da177e4 | 71 | |
44f6c012 RM |
72 | static u32 |
73 | acpi_ex_digits_needed ( | |
74 | acpi_integer value, | |
75 | u32 base); | |
1da177e4 | 76 | |
44f6c012 RM |
77 | |
78 | #ifndef ACPI_NO_METHOD_EXECUTION | |
1da177e4 LT |
79 | /******************************************************************************* |
80 | * | |
81 | * FUNCTION: acpi_ex_enter_interpreter | |
82 | * | |
83 | * PARAMETERS: None | |
84 | * | |
44f6c012 RM |
85 | * RETURN: Status |
86 | * | |
1da177e4 LT |
87 | * DESCRIPTION: Enter the interpreter execution region. Failure to enter |
88 | * the interpreter region is a fatal system error | |
89 | * | |
90 | ******************************************************************************/ | |
91 | ||
92 | acpi_status | |
44f6c012 RM |
93 | acpi_ex_enter_interpreter ( |
94 | void) | |
1da177e4 LT |
95 | { |
96 | acpi_status status; | |
97 | ||
98 | ACPI_FUNCTION_TRACE ("ex_enter_interpreter"); | |
99 | ||
100 | ||
101 | status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE); | |
102 | if (ACPI_FAILURE (status)) { | |
103 | ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n")); | |
104 | } | |
105 | ||
106 | return_ACPI_STATUS (status); | |
107 | } | |
108 | ||
109 | ||
110 | /******************************************************************************* | |
111 | * | |
112 | * FUNCTION: acpi_ex_exit_interpreter | |
113 | * | |
114 | * PARAMETERS: None | |
115 | * | |
44f6c012 RM |
116 | * RETURN: None |
117 | * | |
1da177e4 LT |
118 | * DESCRIPTION: Exit the interpreter execution region |
119 | * | |
120 | * Cases where the interpreter is unlocked: | |
121 | * 1) Completion of the execution of a control method | |
122 | * 2) Method blocked on a Sleep() AML opcode | |
123 | * 3) Method blocked on an Acquire() AML opcode | |
124 | * 4) Method blocked on a Wait() AML opcode | |
125 | * 5) Method blocked to acquire the global lock | |
126 | * 6) Method blocked to execute a serialized control method that is | |
127 | * already executing | |
128 | * 7) About to invoke a user-installed opregion handler | |
129 | * | |
130 | ******************************************************************************/ | |
131 | ||
132 | void | |
44f6c012 RM |
133 | acpi_ex_exit_interpreter ( |
134 | void) | |
1da177e4 LT |
135 | { |
136 | acpi_status status; | |
137 | ||
138 | ||
139 | ACPI_FUNCTION_TRACE ("ex_exit_interpreter"); | |
140 | ||
141 | ||
142 | status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE); | |
143 | if (ACPI_FAILURE (status)) { | |
144 | ACPI_REPORT_ERROR (("Could not release interpreter mutex\n")); | |
145 | } | |
146 | ||
147 | return_VOID; | |
148 | } | |
149 | ||
150 | ||
151 | /******************************************************************************* | |
152 | * | |
153 | * FUNCTION: acpi_ex_truncate_for32bit_table | |
154 | * | |
155 | * PARAMETERS: obj_desc - Object to be truncated | |
156 | * | |
157 | * RETURN: none | |
158 | * | |
159 | * DESCRIPTION: Truncate a number to 32-bits if the currently executing method | |
160 | * belongs to a 32-bit ACPI table. | |
161 | * | |
162 | ******************************************************************************/ | |
163 | ||
164 | void | |
165 | acpi_ex_truncate_for32bit_table ( | |
166 | union acpi_operand_object *obj_desc) | |
167 | { | |
168 | ||
169 | ACPI_FUNCTION_ENTRY (); | |
170 | ||
171 | ||
172 | /* | |
173 | * Object must be a valid number and we must be executing | |
174 | * a control method | |
175 | */ | |
176 | if ((!obj_desc) || | |
177 | (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) { | |
178 | return; | |
179 | } | |
180 | ||
181 | if (acpi_gbl_integer_byte_width == 4) { | |
182 | /* | |
183 | * We are running a method that exists in a 32-bit ACPI table. | |
184 | * Truncate the value to 32 bits by zeroing out the upper 32-bit field | |
185 | */ | |
186 | obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX; | |
187 | } | |
188 | } | |
189 | ||
190 | ||
191 | /******************************************************************************* | |
192 | * | |
193 | * FUNCTION: acpi_ex_acquire_global_lock | |
194 | * | |
195 | * PARAMETERS: field_flags - Flags with Lock rule: | |
196 | * always_lock or never_lock | |
197 | * | |
198 | * RETURN: TRUE/FALSE indicating whether the lock was actually acquired | |
199 | * | |
200 | * DESCRIPTION: Obtain the global lock and keep track of this fact via two | |
201 | * methods. A global variable keeps the state of the lock, and | |
202 | * the state is returned to the caller. | |
203 | * | |
204 | ******************************************************************************/ | |
205 | ||
206 | u8 | |
207 | acpi_ex_acquire_global_lock ( | |
208 | u32 field_flags) | |
209 | { | |
210 | u8 locked = FALSE; | |
211 | acpi_status status; | |
212 | ||
213 | ||
214 | ACPI_FUNCTION_TRACE ("ex_acquire_global_lock"); | |
215 | ||
216 | ||
217 | /* Only attempt lock if the always_lock bit is set */ | |
218 | ||
219 | if (field_flags & AML_FIELD_LOCK_RULE_MASK) { | |
220 | /* We should attempt to get the lock, wait forever */ | |
221 | ||
222 | status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER); | |
223 | if (ACPI_SUCCESS (status)) { | |
224 | locked = TRUE; | |
225 | } | |
226 | else { | |
44f6c012 RM |
227 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, |
228 | "Could not acquire Global Lock, %s\n", | |
1da177e4 LT |
229 | acpi_format_exception (status))); |
230 | } | |
231 | } | |
232 | ||
233 | return_VALUE (locked); | |
234 | } | |
235 | ||
236 | ||
237 | /******************************************************************************* | |
238 | * | |
239 | * FUNCTION: acpi_ex_release_global_lock | |
240 | * | |
241 | * PARAMETERS: locked_by_me - Return value from corresponding call to | |
242 | * acquire_global_lock. | |
243 | * | |
44f6c012 | 244 | * RETURN: None |
1da177e4 LT |
245 | * |
246 | * DESCRIPTION: Release the global lock if it is locked. | |
247 | * | |
248 | ******************************************************************************/ | |
249 | ||
250 | void | |
251 | acpi_ex_release_global_lock ( | |
252 | u8 locked_by_me) | |
253 | { | |
254 | acpi_status status; | |
255 | ||
256 | ||
257 | ACPI_FUNCTION_TRACE ("ex_release_global_lock"); | |
258 | ||
259 | ||
260 | /* Only attempt unlock if the caller locked it */ | |
261 | ||
262 | if (locked_by_me) { | |
263 | /* OK, now release the lock */ | |
264 | ||
265 | status = acpi_ev_release_global_lock (); | |
266 | if (ACPI_FAILURE (status)) { | |
267 | /* Report the error, but there isn't much else we can do */ | |
268 | ||
269 | ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n", | |
270 | acpi_format_exception (status))); | |
271 | } | |
272 | } | |
273 | ||
274 | return_VOID; | |
275 | } | |
276 | ||
277 | ||
278 | /******************************************************************************* | |
279 | * | |
280 | * FUNCTION: acpi_ex_digits_needed | |
281 | * | |
282 | * PARAMETERS: Value - Value to be represented | |
283 | * Base - Base of representation | |
284 | * | |
44f6c012 RM |
285 | * RETURN: The number of digits. |
286 | * | |
287 | * DESCRIPTION: Calculate the number of digits needed to represent the Value | |
288 | * in the given Base (Radix) | |
1da177e4 LT |
289 | * |
290 | ******************************************************************************/ | |
291 | ||
44f6c012 | 292 | static u32 |
1da177e4 LT |
293 | acpi_ex_digits_needed ( |
294 | acpi_integer value, | |
295 | u32 base) | |
296 | { | |
297 | u32 num_digits; | |
298 | acpi_integer current_value; | |
299 | ||
300 | ||
301 | ACPI_FUNCTION_TRACE ("ex_digits_needed"); | |
302 | ||
303 | ||
304 | /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ | |
305 | ||
306 | if (value == 0) { | |
307 | return_VALUE (1); | |
308 | } | |
309 | ||
310 | current_value = value; | |
311 | num_digits = 0; | |
312 | ||
313 | /* Count the digits in the requested base */ | |
314 | ||
315 | while (current_value) { | |
316 | (void) acpi_ut_short_divide (current_value, base, ¤t_value, NULL); | |
317 | num_digits++; | |
318 | } | |
319 | ||
320 | return_VALUE (num_digits); | |
321 | } | |
322 | ||
323 | ||
324 | /******************************************************************************* | |
325 | * | |
326 | * FUNCTION: acpi_ex_eisa_id_to_string | |
327 | * | |
328 | * PARAMETERS: numeric_id - EISA ID to be converted | |
329 | * out_string - Where to put the converted string (8 bytes) | |
330 | * | |
44f6c012 RM |
331 | * RETURN: None |
332 | * | |
1da177e4 LT |
333 | * DESCRIPTION: Convert a numeric EISA ID to string representation |
334 | * | |
335 | ******************************************************************************/ | |
336 | ||
337 | void | |
338 | acpi_ex_eisa_id_to_string ( | |
339 | u32 numeric_id, | |
340 | char *out_string) | |
341 | { | |
342 | u32 eisa_id; | |
343 | ||
344 | ||
345 | ACPI_FUNCTION_ENTRY (); | |
346 | ||
347 | ||
348 | /* Swap ID to big-endian to get contiguous bits */ | |
349 | ||
350 | eisa_id = acpi_ut_dword_byte_swap (numeric_id); | |
351 | ||
352 | out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f)); | |
353 | out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f)); | |
354 | out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f)); | |
355 | out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12); | |
356 | out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8); | |
357 | out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4); | |
358 | out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0); | |
359 | out_string[7] = 0; | |
360 | } | |
361 | ||
362 | ||
363 | /******************************************************************************* | |
364 | * | |
365 | * FUNCTION: acpi_ex_unsigned_integer_to_string | |
366 | * | |
367 | * PARAMETERS: Value - Value to be converted | |
368 | * out_string - Where to put the converted string (8 bytes) | |
369 | * | |
44f6c012 RM |
370 | * RETURN: None, string |
371 | * | |
73459f73 | 372 | * DESCRIPTION: Convert a number to string representation. Assumes string |
44f6c012 | 373 | * buffer is large enough to hold the string. |
1da177e4 LT |
374 | * |
375 | ******************************************************************************/ | |
376 | ||
377 | void | |
378 | acpi_ex_unsigned_integer_to_string ( | |
379 | acpi_integer value, | |
380 | char *out_string) | |
381 | { | |
382 | u32 count; | |
383 | u32 digits_needed; | |
384 | u32 remainder; | |
385 | ||
386 | ||
387 | ACPI_FUNCTION_ENTRY (); | |
388 | ||
389 | ||
390 | digits_needed = acpi_ex_digits_needed (value, 10); | |
391 | out_string[digits_needed] = 0; | |
392 | ||
393 | for (count = digits_needed; count > 0; count--) { | |
394 | (void) acpi_ut_short_divide (value, 10, &value, &remainder); | |
395 | out_string[count-1] = (char) ('0' + remainder);\ | |
396 | } | |
397 | } | |
398 | ||
399 | #endif |