mirror of
https://github.com/reactos/reactos.git
synced 2024-09-18 16:52:54 +00:00
c501d8112c
svn path=/branches/aicom-network-fixes/; revision=34994
555 lines
13 KiB
C
555 lines
13 KiB
C
/******************************************************************************
|
|
*
|
|
* Module Name: psutils - Parser miscellaneous utilities (Parser only)
|
|
* $Revision: 1.1 $
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
* Copyright (C) 2000, 2001 R. Byron Moore
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
|
|
#include <acpi.h>
|
|
|
|
#define _COMPONENT ACPI_PARSER
|
|
MODULE_NAME ("psutils")
|
|
|
|
|
|
#define PARSEOP_GENERIC 0x01
|
|
#define PARSEOP_NAMED 0x02
|
|
#define PARSEOP_DEFERRED 0x03
|
|
#define PARSEOP_BYTELIST 0x04
|
|
#define PARSEOP_IN_CACHE 0x80
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: Acpi_ps_init_op
|
|
*
|
|
* PARAMETERS: Op - A newly allocated Op object
|
|
* Opcode - Opcode to store in the Op
|
|
*
|
|
* RETURN: Status
|
|
*
|
|
* DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
|
|
* opcode
|
|
*
|
|
******************************************************************************/
|
|
|
|
void
|
|
acpi_ps_init_op (
|
|
ACPI_PARSE_OBJECT *op,
|
|
u16 opcode)
|
|
{
|
|
ACPI_OPCODE_INFO *aml_op;
|
|
|
|
|
|
op->data_type = ACPI_DESC_TYPE_PARSER;
|
|
op->opcode = opcode;
|
|
|
|
aml_op = acpi_ps_get_opcode_info (opcode);
|
|
|
|
DEBUG_ONLY_MEMBERS (STRNCPY (op->op_name, aml_op->name,
|
|
sizeof (op->op_name)));
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: Acpi_ps_alloc_op
|
|
*
|
|
* PARAMETERS: Opcode - Opcode that will be stored in the new Op
|
|
*
|
|
* RETURN: Pointer to the new Op.
|
|
*
|
|
* DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
|
|
* opcode. A cache of opcodes is available for the pure
|
|
* GENERIC_OP, since this is by far the most commonly used.
|
|
*
|
|
******************************************************************************/
|
|
|
|
ACPI_PARSE_OBJECT*
|
|
acpi_ps_alloc_op (
|
|
u16 opcode)
|
|
{
|
|
ACPI_PARSE_OBJECT *op = NULL;
|
|
u32 size;
|
|
u8 flags;
|
|
|
|
|
|
/* Allocate the minimum required size object */
|
|
|
|
if (acpi_ps_is_deferred_op (opcode)) {
|
|
size = sizeof (ACPI_PARSE2_OBJECT);
|
|
flags = PARSEOP_DEFERRED;
|
|
}
|
|
|
|
else if (acpi_ps_is_named_op (opcode)) {
|
|
size = sizeof (ACPI_PARSE2_OBJECT);
|
|
flags = PARSEOP_NAMED;
|
|
}
|
|
|
|
else if (acpi_ps_is_bytelist_op (opcode)) {
|
|
size = sizeof (ACPI_PARSE2_OBJECT);
|
|
flags = PARSEOP_BYTELIST;
|
|
}
|
|
|
|
else {
|
|
size = sizeof (ACPI_PARSE_OBJECT);
|
|
flags = PARSEOP_GENERIC;
|
|
}
|
|
|
|
|
|
if (size == sizeof (ACPI_PARSE_OBJECT)) {
|
|
/*
|
|
* The generic op is by far the most common (16 to 1), and therefore
|
|
* the op cache is implemented with this type.
|
|
*
|
|
* Check if there is an Op already available in the cache
|
|
*/
|
|
|
|
acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
|
|
acpi_gbl_parse_cache_requests++;
|
|
if (acpi_gbl_parse_cache) {
|
|
/* Extract an op from the front of the cache list */
|
|
|
|
acpi_gbl_parse_cache_depth--;
|
|
acpi_gbl_parse_cache_hits++;
|
|
|
|
op = acpi_gbl_parse_cache;
|
|
acpi_gbl_parse_cache = op->next;
|
|
|
|
|
|
/* Clear the previously used Op */
|
|
|
|
MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT));
|
|
|
|
}
|
|
acpi_cm_release_mutex (ACPI_MTX_CACHES);
|
|
}
|
|
|
|
else {
|
|
/*
|
|
* The generic op is by far the most common (16 to 1), and therefore
|
|
* the op cache is implemented with this type.
|
|
*
|
|
* Check if there is an Op already available in the cache
|
|
*/
|
|
|
|
acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
|
|
acpi_gbl_ext_parse_cache_requests++;
|
|
if (acpi_gbl_ext_parse_cache) {
|
|
/* Extract an op from the front of the cache list */
|
|
|
|
acpi_gbl_ext_parse_cache_depth--;
|
|
acpi_gbl_ext_parse_cache_hits++;
|
|
|
|
op = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache;
|
|
acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op->next;
|
|
|
|
|
|
/* Clear the previously used Op */
|
|
|
|
MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT));
|
|
|
|
}
|
|
acpi_cm_release_mutex (ACPI_MTX_CACHES);
|
|
}
|
|
|
|
|
|
/* Allocate a new Op if necessary */
|
|
|
|
if (!op) {
|
|
op = acpi_cm_callocate (size);
|
|
}
|
|
|
|
/* Initialize the Op */
|
|
if (op) {
|
|
acpi_ps_init_op (op, opcode);
|
|
op->flags = flags;
|
|
}
|
|
|
|
return (op);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: Acpi_ps_free_op
|
|
*
|
|
* PARAMETERS: Op - Op to be freed
|
|
*
|
|
* RETURN: None.
|
|
*
|
|
* DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
|
|
* or actually free it.
|
|
*
|
|
******************************************************************************/
|
|
|
|
void
|
|
acpi_ps_free_op (
|
|
ACPI_PARSE_OBJECT *op)
|
|
{
|
|
|
|
|
|
|
|
if (op->flags == PARSEOP_GENERIC) {
|
|
/* Is the cache full? */
|
|
|
|
if (acpi_gbl_parse_cache_depth < MAX_PARSE_CACHE_DEPTH) {
|
|
/* Put a GENERIC_OP back into the cache */
|
|
|
|
/* Clear the previously used Op */
|
|
|
|
MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT));
|
|
op->flags = PARSEOP_IN_CACHE;
|
|
|
|
acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
|
|
acpi_gbl_parse_cache_depth++;
|
|
|
|
op->next = acpi_gbl_parse_cache;
|
|
acpi_gbl_parse_cache = op;
|
|
|
|
acpi_cm_release_mutex (ACPI_MTX_CACHES);
|
|
return;
|
|
}
|
|
}
|
|
|
|
else {
|
|
/* Is the cache full? */
|
|
|
|
if (acpi_gbl_ext_parse_cache_depth < MAX_EXTPARSE_CACHE_DEPTH) {
|
|
/* Put a GENERIC_OP back into the cache */
|
|
|
|
/* Clear the previously used Op */
|
|
|
|
MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT));
|
|
op->flags = PARSEOP_IN_CACHE;
|
|
|
|
acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
|
|
acpi_gbl_ext_parse_cache_depth++;
|
|
|
|
op->next = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache;
|
|
acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op;
|
|
|
|
acpi_cm_release_mutex (ACPI_MTX_CACHES);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Not a GENERIC OP, or the cache is full, just free the Op
|
|
*/
|
|
|
|
acpi_cm_free (op);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: Acpi_ps_delete_parse_cache
|
|
*
|
|
* PARAMETERS: None
|
|
*
|
|
* RETURN: None
|
|
*
|
|
* DESCRIPTION: Free all objects that are on the parse cache list.
|
|
*
|
|
******************************************************************************/
|
|
|
|
void
|
|
acpi_ps_delete_parse_cache (
|
|
void)
|
|
{
|
|
ACPI_PARSE_OBJECT *next;
|
|
|
|
|
|
/* Traverse the global cache list */
|
|
|
|
while (acpi_gbl_parse_cache) {
|
|
/* Delete one cached state object */
|
|
|
|
next = acpi_gbl_parse_cache->next;
|
|
acpi_cm_free (acpi_gbl_parse_cache);
|
|
acpi_gbl_parse_cache = next;
|
|
acpi_gbl_parse_cache_depth--;
|
|
}
|
|
|
|
/* Traverse the global cache list */
|
|
|
|
while (acpi_gbl_ext_parse_cache) {
|
|
/* Delete one cached state object */
|
|
|
|
next = acpi_gbl_ext_parse_cache->next;
|
|
acpi_cm_free (acpi_gbl_ext_parse_cache);
|
|
acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) next;
|
|
acpi_gbl_ext_parse_cache_depth--;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: Utility functions
|
|
*
|
|
* DESCRIPTION: Low level functions
|
|
*
|
|
* TBD: [Restructure]
|
|
* 1) Some of these functions should be macros
|
|
* 2) Some can be simplified
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
/*
|
|
* Is "c" a namestring lead character?
|
|
*/
|
|
|
|
|
|
u8
|
|
acpi_ps_is_leading_char (
|
|
u32 c)
|
|
{
|
|
return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
|
|
}
|
|
|
|
|
|
/*
|
|
* Is "c" a namestring prefix character?
|
|
*/
|
|
u8
|
|
acpi_ps_is_prefix_char (
|
|
u32 c)
|
|
{
|
|
return ((u8) (c == '\\' || c == '^'));
|
|
}
|
|
|
|
|
|
u8
|
|
acpi_ps_is_namespace_object_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_SCOPE_OP ||
|
|
opcode == AML_DEVICE_OP ||
|
|
opcode == AML_THERMAL_ZONE_OP ||
|
|
opcode == AML_METHOD_OP ||
|
|
opcode == AML_POWER_RES_OP ||
|
|
opcode == AML_PROCESSOR_OP ||
|
|
opcode == AML_DEF_FIELD_OP ||
|
|
opcode == AML_INDEX_FIELD_OP ||
|
|
opcode == AML_BANK_FIELD_OP ||
|
|
opcode == AML_NAMEDFIELD_OP ||
|
|
opcode == AML_NAME_OP ||
|
|
opcode == AML_ALIAS_OP ||
|
|
opcode == AML_MUTEX_OP ||
|
|
opcode == AML_EVENT_OP ||
|
|
opcode == AML_REGION_OP ||
|
|
opcode == AML_CREATE_FIELD_OP ||
|
|
opcode == AML_BIT_FIELD_OP ||
|
|
opcode == AML_BYTE_FIELD_OP ||
|
|
opcode == AML_WORD_FIELD_OP ||
|
|
opcode == AML_DWORD_FIELD_OP ||
|
|
opcode == AML_METHODCALL_OP ||
|
|
opcode == AML_NAMEPATH_OP));
|
|
}
|
|
|
|
u8
|
|
acpi_ps_is_namespace_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_SCOPE_OP ||
|
|
opcode == AML_DEVICE_OP ||
|
|
opcode == AML_THERMAL_ZONE_OP ||
|
|
opcode == AML_METHOD_OP ||
|
|
opcode == AML_POWER_RES_OP ||
|
|
opcode == AML_PROCESSOR_OP ||
|
|
opcode == AML_DEF_FIELD_OP ||
|
|
opcode == AML_INDEX_FIELD_OP ||
|
|
opcode == AML_BANK_FIELD_OP ||
|
|
opcode == AML_NAME_OP ||
|
|
opcode == AML_ALIAS_OP ||
|
|
opcode == AML_MUTEX_OP ||
|
|
opcode == AML_EVENT_OP ||
|
|
opcode == AML_REGION_OP ||
|
|
opcode == AML_NAMEDFIELD_OP));
|
|
}
|
|
|
|
|
|
/*
|
|
* Is opcode for a named object Op?
|
|
* (Includes all named object opcodes)
|
|
*
|
|
* TBD: [Restructure] Need a better way than this brute force approach!
|
|
*/
|
|
u8
|
|
acpi_ps_is_node_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_SCOPE_OP ||
|
|
opcode == AML_DEVICE_OP ||
|
|
opcode == AML_THERMAL_ZONE_OP ||
|
|
opcode == AML_METHOD_OP ||
|
|
opcode == AML_POWER_RES_OP ||
|
|
opcode == AML_PROCESSOR_OP ||
|
|
opcode == AML_NAMEDFIELD_OP ||
|
|
opcode == AML_NAME_OP ||
|
|
opcode == AML_ALIAS_OP ||
|
|
opcode == AML_MUTEX_OP ||
|
|
opcode == AML_EVENT_OP ||
|
|
opcode == AML_REGION_OP ||
|
|
|
|
|
|
opcode == AML_CREATE_FIELD_OP ||
|
|
opcode == AML_BIT_FIELD_OP ||
|
|
opcode == AML_BYTE_FIELD_OP ||
|
|
opcode == AML_WORD_FIELD_OP ||
|
|
opcode == AML_DWORD_FIELD_OP ||
|
|
opcode == AML_METHODCALL_OP ||
|
|
opcode == AML_NAMEPATH_OP));
|
|
}
|
|
|
|
|
|
/*
|
|
* Is opcode for a named Op?
|
|
*/
|
|
u8
|
|
acpi_ps_is_named_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_SCOPE_OP ||
|
|
opcode == AML_DEVICE_OP ||
|
|
opcode == AML_THERMAL_ZONE_OP ||
|
|
opcode == AML_METHOD_OP ||
|
|
opcode == AML_POWER_RES_OP ||
|
|
opcode == AML_PROCESSOR_OP ||
|
|
opcode == AML_NAME_OP ||
|
|
opcode == AML_ALIAS_OP ||
|
|
opcode == AML_MUTEX_OP ||
|
|
opcode == AML_EVENT_OP ||
|
|
opcode == AML_REGION_OP ||
|
|
opcode == AML_NAMEDFIELD_OP));
|
|
}
|
|
|
|
|
|
u8
|
|
acpi_ps_is_deferred_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_METHOD_OP ||
|
|
opcode == AML_CREATE_FIELD_OP ||
|
|
opcode == AML_BIT_FIELD_OP ||
|
|
opcode == AML_BYTE_FIELD_OP ||
|
|
opcode == AML_WORD_FIELD_OP ||
|
|
opcode == AML_DWORD_FIELD_OP ||
|
|
opcode == AML_REGION_OP));
|
|
}
|
|
|
|
|
|
/*
|
|
* Is opcode for a bytelist?
|
|
*/
|
|
u8
|
|
acpi_ps_is_bytelist_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8) (opcode == AML_BYTELIST_OP));
|
|
}
|
|
|
|
|
|
/*
|
|
* Is opcode for a Field, Index_field, or Bank_field
|
|
*/
|
|
u8
|
|
acpi_ps_is_field_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_CREATE_FIELD_OP
|
|
|| opcode == AML_DEF_FIELD_OP
|
|
|| opcode == AML_INDEX_FIELD_OP
|
|
|| opcode == AML_BANK_FIELD_OP));
|
|
}
|
|
|
|
|
|
/*
|
|
* Is field creation op
|
|
*/
|
|
u8
|
|
acpi_ps_is_create_field_op (
|
|
u16 opcode)
|
|
{
|
|
return ((u8)
|
|
(opcode == AML_CREATE_FIELD_OP ||
|
|
opcode == AML_BIT_FIELD_OP ||
|
|
opcode == AML_BYTE_FIELD_OP ||
|
|
opcode == AML_WORD_FIELD_OP ||
|
|
opcode == AML_DWORD_FIELD_OP));
|
|
}
|
|
|
|
|
|
/*
|
|
* Cast an acpi_op to an acpi_extended_op if possible
|
|
*/
|
|
|
|
/* TBD: This is very inefficient, fix */
|
|
ACPI_PARSE2_OBJECT *
|
|
acpi_ps_to_extended_op (
|
|
ACPI_PARSE_OBJECT *op)
|
|
{
|
|
return ((acpi_ps_is_deferred_op (op->opcode) || acpi_ps_is_named_op (op->opcode) || acpi_ps_is_bytelist_op (op->opcode))
|
|
? ( (ACPI_PARSE2_OBJECT *) op) : NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* Get op's name (4-byte name segment) or 0 if unnamed
|
|
*/
|
|
u32
|
|
acpi_ps_get_name (
|
|
ACPI_PARSE_OBJECT *op)
|
|
{
|
|
ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op);
|
|
|
|
return (named ? named->name : 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Set op's name
|
|
*/
|
|
void
|
|
acpi_ps_set_name (
|
|
ACPI_PARSE_OBJECT *op,
|
|
u32 name)
|
|
{
|
|
ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op);
|
|
|
|
if (named) {
|
|
named->name = name;
|
|
}
|
|
}
|
|
|