- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / parser / psutils.c
blob3bac4a647012ac60481d2b853738c61370e87fab
1 /******************************************************************************
3 * Module Name: psutils - Parser miscellaneous utilities (Parser only)
4 * $Revision: 30 $
6 *****************************************************************************/
8 /*
9 * Copyright (C) 2000 R. Byron Moore
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.
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.
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
27 #include "acpi.h"
28 #include "acparser.h"
29 #include "amlcode.h"
31 #define _COMPONENT PARSER
32 MODULE_NAME ("psutils")
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
42 /*******************************************************************************
44 * FUNCTION: Acpi_ps_init_op
46 * PARAMETERS: Op - A newly allocated Op object
47 * Opcode - Opcode to store in the Op
49 * RETURN: Status
51 * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
52 * opcode
54 ******************************************************************************/
56 void
57 acpi_ps_init_op (
58 ACPI_PARSE_OBJECT *op,
59 u16 opcode)
61 ACPI_OPCODE_INFO *aml_op;
64 op->data_type = ACPI_DESC_TYPE_PARSER;
65 op->opcode = opcode;
67 aml_op = acpi_ps_get_opcode_info (opcode);
69 DEBUG_ONLY_MEMBERS (STRNCPY (op->op_name, aml_op->name,
70 sizeof (op->op_name)));
74 /*******************************************************************************
76 * FUNCTION: Acpi_ps_alloc_op
78 * PARAMETERS: Opcode - Opcode that will be stored in the new Op
80 * RETURN: Pointer to the new Op.
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.
86 ******************************************************************************/
88 ACPI_PARSE_OBJECT*
89 acpi_ps_alloc_op (
90 u16 opcode)
92 ACPI_PARSE_OBJECT *op = NULL;
93 u32 size;
94 u8 flags;
97 /* Allocate the minimum required size object */
99 if (acpi_ps_is_deferred_op (opcode)) {
100 size = sizeof (ACPI_PARSE2_OBJECT);
101 flags = PARSEOP_DEFERRED;
104 else if (acpi_ps_is_named_op (opcode)) {
105 size = sizeof (ACPI_PARSE2_OBJECT);
106 flags = PARSEOP_NAMED;
109 else if (acpi_ps_is_bytelist_op (opcode)) {
110 size = sizeof (ACPI_PARSE2_OBJECT);
111 flags = PARSEOP_BYTELIST;
114 else {
115 size = sizeof (ACPI_PARSE_OBJECT);
116 flags = PARSEOP_GENERIC;
120 if (size == sizeof (ACPI_PARSE_OBJECT)) {
122 * The generic op is by far the most common (16 to 1), and therefore
123 * the op cache is implemented with this type.
125 * Check if there is an Op already available in the cache
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 */
133 acpi_gbl_parse_cache_depth--;
134 acpi_gbl_parse_cache_hits++;
136 op = acpi_gbl_parse_cache;
137 acpi_gbl_parse_cache = op->next;
140 /* Clear the previously used Op */
142 MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT));
145 acpi_cm_release_mutex (ACPI_MTX_CACHES);
148 else {
150 * The generic op is by far the most common (16 to 1), and therefore
151 * the op cache is implemented with this type.
153 * Check if there is an Op already available in the cache
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 */
161 acpi_gbl_ext_parse_cache_depth--;
162 acpi_gbl_ext_parse_cache_hits++;
164 op = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache;
165 acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op->next;
168 /* Clear the previously used Op */
170 MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT));
173 acpi_cm_release_mutex (ACPI_MTX_CACHES);
177 /* Allocate a new Op if necessary */
179 if (!op) {
180 op = acpi_cm_callocate (size);
183 /* Initialize the Op */
184 if (op) {
185 acpi_ps_init_op (op, opcode);
186 op->flags = flags;
189 return (op);
193 /*******************************************************************************
195 * FUNCTION: Acpi_ps_free_op
197 * PARAMETERS: Op - Op to be freed
199 * RETURN: None.
201 * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
202 * or actually free it.
204 ******************************************************************************/
206 void
207 acpi_ps_free_op (
208 ACPI_PARSE_OBJECT *op)
213 if (op->flags == PARSEOP_GENERIC) {
214 /* Is the cache full? */
216 if (acpi_gbl_parse_cache_depth < MAX_PARSE_CACHE_DEPTH) {
217 /* Put a GENERIC_OP back into the cache */
219 /* Clear the previously used Op */
221 MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT));
222 op->flags = PARSEOP_IN_CACHE;
224 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
225 acpi_gbl_parse_cache_depth++;
227 op->next = acpi_gbl_parse_cache;
228 acpi_gbl_parse_cache = op;
230 acpi_cm_release_mutex (ACPI_MTX_CACHES);
231 return;
235 else {
236 /* Is the cache full? */
238 if (acpi_gbl_ext_parse_cache_depth < MAX_EXTPARSE_CACHE_DEPTH) {
239 /* Put a GENERIC_OP back into the cache */
241 /* Clear the previously used Op */
243 MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT));
244 op->flags = PARSEOP_IN_CACHE;
246 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
247 acpi_gbl_ext_parse_cache_depth++;
249 op->next = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache;
250 acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op;
252 acpi_cm_release_mutex (ACPI_MTX_CACHES);
253 return;
259 * Not a GENERIC OP, or the cache is full, just free the Op
262 acpi_cm_free (op);
266 /*******************************************************************************
268 * FUNCTION: Acpi_ps_delete_parse_cache
270 * PARAMETERS: None
272 * RETURN: None
274 * DESCRIPTION: Free all objects that are on the parse cache list.
276 ******************************************************************************/
278 void
279 acpi_ps_delete_parse_cache (
280 void)
282 ACPI_PARSE_OBJECT *next;
285 /* Traverse the global cache list */
287 while (acpi_gbl_parse_cache) {
288 /* Delete one cached state object */
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--;
296 /* Traverse the global cache list */
298 while (acpi_gbl_ext_parse_cache) {
299 /* Delete one cached state object */
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--;
307 return;
311 /*******************************************************************************
313 * FUNCTION: Utility functions
315 * DESCRIPTION: Low level functions
317 * TBD: [Restructure]
318 * 1) Some of these functions should be macros
319 * 2) Some can be simplified
321 ******************************************************************************/
325 * Is "c" a namestring lead character?
330 acpi_ps_is_leading_char (
331 u32 c)
333 return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
338 * Is "c" a namestring prefix character?
341 acpi_ps_is_prefix_char (
342 u32 c)
344 return ((u8) (c == '\\' || c == '^'));
349 acpi_ps_is_namespace_object_op (
350 u16 opcode)
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));
378 acpi_ps_is_namespace_op (
379 u16 opcode)
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));
401 * Is opcode for a named object Op?
402 * (Includes all named object opcodes)
404 * TBD: [Restructure] Need a better way than this brute force approach!
407 acpi_ps_is_node_op (
408 u16 opcode)
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 ||
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));
436 * Is opcode for a named Op?
439 acpi_ps_is_named_op (
440 u16 opcode)
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));
459 acpi_ps_is_deferred_op (
460 u16 opcode)
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));
474 * Is opcode for a bytelist?
477 acpi_ps_is_bytelist_op (
478 u16 opcode)
480 return ((u8) (opcode == AML_BYTELIST_OP));
485 * Is opcode for a Field, Index_field, or Bank_field
488 acpi_ps_is_field_op (
489 u16 opcode)
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));
500 * Is field creation op
503 acpi_ps_is_create_field_op (
504 u16 opcode)
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));
516 * Cast an acpi_op to an acpi_extended_op if possible
519 /* TBD: This is very inefficient, fix */
520 ACPI_PARSE2_OBJECT *
521 acpi_ps_to_extended_op (
522 ACPI_PARSE_OBJECT *op)
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);
530 * Get op's name (4-byte name segment) or 0 if unnamed
533 acpi_ps_get_name (
534 ACPI_PARSE_OBJECT *op)
536 ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op);
538 return (named ? named->name : 0);
543 * Set op's name
545 void
546 acpi_ps_set_name (
547 ACPI_PARSE_OBJECT *op,
548 u32 name)
550 ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op);
552 if (named) {
553 named->name = name;