Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | /****************************************************************************** | |
3 | * | |
4 | * Module Name: exutils - interpreter/scanner utilities | |
5 | * | |
6 | *****************************************************************************/ | |
7 | ||
8 | /* | |
4a90c7e8 | 9 | * Copyright (C) 2000 - 2006, R. Byron Moore |
1da177e4 LT |
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 | ||
1da177e4 LT |
45 | /* |
46 | * DEFINE_AML_GLOBALS is tested in amlcode.h | |
47 | * to determine whether certain global names should be "defined" or only | |
48 | * "declared" in the current compilation. This enhances maintainability | |
49 | * by enabling a single header file to embody all knowledge of the names | |
50 | * in question. | |
51 | * | |
52 | * Exactly one module of any executable should #define DEFINE_GLOBALS | |
53 | * before #including the header files which use this convention. The | |
54 | * names in question will be defined and initialized in that module, | |
55 | * and declared as extern in all other modules which #include those | |
56 | * header files. | |
57 | */ | |
58 | ||
59 | #define DEFINE_AML_GLOBALS | |
60 | ||
61 | #include <acpi/acpi.h> | |
62 | #include <acpi/acinterp.h> | |
63 | #include <acpi/amlcode.h> | |
64 | #include <acpi/acevents.h> | |
65 | ||
66 | #define _COMPONENT ACPI_EXECUTER | |
4be44fcd | 67 | ACPI_MODULE_NAME("exutils") |
1da177e4 | 68 | |
44f6c012 | 69 | /* Local prototypes */ |
4be44fcd | 70 | static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); |
44f6c012 RM |
71 | |
72 | #ifndef ACPI_NO_METHOD_EXECUTION | |
1da177e4 LT |
73 | /******************************************************************************* |
74 | * | |
75 | * FUNCTION: acpi_ex_enter_interpreter | |
76 | * | |
77 | * PARAMETERS: None | |
78 | * | |
44f6c012 RM |
79 | * RETURN: Status |
80 | * | |
1da177e4 LT |
81 | * DESCRIPTION: Enter the interpreter execution region. Failure to enter |
82 | * the interpreter region is a fatal system error | |
83 | * | |
84 | ******************************************************************************/ | |
85 | ||
4be44fcd | 86 | acpi_status acpi_ex_enter_interpreter(void) |
1da177e4 | 87 | { |
4be44fcd | 88 | acpi_status status; |
1da177e4 | 89 | |
4be44fcd | 90 | ACPI_FUNCTION_TRACE("ex_enter_interpreter"); |
1da177e4 | 91 | |
4be44fcd LB |
92 | status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE); |
93 | if (ACPI_FAILURE(status)) { | |
94 | ACPI_REPORT_ERROR(("Could not acquire interpreter mutex\n")); | |
1da177e4 LT |
95 | } |
96 | ||
4be44fcd | 97 | return_ACPI_STATUS(status); |
1da177e4 LT |
98 | } |
99 | ||
1da177e4 LT |
100 | /******************************************************************************* |
101 | * | |
102 | * FUNCTION: acpi_ex_exit_interpreter | |
103 | * | |
104 | * PARAMETERS: None | |
105 | * | |
44f6c012 RM |
106 | * RETURN: None |
107 | * | |
1da177e4 LT |
108 | * DESCRIPTION: Exit the interpreter execution region |
109 | * | |
110 | * Cases where the interpreter is unlocked: | |
111 | * 1) Completion of the execution of a control method | |
112 | * 2) Method blocked on a Sleep() AML opcode | |
113 | * 3) Method blocked on an Acquire() AML opcode | |
114 | * 4) Method blocked on a Wait() AML opcode | |
115 | * 5) Method blocked to acquire the global lock | |
116 | * 6) Method blocked to execute a serialized control method that is | |
117 | * already executing | |
118 | * 7) About to invoke a user-installed opregion handler | |
119 | * | |
120 | ******************************************************************************/ | |
121 | ||
4be44fcd | 122 | void acpi_ex_exit_interpreter(void) |
1da177e4 | 123 | { |
4be44fcd | 124 | acpi_status status; |
1da177e4 | 125 | |
4be44fcd | 126 | ACPI_FUNCTION_TRACE("ex_exit_interpreter"); |
1da177e4 | 127 | |
4be44fcd LB |
128 | status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE); |
129 | if (ACPI_FAILURE(status)) { | |
130 | ACPI_REPORT_ERROR(("Could not release interpreter mutex\n")); | |
1da177e4 LT |
131 | } |
132 | ||
133 | return_VOID; | |
134 | } | |
135 | ||
1da177e4 LT |
136 | /******************************************************************************* |
137 | * | |
138 | * FUNCTION: acpi_ex_truncate_for32bit_table | |
139 | * | |
140 | * PARAMETERS: obj_desc - Object to be truncated | |
141 | * | |
142 | * RETURN: none | |
143 | * | |
144 | * DESCRIPTION: Truncate a number to 32-bits if the currently executing method | |
145 | * belongs to a 32-bit ACPI table. | |
146 | * | |
147 | ******************************************************************************/ | |
148 | ||
4be44fcd | 149 | void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) |
1da177e4 LT |
150 | { |
151 | ||
4be44fcd | 152 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
153 | |
154 | /* | |
155 | * Object must be a valid number and we must be executing | |
156 | * a control method | |
157 | */ | |
158 | if ((!obj_desc) || | |
4be44fcd | 159 | (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { |
1da177e4 LT |
160 | return; |
161 | } | |
162 | ||
163 | if (acpi_gbl_integer_byte_width == 4) { | |
164 | /* | |
165 | * We are running a method that exists in a 32-bit ACPI table. | |
166 | * Truncate the value to 32 bits by zeroing out the upper 32-bit field | |
167 | */ | |
168 | obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX; | |
169 | } | |
170 | } | |
171 | ||
1da177e4 LT |
172 | /******************************************************************************* |
173 | * | |
174 | * FUNCTION: acpi_ex_acquire_global_lock | |
175 | * | |
176 | * PARAMETERS: field_flags - Flags with Lock rule: | |
177 | * always_lock or never_lock | |
178 | * | |
179 | * RETURN: TRUE/FALSE indicating whether the lock was actually acquired | |
180 | * | |
181 | * DESCRIPTION: Obtain the global lock and keep track of this fact via two | |
182 | * methods. A global variable keeps the state of the lock, and | |
183 | * the state is returned to the caller. | |
184 | * | |
185 | ******************************************************************************/ | |
186 | ||
4be44fcd | 187 | u8 acpi_ex_acquire_global_lock(u32 field_flags) |
1da177e4 | 188 | { |
4be44fcd LB |
189 | u8 locked = FALSE; |
190 | acpi_status status; | |
1da177e4 | 191 | |
4be44fcd | 192 | ACPI_FUNCTION_TRACE("ex_acquire_global_lock"); |
1da177e4 LT |
193 | |
194 | /* Only attempt lock if the always_lock bit is set */ | |
195 | ||
196 | if (field_flags & AML_FIELD_LOCK_RULE_MASK) { | |
197 | /* We should attempt to get the lock, wait forever */ | |
198 | ||
4be44fcd LB |
199 | status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); |
200 | if (ACPI_SUCCESS(status)) { | |
1da177e4 | 201 | locked = TRUE; |
4be44fcd | 202 | } else { |
4a90c7e8 | 203 | ACPI_REPORT_ERROR(("Could not acquire Global Lock, %s\n", acpi_format_exception(status))); |
1da177e4 LT |
204 | } |
205 | } | |
206 | ||
50eca3eb | 207 | return_UINT8(locked); |
1da177e4 LT |
208 | } |
209 | ||
1da177e4 LT |
210 | /******************************************************************************* |
211 | * | |
212 | * FUNCTION: acpi_ex_release_global_lock | |
213 | * | |
214 | * PARAMETERS: locked_by_me - Return value from corresponding call to | |
215 | * acquire_global_lock. | |
216 | * | |
44f6c012 | 217 | * RETURN: None |
1da177e4 LT |
218 | * |
219 | * DESCRIPTION: Release the global lock if it is locked. | |
220 | * | |
221 | ******************************************************************************/ | |
222 | ||
4be44fcd | 223 | void acpi_ex_release_global_lock(u8 locked_by_me) |
1da177e4 | 224 | { |
4be44fcd | 225 | acpi_status status; |
1da177e4 | 226 | |
4be44fcd | 227 | ACPI_FUNCTION_TRACE("ex_release_global_lock"); |
1da177e4 LT |
228 | |
229 | /* Only attempt unlock if the caller locked it */ | |
230 | ||
231 | if (locked_by_me) { | |
232 | /* OK, now release the lock */ | |
233 | ||
4be44fcd LB |
234 | status = acpi_ev_release_global_lock(); |
235 | if (ACPI_FAILURE(status)) { | |
1da177e4 LT |
236 | /* Report the error, but there isn't much else we can do */ |
237 | ||
4be44fcd | 238 | ACPI_REPORT_ERROR(("Could not release ACPI Global Lock, %s\n", acpi_format_exception(status))); |
1da177e4 LT |
239 | } |
240 | } | |
241 | ||
242 | return_VOID; | |
243 | } | |
244 | ||
1da177e4 LT |
245 | /******************************************************************************* |
246 | * | |
247 | * FUNCTION: acpi_ex_digits_needed | |
248 | * | |
249 | * PARAMETERS: Value - Value to be represented | |
250 | * Base - Base of representation | |
251 | * | |
44f6c012 RM |
252 | * RETURN: The number of digits. |
253 | * | |
254 | * DESCRIPTION: Calculate the number of digits needed to represent the Value | |
255 | * in the given Base (Radix) | |
1da177e4 LT |
256 | * |
257 | ******************************************************************************/ | |
258 | ||
4be44fcd | 259 | static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) |
1da177e4 | 260 | { |
4be44fcd LB |
261 | u32 num_digits; |
262 | acpi_integer current_value; | |
1da177e4 | 263 | |
4be44fcd | 264 | ACPI_FUNCTION_TRACE("ex_digits_needed"); |
1da177e4 LT |
265 | |
266 | /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ | |
267 | ||
268 | if (value == 0) { | |
50eca3eb | 269 | return_UINT32(1); |
1da177e4 LT |
270 | } |
271 | ||
272 | current_value = value; | |
273 | num_digits = 0; | |
274 | ||
275 | /* Count the digits in the requested base */ | |
276 | ||
277 | while (current_value) { | |
4be44fcd LB |
278 | (void)acpi_ut_short_divide(current_value, base, ¤t_value, |
279 | NULL); | |
1da177e4 LT |
280 | num_digits++; |
281 | } | |
282 | ||
50eca3eb | 283 | return_UINT32(num_digits); |
1da177e4 LT |
284 | } |
285 | ||
1da177e4 LT |
286 | /******************************************************************************* |
287 | * | |
288 | * FUNCTION: acpi_ex_eisa_id_to_string | |
289 | * | |
290 | * PARAMETERS: numeric_id - EISA ID to be converted | |
291 | * out_string - Where to put the converted string (8 bytes) | |
292 | * | |
44f6c012 RM |
293 | * RETURN: None |
294 | * | |
1da177e4 LT |
295 | * DESCRIPTION: Convert a numeric EISA ID to string representation |
296 | * | |
297 | ******************************************************************************/ | |
298 | ||
4be44fcd | 299 | void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string) |
1da177e4 | 300 | { |
4be44fcd | 301 | u32 eisa_id; |
1da177e4 | 302 | |
4be44fcd | 303 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
304 | |
305 | /* Swap ID to big-endian to get contiguous bits */ | |
306 | ||
4be44fcd | 307 | eisa_id = acpi_ut_dword_byte_swap(numeric_id); |
1da177e4 | 308 | |
4be44fcd LB |
309 | out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f)); |
310 | out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f)); | |
311 | out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f)); | |
312 | out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12); | |
313 | out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8); | |
314 | out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4); | |
315 | out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0); | |
1da177e4 LT |
316 | out_string[7] = 0; |
317 | } | |
318 | ||
1da177e4 LT |
319 | /******************************************************************************* |
320 | * | |
321 | * FUNCTION: acpi_ex_unsigned_integer_to_string | |
322 | * | |
323 | * PARAMETERS: Value - Value to be converted | |
324 | * out_string - Where to put the converted string (8 bytes) | |
325 | * | |
44f6c012 RM |
326 | * RETURN: None, string |
327 | * | |
73459f73 | 328 | * DESCRIPTION: Convert a number to string representation. Assumes string |
44f6c012 | 329 | * buffer is large enough to hold the string. |
1da177e4 LT |
330 | * |
331 | ******************************************************************************/ | |
332 | ||
4be44fcd | 333 | void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string) |
1da177e4 | 334 | { |
4be44fcd LB |
335 | u32 count; |
336 | u32 digits_needed; | |
337 | u32 remainder; | |
1da177e4 | 338 | |
4be44fcd | 339 | ACPI_FUNCTION_ENTRY(); |
1da177e4 | 340 | |
4be44fcd | 341 | digits_needed = acpi_ex_digits_needed(value, 10); |
1da177e4 LT |
342 | out_string[digits_needed] = 0; |
343 | ||
344 | for (count = digits_needed; count > 0; count--) { | |
4be44fcd LB |
345 | (void)acpi_ut_short_divide(value, 10, &value, &remainder); |
346 | out_string[count - 1] = (char)('0' + remainder); | |
1da177e4 LT |
347 | } |
348 | } | |
349 | ||
350 | #endif |