Merge trunk HEAD (46152)
[reactos.git] / drivers / bus / acpi / executer / amutils.c
1
2 /******************************************************************************
3 *
4 * Module Name: amutils - interpreter/scanner utilities
5 * $Revision: 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 #include <acpi.h>
29
30
31 #define _COMPONENT ACPI_EXECUTER
32 MODULE_NAME ("amutils")
33
34
35 /*******************************************************************************
36 *
37 * FUNCTION: Acpi_aml_enter_interpreter
38 *
39 * PARAMETERS: None
40 *
41 * DESCRIPTION: Enter the interpreter execution region
42 * TBD: should be a macro
43 *
44 ******************************************************************************/
45
46 ACPI_STATUS
47 acpi_aml_enter_interpreter (void)
48 {
49 ACPI_STATUS status;
50
51
52 status = acpi_cm_acquire_mutex (ACPI_MTX_EXECUTE);
53 return (status);
54 }
55
56
57 /*******************************************************************************
58 *
59 * FUNCTION: Acpi_aml_exit_interpreter
60 *
61 * PARAMETERS: None
62 *
63 * DESCRIPTION: Exit the interpreter execution region
64 *
65 * Cases where the interpreter is unlocked:
66 * 1) Completion of the execution of a control method
67 * 2) Method blocked on a Sleep() AML opcode
68 * 3) Method blocked on an Acquire() AML opcode
69 * 4) Method blocked on a Wait() AML opcode
70 * 5) Method blocked to acquire the global lock
71 * 6) Method blocked to execute a serialized control method that is
72 * already executing
73 * 7) About to invoke a user-installed opregion handler
74 *
75 * TBD: should be a macro
76 *
77 ******************************************************************************/
78
79 void
80 acpi_aml_exit_interpreter (void)
81 {
82
83 acpi_cm_release_mutex (ACPI_MTX_EXECUTE);
84
85 return;
86 }
87
88
89 /*******************************************************************************
90 *
91 * FUNCTION: Acpi_aml_validate_object_type
92 *
93 * PARAMETERS: Type Object type to validate
94 *
95 * DESCRIPTION: Determine if a type is a valid ACPI object type
96 *
97 ******************************************************************************/
98
99 u8
100 acpi_aml_validate_object_type (
101 ACPI_OBJECT_TYPE type)
102 {
103
104 if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) ||
105 (type > INTERNAL_TYPE_MAX)) {
106 return (FALSE);
107 }
108
109 return (TRUE);
110 }
111
112
113 /*******************************************************************************
114 *
115 * FUNCTION: Acpi_aml_truncate_for32bit_table
116 *
117 * PARAMETERS: Obj_desc - Object to be truncated
118 * Walk_state - Current walk state
119 * (A method must be executing)
120 *
121 * RETURN: none
122 *
123 * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
124 * belongs to a 32-bit ACPI table.
125 *
126 ******************************************************************************/
127
128 void
129 acpi_aml_truncate_for32bit_table (
130 ACPI_OPERAND_OBJECT *obj_desc,
131 ACPI_WALK_STATE *walk_state)
132 {
133
134 /*
135 * Object must be a valid number and we must be executing
136 * a control method
137 */
138
139 if ((!obj_desc) ||
140 (obj_desc->common.type != ACPI_TYPE_INTEGER) ||
141 (!walk_state->method_node)) {
142 return;
143 }
144
145 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
146 /*
147 * We are running a method that exists in a 32-bit ACPI table.
148 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
149 */
150 obj_desc->integer.value &= (ACPI_INTEGER) ACPI_UINT32_MAX;
151 }
152 }
153
154
155 /*******************************************************************************
156 *
157 * FUNCTION: Acpi_aml_acquire_global_lock
158 *
159 * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock
160 *
161 * RETURN: TRUE/FALSE indicating whether the lock was actually acquired
162 *
163 * DESCRIPTION: Obtain the global lock and keep track of this fact via two
164 * methods. A global variable keeps the state of the lock, and
165 * the state is returned to the caller.
166 *
167 ******************************************************************************/
168
169 u8
170 acpi_aml_acquire_global_lock (
171 u32 rule)
172 {
173 u8 locked = FALSE;
174 ACPI_STATUS status;
175
176
177 /* Only attempt lock if the Rule says so */
178
179 if (rule == (u32) GLOCK_ALWAYS_LOCK) {
180 /* We should attempt to get the lock */
181
182 status = acpi_ev_acquire_global_lock ();
183 if (ACPI_SUCCESS (status)) {
184 locked = TRUE;
185 }
186
187 }
188
189 return (locked);
190 }
191
192
193 /*******************************************************************************
194 *
195 * FUNCTION: Acpi_aml_release_global_lock
196 *
197 * PARAMETERS: Locked_by_me - Return value from corresponding call to
198 * Acquire_global_lock.
199 *
200 * RETURN: Status
201 *
202 * DESCRIPTION: Release the global lock if it is locked.
203 *
204 ******************************************************************************/
205
206 ACPI_STATUS
207 acpi_aml_release_global_lock (
208 u8 locked_by_me)
209 {
210
211
212 /* Only attempt unlock if the caller locked it */
213
214 if (locked_by_me) {
215 /* OK, now release the lock */
216
217 acpi_ev_release_global_lock ();
218 }
219
220
221 return (AE_OK);
222 }
223
224
225 /*******************************************************************************
226 *
227 * FUNCTION: Acpi_aml_digits_needed
228 *
229 * PARAMETERS: val - Value to be represented
230 * base - Base of representation
231 *
232 * RETURN: the number of digits needed to represent val in base
233 *
234 ******************************************************************************/
235
236 u32
237 acpi_aml_digits_needed (
238 ACPI_INTEGER val,
239 u32 base)
240 {
241 u32 num_digits = 0;
242
243
244 if (base < 1) {
245 REPORT_ERROR (("Aml_digits_needed: Internal error - Invalid base\n"));
246 }
247
248 else {
249 for (num_digits = 1; (val = ACPI_DIVIDE (val,base)); ++num_digits) { ; }
250 }
251
252 return (num_digits);
253 }
254
255
256 /*******************************************************************************
257 *
258 * FUNCTION: ntohl
259 *
260 * PARAMETERS: Value - Value to be converted
261 *
262 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
263 *
264 ******************************************************************************/
265
266 static u32
267 _ntohl (
268 u32 value)
269 {
270 union {
271 u32 value;
272 u8 bytes[4];
273 } out;
274
275 union {
276 u32 value;
277 u8 bytes[4];
278 } in;
279
280
281 in.value = value;
282
283 out.bytes[0] = in.bytes[3];
284 out.bytes[1] = in.bytes[2];
285 out.bytes[2] = in.bytes[1];
286 out.bytes[3] = in.bytes[0];
287
288 return (out.value);
289 }
290
291
292 /*******************************************************************************
293 *
294 * FUNCTION: Acpi_aml_eisa_id_to_string
295 *
296 * PARAMETERS: Numeric_id - EISA ID to be converted
297 * Out_string - Where to put the converted string (8 bytes)
298 *
299 * DESCRIPTION: Convert a numeric EISA ID to string representation
300 *
301 ******************************************************************************/
302
303 ACPI_STATUS
304 acpi_aml_eisa_id_to_string (
305 u32 numeric_id,
306 NATIVE_CHAR *out_string)
307 {
308 u32 id;
309
310 /* swap to big-endian to get contiguous bits */
311
312 id = _ntohl (numeric_id);
313
314 out_string[0] = (char) ('@' + ((id >> 26) & 0x1f));
315 out_string[1] = (char) ('@' + ((id >> 21) & 0x1f));
316 out_string[2] = (char) ('@' + ((id >> 16) & 0x1f));
317 out_string[3] = acpi_gbl_hex_to_ascii[(id >> 12) & 0xf];
318 out_string[4] = acpi_gbl_hex_to_ascii[(id >> 8) & 0xf];
319 out_string[5] = acpi_gbl_hex_to_ascii[(id >> 4) & 0xf];
320 out_string[6] = acpi_gbl_hex_to_ascii[id & 0xf];
321 out_string[7] = 0;
322
323 return (AE_OK);
324 }
325
326
327 /*******************************************************************************
328 *
329 * FUNCTION: Acpi_aml_unsigned_integer_to_string
330 *
331 * PARAMETERS: Value - Value to be converted
332 * Out_string - Where to put the converted string (8 bytes)
333 *
334 * RETURN: Convert a number to string representation
335 *
336 ******************************************************************************/
337
338 ACPI_STATUS
339 acpi_aml_unsigned_integer_to_string (
340 ACPI_INTEGER value,
341 NATIVE_CHAR *out_string)
342 {
343 u32 count;
344 u32 digits_needed;
345
346
347 digits_needed = acpi_aml_digits_needed (value, 10);
348
349 out_string[digits_needed] = '\0';
350
351 for (count = digits_needed; count > 0; count--) {
352 out_string[count-1] = (NATIVE_CHAR) ('0' + (ACPI_MODULO (value, 10)));
353 value = ACPI_DIVIDE (value, 10);
354 }
355
356 return (AE_OK);
357 }
358
359