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