Merge trunk HEAD (46152)
[reactos.git] / drivers / bus / acpi / parser / psutils.c
1 /******************************************************************************
2 *
3 * Module Name: psutils - Parser miscellaneous utilities (Parser only)
4 * $Revision: 1.1 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26
27 #include <acpi.h>
28
29 #define _COMPONENT ACPI_PARSER
30 MODULE_NAME ("psutils")
31
32
33 #define PARSEOP_GENERIC 0x01
34 #define PARSEOP_NAMED 0x02
35 #define PARSEOP_DEFERRED 0x03
36 #define PARSEOP_BYTELIST 0x04
37 #define PARSEOP_IN_CACHE 0x80
38
39
40 /*******************************************************************************
41 *
42 * FUNCTION: Acpi_ps_init_op
43 *
44 * PARAMETERS: Op - A newly allocated Op object
45 * Opcode - Opcode to store in the Op
46 *
47 * RETURN: Status
48 *
49 * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
50 * opcode
51 *
52 ******************************************************************************/
53
54 void
55 acpi_ps_init_op (
56 ACPI_PARSE_OBJECT *op,
57 u16 opcode)
58 {
59 ACPI_OPCODE_INFO *aml_op;
60
61
62 op->data_type = ACPI_DESC_TYPE_PARSER;
63 op->opcode = opcode;
64
65 aml_op = acpi_ps_get_opcode_info (opcode);
66
67 DEBUG_ONLY_MEMBERS (STRNCPY (op->op_name, aml_op->name,
68 sizeof (op->op_name)));
69 }
70
71
72 /*******************************************************************************
73 *
74 * FUNCTION: Acpi_ps_alloc_op
75 *
76 * PARAMETERS: Opcode - Opcode that will be stored in the new Op
77 *
78 * RETURN: Pointer to the new Op.
79 *
80 * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
81 * opcode. A cache of opcodes is available for the pure
82 * GENERIC_OP, since this is by far the most commonly used.
83 *
84 ******************************************************************************/
85
86 ACPI_PARSE_OBJECT*
87 acpi_ps_alloc_op (
88 u16 opcode)
89 {
90 ACPI_PARSE_OBJECT *op = NULL;
91 u32 size;
92 u8 flags;
93
94
95 /* Allocate the minimum required size object */
96
97 if (acpi_ps_is_deferred_op (opcode)) {
98 size = sizeof (ACPI_PARSE2_OBJECT);
99 flags = PARSEOP_DEFERRED;
100 }
101
102 else if (acpi_ps_is_named_op (opcode)) {
103 size = sizeof (ACPI_PARSE2_OBJECT);
104 flags = PARSEOP_NAMED;
105 }
106
107 else if (acpi_ps_is_bytelist_op (opcode)) {
108 size = sizeof (ACPI_PARSE2_OBJECT);
109 flags = PARSEOP_BYTELIST;
110 }
111
112 else {
113 size = sizeof (ACPI_PARSE_OBJECT);
114 flags = PARSEOP_GENERIC;
115 }
116
117
118 if (size == sizeof (ACPI_PARSE_OBJECT)) {
119 /*
120 * The generic op is by far the most common (16 to 1), and therefore
121 * the op cache is implemented with this type.
122 *
123 * Check if there is an Op already available in the cache
124 */
125
126 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
127 acpi_gbl_parse_cache_requests++;
128 if (acpi_gbl_parse_cache) {
129 /* Extract an op from the front of the cache list */
130
131 acpi_gbl_parse_cache_depth--;
132 acpi_gbl_parse_cache_hits++;
133
134 op = acpi_gbl_parse_cache;
135 acpi_gbl_parse_cache = op->next;
136
137
138 /* Clear the previously used Op */
139
140 MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT));
141
142 }
143 acpi_cm_release_mutex (ACPI_MTX_CACHES);
144 }
145
146 else {
147 /*
148 * The generic op is by far the most common (16 to 1), and therefore
149 * the op cache is implemented with this type.
150 *
151 * Check if there is an Op already available in the cache
152 */
153
154 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
155 acpi_gbl_ext_parse_cache_requests++;
156 if (acpi_gbl_ext_parse_cache) {
157 /* Extract an op from the front of the cache list */
158
159 acpi_gbl_ext_parse_cache_depth--;
160 acpi_gbl_ext_parse_cache_hits++;
161
162 op = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache;
163 acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op->next;
164
165
166 /* Clear the previously used Op */
167
168 MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT));
169
170 }
171 acpi_cm_release_mutex (ACPI_MTX_CACHES);
172 }
173
174
175 /* Allocate a new Op if necessary */
176
177 if (!op) {
178 op = acpi_cm_callocate (size);
179 }
180
181 /* Initialize the Op */
182 if (op) {
183 acpi_ps_init_op (op, opcode);
184 op->flags = flags;
185 }
186
187 return (op);
188 }
189
190
191 /*******************************************************************************
192 *
193 * FUNCTION: Acpi_ps_free_op
194 *
195 * PARAMETERS: Op - Op to be freed
196 *
197 * RETURN: None.
198 *
199 * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
200 * or actually free it.
201 *
202 ******************************************************************************/
203
204 void
205 acpi_ps_free_op (
206 ACPI_PARSE_OBJECT *op)
207 {
208
209
210
211 if (op->flags == PARSEOP_GENERIC) {
212 /* Is the cache full? */
213
214 if (acpi_gbl_parse_cache_depth < MAX_PARSE_CACHE_DEPTH) {
215 /* Put a GENERIC_OP back into the cache */
216
217 /* Clear the previously used Op */
218
219 MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT));
220 op->flags = PARSEOP_IN_CACHE;
221
222 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
223 acpi_gbl_parse_cache_depth++;
224
225 op->next = acpi_gbl_parse_cache;
226 acpi_gbl_parse_cache = op;
227
228 acpi_cm_release_mutex (ACPI_MTX_CACHES);
229 return;
230 }
231 }
232
233 else {
234 /* Is the cache full? */
235
236 if (acpi_gbl_ext_parse_cache_depth < MAX_EXTPARSE_CACHE_DEPTH) {
237 /* Put a GENERIC_OP back into the cache */
238
239 /* Clear the previously used Op */
240
241 MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT));
242 op->flags = PARSEOP_IN_CACHE;
243
244 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
245 acpi_gbl_ext_parse_cache_depth++;
246
247 op->next = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache;
248 acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op;
249
250 acpi_cm_release_mutex (ACPI_MTX_CACHES);
251 return;
252 }
253 }
254
255
256 /*
257 * Not a GENERIC OP, or the cache is full, just free the Op
258 */
259
260 acpi_cm_free (op);
261 }
262
263
264 /*******************************************************************************
265 *
266 * FUNCTION: Acpi_ps_delete_parse_cache
267 *
268 * PARAMETERS: None
269 *
270 * RETURN: None
271 *
272 * DESCRIPTION: Free all objects that are on the parse cache list.
273 *
274 ******************************************************************************/
275
276 void
277 acpi_ps_delete_parse_cache (
278 void)
279 {
280 ACPI_PARSE_OBJECT *next;
281
282
283 /* Traverse the global cache list */
284
285 while (acpi_gbl_parse_cache) {
286 /* Delete one cached state object */
287
288 next = acpi_gbl_parse_cache->next;
289 acpi_cm_free (acpi_gbl_parse_cache);
290 acpi_gbl_parse_cache = next;
291 acpi_gbl_parse_cache_depth--;
292 }
293
294 /* Traverse the global cache list */
295
296 while (acpi_gbl_ext_parse_cache) {
297 /* Delete one cached state object */
298
299 next = acpi_gbl_ext_parse_cache->next;
300 acpi_cm_free (acpi_gbl_ext_parse_cache);
301 acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) next;
302 acpi_gbl_ext_parse_cache_depth--;
303 }
304
305 return;
306 }
307
308
309 /*******************************************************************************
310 *
311 * FUNCTION: Utility functions
312 *
313 * DESCRIPTION: Low level functions
314 *
315 * TBD: [Restructure]
316 * 1) Some of these functions should be macros
317 * 2) Some can be simplified
318 *
319 ******************************************************************************/
320
321
322 /*
323 * Is "c" a namestring lead character?
324 */
325
326
327 u8
328 acpi_ps_is_leading_char (
329 u32 c)
330 {
331 return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
332 }
333
334
335 /*
336 * Is "c" a namestring prefix character?
337 */
338 u8
339 acpi_ps_is_prefix_char (
340 u32 c)
341 {
342 return ((u8) (c == '\\' || c == '^'));
343 }
344
345
346 u8
347 acpi_ps_is_namespace_object_op (
348 u16 opcode)
349 {
350 return ((u8)
351 (opcode == AML_SCOPE_OP ||
352 opcode == AML_DEVICE_OP ||
353 opcode == AML_THERMAL_ZONE_OP ||
354 opcode == AML_METHOD_OP ||
355 opcode == AML_POWER_RES_OP ||
356 opcode == AML_PROCESSOR_OP ||
357 opcode == AML_DEF_FIELD_OP ||
358 opcode == AML_INDEX_FIELD_OP ||
359 opcode == AML_BANK_FIELD_OP ||
360 opcode == AML_NAMEDFIELD_OP ||
361 opcode == AML_NAME_OP ||
362 opcode == AML_ALIAS_OP ||
363 opcode == AML_MUTEX_OP ||
364 opcode == AML_EVENT_OP ||
365 opcode == AML_REGION_OP ||
366 opcode == AML_CREATE_FIELD_OP ||
367 opcode == AML_BIT_FIELD_OP ||
368 opcode == AML_BYTE_FIELD_OP ||
369 opcode == AML_WORD_FIELD_OP ||
370 opcode == AML_DWORD_FIELD_OP ||
371 opcode == AML_METHODCALL_OP ||
372 opcode == AML_NAMEPATH_OP));
373 }
374
375 u8
376 acpi_ps_is_namespace_op (
377 u16 opcode)
378 {
379 return ((u8)
380 (opcode == AML_SCOPE_OP ||
381 opcode == AML_DEVICE_OP ||
382 opcode == AML_THERMAL_ZONE_OP ||
383 opcode == AML_METHOD_OP ||
384 opcode == AML_POWER_RES_OP ||
385 opcode == AML_PROCESSOR_OP ||
386 opcode == AML_DEF_FIELD_OP ||
387 opcode == AML_INDEX_FIELD_OP ||
388 opcode == AML_BANK_FIELD_OP ||
389 opcode == AML_NAME_OP ||
390 opcode == AML_ALIAS_OP ||
391 opcode == AML_MUTEX_OP ||
392 opcode == AML_EVENT_OP ||
393 opcode == AML_REGION_OP ||
394 opcode == AML_NAMEDFIELD_OP));
395 }
396
397
398 /*
399 * Is opcode for a named object Op?
400 * (Includes all named object opcodes)
401 *
402 * TBD: [Restructure] Need a better way than this brute force approach!
403 */
404 u8
405 acpi_ps_is_node_op (
406 u16 opcode)
407 {
408 return ((u8)
409 (opcode == AML_SCOPE_OP ||
410 opcode == AML_DEVICE_OP ||
411 opcode == AML_THERMAL_ZONE_OP ||
412 opcode == AML_METHOD_OP ||
413 opcode == AML_POWER_RES_OP ||
414 opcode == AML_PROCESSOR_OP ||
415 opcode == AML_NAMEDFIELD_OP ||
416 opcode == AML_NAME_OP ||
417 opcode == AML_ALIAS_OP ||
418 opcode == AML_MUTEX_OP ||
419 opcode == AML_EVENT_OP ||
420 opcode == AML_REGION_OP ||
421
422
423 opcode == AML_CREATE_FIELD_OP ||
424 opcode == AML_BIT_FIELD_OP ||
425 opcode == AML_BYTE_FIELD_OP ||
426 opcode == AML_WORD_FIELD_OP ||
427 opcode == AML_DWORD_FIELD_OP ||
428 opcode == AML_METHODCALL_OP ||
429 opcode == AML_NAMEPATH_OP));
430 }
431
432
433 /*
434 * Is opcode for a named Op?
435 */
436 u8
437 acpi_ps_is_named_op (
438 u16 opcode)
439 {
440 return ((u8)
441 (opcode == AML_SCOPE_OP ||
442 opcode == AML_DEVICE_OP ||
443 opcode == AML_THERMAL_ZONE_OP ||
444 opcode == AML_METHOD_OP ||
445 opcode == AML_POWER_RES_OP ||
446 opcode == AML_PROCESSOR_OP ||
447 opcode == AML_NAME_OP ||
448 opcode == AML_ALIAS_OP ||
449 opcode == AML_MUTEX_OP ||
450 opcode == AML_EVENT_OP ||
451 opcode == AML_REGION_OP ||
452 opcode == AML_NAMEDFIELD_OP));
453 }
454
455
456 u8
457 acpi_ps_is_deferred_op (
458 u16 opcode)
459 {
460 return ((u8)
461 (opcode == AML_METHOD_OP ||
462 opcode == AML_CREATE_FIELD_OP ||
463 opcode == AML_BIT_FIELD_OP ||
464 opcode == AML_BYTE_FIELD_OP ||
465 opcode == AML_WORD_FIELD_OP ||
466 opcode == AML_DWORD_FIELD_OP ||
467 opcode == AML_REGION_OP));
468 }
469
470
471 /*
472 * Is opcode for a bytelist?
473 */
474 u8
475 acpi_ps_is_bytelist_op (
476 u16 opcode)
477 {
478 return ((u8) (opcode == AML_BYTELIST_OP));
479 }
480
481
482 /*
483 * Is opcode for a Field, Index_field, or Bank_field
484 */
485 u8
486 acpi_ps_is_field_op (
487 u16 opcode)
488 {
489 return ((u8)
490 (opcode == AML_CREATE_FIELD_OP
491 || opcode == AML_DEF_FIELD_OP
492 || opcode == AML_INDEX_FIELD_OP
493 || opcode == AML_BANK_FIELD_OP));
494 }
495
496
497 /*
498 * Is field creation op
499 */
500 u8
501 acpi_ps_is_create_field_op (
502 u16 opcode)
503 {
504 return ((u8)
505 (opcode == AML_CREATE_FIELD_OP ||
506 opcode == AML_BIT_FIELD_OP ||
507 opcode == AML_BYTE_FIELD_OP ||
508 opcode == AML_WORD_FIELD_OP ||
509 opcode == AML_DWORD_FIELD_OP));
510 }
511
512
513 /*
514 * Cast an acpi_op to an acpi_extended_op if possible
515 */
516
517 /* TBD: This is very inefficient, fix */
518 ACPI_PARSE2_OBJECT *
519 acpi_ps_to_extended_op (
520 ACPI_PARSE_OBJECT *op)
521 {
522 return ((acpi_ps_is_deferred_op (op->opcode) || acpi_ps_is_named_op (op->opcode) || acpi_ps_is_bytelist_op (op->opcode))
523 ? ( (ACPI_PARSE2_OBJECT *) op) : NULL);
524 }
525
526
527 /*
528 * Get op's name (4-byte name segment) or 0 if unnamed
529 */
530 u32
531 acpi_ps_get_name (
532 ACPI_PARSE_OBJECT *op)
533 {
534 ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op);
535
536 return (named ? named->name : 0);
537 }
538
539
540 /*
541 * Set op's name
542 */
543 void
544 acpi_ps_set_name (
545 ACPI_PARSE_OBJECT *op,
546 u32 name)
547 {
548 ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op);
549
550 if (named) {
551 named->name = name;
552 }
553 }
554