diff options
Diffstat (limited to 'drivers/acpi/executer/exutils.c')
-rw-r--r-- | drivers/acpi/executer/exutils.c | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c new file mode 100644 index 000000000000..40c6abb8b49a --- /dev/null +++ b/drivers/acpi/executer/exutils.c | |||
@@ -0,0 +1,378 @@ | |||
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 | |||
70 | |||
71 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
72 | |||
73 | /******************************************************************************* | ||
74 | * | ||
75 | * FUNCTION: acpi_ex_enter_interpreter | ||
76 | * | ||
77 | * PARAMETERS: None | ||
78 | * | ||
79 | * DESCRIPTION: Enter the interpreter execution region. Failure to enter | ||
80 | * the interpreter region is a fatal system error | ||
81 | * | ||
82 | ******************************************************************************/ | ||
83 | |||
84 | acpi_status | ||
85 | acpi_ex_enter_interpreter (void) | ||
86 | { | ||
87 | acpi_status status; | ||
88 | |||
89 | ACPI_FUNCTION_TRACE ("ex_enter_interpreter"); | ||
90 | |||
91 | |||
92 | status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE); | ||
93 | if (ACPI_FAILURE (status)) { | ||
94 | ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n")); | ||
95 | } | ||
96 | |||
97 | return_ACPI_STATUS (status); | ||
98 | } | ||
99 | |||
100 | |||
101 | /******************************************************************************* | ||
102 | * | ||
103 | * FUNCTION: acpi_ex_exit_interpreter | ||
104 | * | ||
105 | * PARAMETERS: None | ||
106 | * | ||
107 | * DESCRIPTION: Exit the interpreter execution region | ||
108 | * | ||
109 | * Cases where the interpreter is unlocked: | ||
110 | * 1) Completion of the execution of a control method | ||
111 | * 2) Method blocked on a Sleep() AML opcode | ||
112 | * 3) Method blocked on an Acquire() AML opcode | ||
113 | * 4) Method blocked on a Wait() AML opcode | ||
114 | * 5) Method blocked to acquire the global lock | ||
115 | * 6) Method blocked to execute a serialized control method that is | ||
116 | * already executing | ||
117 | * 7) About to invoke a user-installed opregion handler | ||
118 | * | ||
119 | ******************************************************************************/ | ||
120 | |||
121 | void | ||
122 | acpi_ex_exit_interpreter (void) | ||
123 | { | ||
124 | acpi_status status; | ||
125 | |||
126 | |||
127 | ACPI_FUNCTION_TRACE ("ex_exit_interpreter"); | ||
128 | |||
129 | |||
130 | status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE); | ||
131 | if (ACPI_FAILURE (status)) { | ||
132 | ACPI_REPORT_ERROR (("Could not release interpreter mutex\n")); | ||
133 | } | ||
134 | |||
135 | return_VOID; | ||
136 | } | ||
137 | |||
138 | |||
139 | /******************************************************************************* | ||
140 | * | ||
141 | * FUNCTION: acpi_ex_truncate_for32bit_table | ||
142 | * | ||
143 | * PARAMETERS: obj_desc - Object to be truncated | ||
144 | * | ||
145 | * RETURN: none | ||
146 | * | ||
147 | * DESCRIPTION: Truncate a number to 32-bits if the currently executing method | ||
148 | * belongs to a 32-bit ACPI table. | ||
149 | * | ||
150 | ******************************************************************************/ | ||
151 | |||
152 | void | ||
153 | acpi_ex_truncate_for32bit_table ( | ||
154 | union acpi_operand_object *obj_desc) | ||
155 | { | ||
156 | |||
157 | ACPI_FUNCTION_ENTRY (); | ||
158 | |||
159 | |||
160 | /* | ||
161 | * Object must be a valid number and we must be executing | ||
162 | * a control method | ||
163 | */ | ||
164 | if ((!obj_desc) || | ||
165 | (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) { | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | if (acpi_gbl_integer_byte_width == 4) { | ||
170 | /* | ||
171 | * We are running a method that exists in a 32-bit ACPI table. | ||
172 | * Truncate the value to 32 bits by zeroing out the upper 32-bit field | ||
173 | */ | ||
174 | obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | |||
179 | /******************************************************************************* | ||
180 | * | ||
181 | * FUNCTION: acpi_ex_acquire_global_lock | ||
182 | * | ||
183 | * PARAMETERS: field_flags - Flags with Lock rule: | ||
184 | * always_lock or never_lock | ||
185 | * | ||
186 | * RETURN: TRUE/FALSE indicating whether the lock was actually acquired | ||
187 | * | ||
188 | * DESCRIPTION: Obtain the global lock and keep track of this fact via two | ||
189 | * methods. A global variable keeps the state of the lock, and | ||
190 | * the state is returned to the caller. | ||
191 | * | ||
192 | ******************************************************************************/ | ||
193 | |||
194 | u8 | ||
195 | acpi_ex_acquire_global_lock ( | ||
196 | u32 field_flags) | ||
197 | { | ||
198 | u8 locked = FALSE; | ||
199 | acpi_status status; | ||
200 | |||
201 | |||
202 | ACPI_FUNCTION_TRACE ("ex_acquire_global_lock"); | ||
203 | |||
204 | |||
205 | /* Only attempt lock if the always_lock bit is set */ | ||
206 | |||
207 | if (field_flags & AML_FIELD_LOCK_RULE_MASK) { | ||
208 | /* We should attempt to get the lock, wait forever */ | ||
209 | |||
210 | status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER); | ||
211 | if (ACPI_SUCCESS (status)) { | ||
212 | locked = TRUE; | ||
213 | } | ||
214 | else { | ||
215 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not acquire Global Lock, %s\n", | ||
216 | acpi_format_exception (status))); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | return_VALUE (locked); | ||
221 | } | ||
222 | |||
223 | |||
224 | /******************************************************************************* | ||
225 | * | ||
226 | * FUNCTION: acpi_ex_release_global_lock | ||
227 | * | ||
228 | * PARAMETERS: locked_by_me - Return value from corresponding call to | ||
229 | * acquire_global_lock. | ||
230 | * | ||
231 | * RETURN: Status | ||
232 | * | ||
233 | * DESCRIPTION: Release the global lock if it is locked. | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | void | ||
238 | acpi_ex_release_global_lock ( | ||
239 | u8 locked_by_me) | ||
240 | { | ||
241 | acpi_status status; | ||
242 | |||
243 | |||
244 | ACPI_FUNCTION_TRACE ("ex_release_global_lock"); | ||
245 | |||
246 | |||
247 | /* Only attempt unlock if the caller locked it */ | ||
248 | |||
249 | if (locked_by_me) { | ||
250 | /* OK, now release the lock */ | ||
251 | |||
252 | status = acpi_ev_release_global_lock (); | ||
253 | if (ACPI_FAILURE (status)) { | ||
254 | /* Report the error, but there isn't much else we can do */ | ||
255 | |||
256 | ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n", | ||
257 | acpi_format_exception (status))); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | return_VOID; | ||
262 | } | ||
263 | |||
264 | |||
265 | /******************************************************************************* | ||
266 | * | ||
267 | * FUNCTION: acpi_ex_digits_needed | ||
268 | * | ||
269 | * PARAMETERS: Value - Value to be represented | ||
270 | * Base - Base of representation | ||
271 | * | ||
272 | * RETURN: the number of digits needed to represent Value in Base | ||
273 | * | ||
274 | ******************************************************************************/ | ||
275 | |||
276 | u32 | ||
277 | acpi_ex_digits_needed ( | ||
278 | acpi_integer value, | ||
279 | u32 base) | ||
280 | { | ||
281 | u32 num_digits; | ||
282 | acpi_integer current_value; | ||
283 | |||
284 | |||
285 | ACPI_FUNCTION_TRACE ("ex_digits_needed"); | ||
286 | |||
287 | |||
288 | /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ | ||
289 | |||
290 | if (value == 0) { | ||
291 | return_VALUE (1); | ||
292 | } | ||
293 | |||
294 | current_value = value; | ||
295 | num_digits = 0; | ||
296 | |||
297 | /* Count the digits in the requested base */ | ||
298 | |||
299 | while (current_value) { | ||
300 | (void) acpi_ut_short_divide (current_value, base, ¤t_value, NULL); | ||
301 | num_digits++; | ||
302 | } | ||
303 | |||
304 | return_VALUE (num_digits); | ||
305 | } | ||
306 | |||
307 | |||
308 | /******************************************************************************* | ||
309 | * | ||
310 | * FUNCTION: acpi_ex_eisa_id_to_string | ||
311 | * | ||
312 | * PARAMETERS: numeric_id - EISA ID to be converted | ||
313 | * out_string - Where to put the converted string (8 bytes) | ||
314 | * | ||
315 | * DESCRIPTION: Convert a numeric EISA ID to string representation | ||
316 | * | ||
317 | ******************************************************************************/ | ||
318 | |||
319 | void | ||
320 | acpi_ex_eisa_id_to_string ( | ||
321 | u32 numeric_id, | ||
322 | char *out_string) | ||
323 | { | ||
324 | u32 eisa_id; | ||
325 | |||
326 | |||
327 | ACPI_FUNCTION_ENTRY (); | ||
328 | |||
329 | |||
330 | /* Swap ID to big-endian to get contiguous bits */ | ||
331 | |||
332 | eisa_id = acpi_ut_dword_byte_swap (numeric_id); | ||
333 | |||
334 | out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f)); | ||
335 | out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f)); | ||
336 | out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f)); | ||
337 | out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12); | ||
338 | out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8); | ||
339 | out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4); | ||
340 | out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0); | ||
341 | out_string[7] = 0; | ||
342 | } | ||
343 | |||
344 | |||
345 | /******************************************************************************* | ||
346 | * | ||
347 | * FUNCTION: acpi_ex_unsigned_integer_to_string | ||
348 | * | ||
349 | * PARAMETERS: Value - Value to be converted | ||
350 | * out_string - Where to put the converted string (8 bytes) | ||
351 | * | ||
352 | * RETURN: Convert a number to string representation | ||
353 | * | ||
354 | ******************************************************************************/ | ||
355 | |||
356 | void | ||
357 | acpi_ex_unsigned_integer_to_string ( | ||
358 | acpi_integer value, | ||
359 | char *out_string) | ||
360 | { | ||
361 | u32 count; | ||
362 | u32 digits_needed; | ||
363 | u32 remainder; | ||
364 | |||
365 | |||
366 | ACPI_FUNCTION_ENTRY (); | ||
367 | |||
368 | |||
369 | digits_needed = acpi_ex_digits_needed (value, 10); | ||
370 | out_string[digits_needed] = 0; | ||
371 | |||
372 | for (count = digits_needed; count > 0; count--) { | ||
373 | (void) acpi_ut_short_divide (value, 10, &value, &remainder); | ||
374 | out_string[count-1] = (char) ('0' + remainder);\ | ||
375 | } | ||
376 | } | ||
377 | |||
378 | #endif | ||