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 | |
b229cf92 | 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)) { | |
b8e4d893 | 94 | ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); |
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 | |
b229cf92 | 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)) { | |
b8e4d893 | 130 | ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); |
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 | |
b229cf92 | 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) { | |
52fc0b02 | 197 | |
1da177e4 LT |
198 | /* We should attempt to get the lock, wait forever */ |
199 | ||
4be44fcd LB |
200 | status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); |
201 | if (ACPI_SUCCESS(status)) { | |
1da177e4 | 202 | locked = TRUE; |
4be44fcd | 203 | } else { |
b8e4d893 BM |
204 | ACPI_EXCEPTION((AE_INFO, status, |
205 | "Could not acquire Global Lock")); | |
1da177e4 LT |
206 | } |
207 | } | |
208 | ||
50eca3eb | 209 | return_UINT8(locked); |
1da177e4 LT |
210 | } |
211 | ||
1da177e4 LT |
212 | /******************************************************************************* |
213 | * | |
214 | * FUNCTION: acpi_ex_release_global_lock | |
215 | * | |
216 | * PARAMETERS: locked_by_me - Return value from corresponding call to | |
217 | * acquire_global_lock. | |
218 | * | |
44f6c012 | 219 | * RETURN: None |
1da177e4 LT |
220 | * |
221 | * DESCRIPTION: Release the global lock if it is locked. | |
222 | * | |
223 | ******************************************************************************/ | |
224 | ||
4be44fcd | 225 | void acpi_ex_release_global_lock(u8 locked_by_me) |
1da177e4 | 226 | { |
4be44fcd | 227 | acpi_status status; |
1da177e4 | 228 | |
b229cf92 | 229 | ACPI_FUNCTION_TRACE(ex_release_global_lock); |
1da177e4 LT |
230 | |
231 | /* Only attempt unlock if the caller locked it */ | |
232 | ||
233 | if (locked_by_me) { | |
52fc0b02 | 234 | |
1da177e4 LT |
235 | /* OK, now release the lock */ |
236 | ||
4be44fcd LB |
237 | status = acpi_ev_release_global_lock(); |
238 | if (ACPI_FAILURE(status)) { | |
52fc0b02 | 239 | |
1da177e4 LT |
240 | /* Report the error, but there isn't much else we can do */ |
241 | ||
b8e4d893 BM |
242 | ACPI_EXCEPTION((AE_INFO, status, |
243 | "Could not release ACPI Global Lock")); | |
1da177e4 LT |
244 | } |
245 | } | |
246 | ||
247 | return_VOID; | |
248 | } | |
249 | ||
1da177e4 LT |
250 | /******************************************************************************* |
251 | * | |
252 | * FUNCTION: acpi_ex_digits_needed | |
253 | * | |
254 | * PARAMETERS: Value - Value to be represented | |
255 | * Base - Base of representation | |
256 | * | |
44f6c012 RM |
257 | * RETURN: The number of digits. |
258 | * | |
259 | * DESCRIPTION: Calculate the number of digits needed to represent the Value | |
260 | * in the given Base (Radix) | |
1da177e4 LT |
261 | * |
262 | ******************************************************************************/ | |
263 | ||
4be44fcd | 264 | static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) |
1da177e4 | 265 | { |
4be44fcd LB |
266 | u32 num_digits; |
267 | acpi_integer current_value; | |
1da177e4 | 268 | |
b229cf92 | 269 | ACPI_FUNCTION_TRACE(ex_digits_needed); |
1da177e4 LT |
270 | |
271 | /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ | |
272 | ||
273 | if (value == 0) { | |
50eca3eb | 274 | return_UINT32(1); |
1da177e4 LT |
275 | } |
276 | ||
277 | current_value = value; | |
278 | num_digits = 0; | |
279 | ||
280 | /* Count the digits in the requested base */ | |
281 | ||
282 | while (current_value) { | |
4be44fcd LB |
283 | (void)acpi_ut_short_divide(current_value, base, ¤t_value, |
284 | NULL); | |
1da177e4 LT |
285 | num_digits++; |
286 | } | |
287 | ||
50eca3eb | 288 | return_UINT32(num_digits); |
1da177e4 LT |
289 | } |
290 | ||
1da177e4 LT |
291 | /******************************************************************************* |
292 | * | |
293 | * FUNCTION: acpi_ex_eisa_id_to_string | |
294 | * | |
295 | * PARAMETERS: numeric_id - EISA ID to be converted | |
296 | * out_string - Where to put the converted string (8 bytes) | |
297 | * | |
44f6c012 RM |
298 | * RETURN: None |
299 | * | |
1da177e4 LT |
300 | * DESCRIPTION: Convert a numeric EISA ID to string representation |
301 | * | |
302 | ******************************************************************************/ | |
303 | ||
4be44fcd | 304 | void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string) |
1da177e4 | 305 | { |
4be44fcd | 306 | u32 eisa_id; |
1da177e4 | 307 | |
4be44fcd | 308 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
309 | |
310 | /* Swap ID to big-endian to get contiguous bits */ | |
311 | ||
4be44fcd | 312 | eisa_id = acpi_ut_dword_byte_swap(numeric_id); |
1da177e4 | 313 | |
4be44fcd LB |
314 | out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f)); |
315 | out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f)); | |
316 | out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f)); | |
317 | out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12); | |
318 | out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8); | |
319 | out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4); | |
320 | out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0); | |
1da177e4 LT |
321 | out_string[7] = 0; |
322 | } | |
323 | ||
1da177e4 LT |
324 | /******************************************************************************* |
325 | * | |
326 | * FUNCTION: acpi_ex_unsigned_integer_to_string | |
327 | * | |
328 | * PARAMETERS: Value - Value to be converted | |
329 | * out_string - Where to put the converted string (8 bytes) | |
330 | * | |
44f6c012 RM |
331 | * RETURN: None, string |
332 | * | |
73459f73 | 333 | * DESCRIPTION: Convert a number to string representation. Assumes string |
44f6c012 | 334 | * buffer is large enough to hold the string. |
1da177e4 LT |
335 | * |
336 | ******************************************************************************/ | |
337 | ||
4be44fcd | 338 | void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string) |
1da177e4 | 339 | { |
4be44fcd LB |
340 | u32 count; |
341 | u32 digits_needed; | |
342 | u32 remainder; | |
1da177e4 | 343 | |
4be44fcd | 344 | ACPI_FUNCTION_ENTRY(); |
1da177e4 | 345 | |
4be44fcd | 346 | digits_needed = acpi_ex_digits_needed(value, 10); |
1da177e4 LT |
347 | out_string[digits_needed] = 0; |
348 | ||
349 | for (count = digits_needed; count > 0; count--) { | |
4be44fcd LB |
350 | (void)acpi_ut_short_divide(value, 10, &value, &remainder); |
351 | out_string[count - 1] = (char)('0' + remainder); | |
1da177e4 LT |
352 | } |
353 | } | |
354 | ||
355 | #endif |