Ported ACPI CA (from the nice guys at Intel) to ReactOS (ACPI bus driver).
authorCasper Hornstrup <chorns@users.sourceforge.net>
Tue, 1 May 2001 23:00:05 +0000 (23:00 +0000)
committerCasper Hornstrup <chorns@users.sourceforge.net>
Tue, 1 May 2001 23:00:05 +0000 (23:00 +0000)
Started on ISA PnP bus driver.

svn path=/trunk/; revision=1850

137 files changed:
reactos/drivers/bus/acpi/acpi.rc [new file with mode: 0644]
reactos/drivers/bus/acpi/changed.txt [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dsfield.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dsmethod.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dsmthdat.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dsobject.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dsopcode.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dsutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dswexec.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dswload.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dswscope.c [new file with mode: 0644]
reactos/drivers/bus/acpi/dispatcher/dswstate.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evevent.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evmisc.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evregion.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evrgnini.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evsci.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evxface.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evxfevnt.c [new file with mode: 0644]
reactos/drivers/bus/acpi/events/evxfregn.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amconfig.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amconvrt.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amcreate.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amdump.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amdyadic.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amfield.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amfldio.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/ammisc.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/ammonad.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/ammutex.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amnames.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amprep.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amregion.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amresnte.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amresolv.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amresop.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amstore.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amstoren.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amstorob.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amsystem.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/executer/amxface.c [new file with mode: 0644]
reactos/drivers/bus/acpi/hardware/hwacpi.c [new file with mode: 0644]
reactos/drivers/bus/acpi/hardware/hwgpe.c [new file with mode: 0644]
reactos/drivers/bus/acpi/hardware/hwregs.c [new file with mode: 0644]
reactos/drivers/bus/acpi/hardware/hwsleep.c [new file with mode: 0644]
reactos/drivers/bus/acpi/hardware/hwtimer.c [new file with mode: 0644]
reactos/drivers/bus/acpi/include/accommon.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acconfig.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acdebug.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acdispat.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acevents.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acexcep.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acglobal.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/achware.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acinterp.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/aclocal.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acmacros.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acnamesp.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acobject.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acoutput.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acparser.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acpi.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acpiosxf.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acpixf.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acresrc.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/acstruct.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/actables.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/actbl.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/actbl1.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/actbl2.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/actbl71.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/actypes.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/amlcode.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/platform/acenv.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/platform/acgcc.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/platform/aclinux.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/platform/acwin.h [new file with mode: 0644]
reactos/drivers/bus/acpi/include/platform/types.h [new file with mode: 0644]
reactos/drivers/bus/acpi/makefile [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsaccess.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsalloc.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nseval.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsinit.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsload.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsnames.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsobject.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nssearch.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nswalk.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsxfname.c [new file with mode: 0644]
reactos/drivers/bus/acpi/namespace/nsxfobj.c [new file with mode: 0644]
reactos/drivers/bus/acpi/ospm/acpienum.c [new file with mode: 0644]
reactos/drivers/bus/acpi/ospm/acpisys.c [new file with mode: 0644]
reactos/drivers/bus/acpi/ospm/include/acpisys.h [new file with mode: 0644]
reactos/drivers/bus/acpi/ospm/osl.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/psargs.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/psopcode.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/psparse.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/psscope.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/pstree.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/psutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/pswalk.c [new file with mode: 0644]
reactos/drivers/bus/acpi/parser/psxface.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsaddr.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rscalc.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rscreate.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsdump.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsio.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsirq.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rslist.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsmemory.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsmisc.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/resource/rsxface.c [new file with mode: 0644]
reactos/drivers/bus/acpi/tables/tbconvrt.c [new file with mode: 0644]
reactos/drivers/bus/acpi/tables/tbget.c [new file with mode: 0644]
reactos/drivers/bus/acpi/tables/tbinstal.c [new file with mode: 0644]
reactos/drivers/bus/acpi/tables/tbutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/tables/tbxface.c [new file with mode: 0644]
reactos/drivers/bus/acpi/tables/tbxfroot.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmalloc.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmclib.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmcopy.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmdebug.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmdelete.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmeval.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmglobal.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cminit.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmobject.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmutils.c [new file with mode: 0644]
reactos/drivers/bus/acpi/utils/cmxface.c [new file with mode: 0644]
reactos/drivers/bus/isapnp/.cvsignore [new file with mode: 0644]
reactos/drivers/bus/isapnp/isapnp.c [new file with mode: 0644]
reactos/drivers/bus/isapnp/isapnp.h [new file with mode: 0644]
reactos/drivers/bus/isapnp/isapnp.rc [new file with mode: 0644]
reactos/drivers/bus/isapnp/makefile [new file with mode: 0644]

diff --git a/reactos/drivers/bus/acpi/acpi.rc b/reactos/drivers/bus/acpi/acpi.rc
new file mode 100644 (file)
index 0000000..f267c92
--- /dev/null
@@ -0,0 +1,37 @@
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+       FILEVERSION     RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+       PRODUCTVERSION  RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+       FILEFLAGSMASK   0x3fL
+#ifdef _DEBUG
+       FILEFLAGS       0x1L
+#else
+       FILEFLAGS       0x0L
+#endif
+       FILEOS          0x40004L
+       FILETYPE        0x2L
+       FILESUBTYPE     0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName",       RES_STR_COMPANY_NAME
+            VALUE "FileDescription",   "ReactOS ACPI Driver\0"
+            VALUE "FileVersion",       RES_STR_FILE_VERSION
+                 VALUE "InternalName", "acpi\0"
+            VALUE "LegalCopyright",    RES_STR_LEGAL_COPYRIGHT
+            VALUE "OriginalFilename",  "acpi.sys\0"
+            VALUE "ProductName",       RES_STR_PRODUCT_NAME
+            VALUE "ProductVersion",    RES_STR_PRODUCT_VERSION
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/reactos/drivers/bus/acpi/changed.txt b/reactos/drivers/bus/acpi/changed.txt
new file mode 100644 (file)
index 0000000..db2ffca
--- /dev/null
@@ -0,0 +1,10 @@
+Changes to ACPI CA
+------------------
+
++ = Added
+- = Removed
+* = Altered
+
++ include/platform/acwin.h
++ include/platform/types.h
+- ospm/*
\ No newline at end of file
diff --git a/reactos/drivers/bus/acpi/dispatcher/dsfield.c b/reactos/drivers/bus/acpi/dispatcher/dsfield.c
new file mode 100644 (file)
index 0000000..c4ca92b
--- /dev/null
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * Module Name: dsfield - Dispatcher field routines
+ *              $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"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dsfield")
+
+
+/*
+ * Field flags: Bits 00 - 03 : Access_type (Any_acc, Byte_acc, etc.)
+ *                   04      : Lock_rule (1 == Lock)
+ *                   05 - 06 : Update_rule
+ */
+
+#define FIELD_ACCESS_TYPE_MASK      0x0F
+#define FIELD_LOCK_RULE_MASK        0x10
+#define FIELD_UPDATE_RULE_MASK      0x60
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_field
+ *
+ * PARAMETERS:  Op              - Op containing the Field definition and args
+ *              Region_node - Object for the containing Operation Region
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a new field in the specified operation region
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_field (
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_NAMESPACE_NODE     *region_node,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status = AE_AML_ERROR;
+       ACPI_PARSE_OBJECT       *arg;
+       ACPI_NAMESPACE_NODE     *node;
+       u8                      field_flags;
+       u8                      access_attribute = 0;
+       u32                     field_bit_position = 0;
+
+
+       /* First arg is the name of the parent Op_region */
+
+       arg = op->value.arg;
+       if (!region_node) {
+               status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
+                                ACPI_TYPE_REGION, IMODE_EXECUTE,
+                                NS_SEARCH_PARENT, walk_state,
+                                &region_node);
+
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+       }
+
+       /* Second arg is the field flags */
+
+       arg = arg->next;
+       field_flags = (u8) arg->value.integer;
+
+       /* Each remaining arg is a Named Field */
+
+       arg = arg->next;
+       while (arg) {
+               switch (arg->opcode) {
+               case AML_RESERVEDFIELD_OP:
+
+                       field_bit_position += arg->value.size;
+                       break;
+
+
+               case AML_ACCESSFIELD_OP:
+
+                       /*
+                        * Get a new Access_type and Access_attribute for all
+                        * entries (until end or another Access_as keyword)
+                        */
+
+                       access_attribute = (u8) arg->value.integer;
+                       field_flags     = (u8)
+                                         ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
+                                         ((u8) (arg->value.integer >> 8)));
+                       break;
+
+
+               case AML_NAMEDFIELD_OP:
+
+                       status = acpi_ns_lookup (walk_state->scope_info,
+                                         (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name,
+                                         INTERNAL_TYPE_DEF_FIELD,
+                                         IMODE_LOAD_PASS1,
+                                         NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                                         NULL, &node);
+
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /*
+                        * Initialize an object for the new Node that is on
+                        * the object stack
+                        */
+
+                       status = acpi_aml_prep_def_field_value (node, region_node, field_flags,
+                                         access_attribute, field_bit_position, arg->value.size);
+
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /* Keep track of bit position for *next* field */
+
+                       field_bit_position += arg->value.size;
+                       break;
+               }
+
+               arg = arg->next;
+       }
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_bank_field
+ *
+ * PARAMETERS:  Op              - Op containing the Field definition and args
+ *              Region_node - Object for the containing Operation Region
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a new bank field in the specified operation region
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_bank_field (
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_NAMESPACE_NODE     *region_node,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status = AE_AML_ERROR;
+       ACPI_PARSE_OBJECT       *arg;
+       ACPI_NAMESPACE_NODE     *register_node;
+       ACPI_NAMESPACE_NODE     *node;
+       u32                     bank_value;
+       u8                      field_flags;
+       u8                      access_attribute = 0;
+       u32                     field_bit_position = 0;
+
+
+       /* First arg is the name of the parent Op_region */
+
+       arg = op->value.arg;
+       if (!region_node) {
+               status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
+                                ACPI_TYPE_REGION, IMODE_EXECUTE,
+                                NS_SEARCH_PARENT, walk_state,
+                                &region_node);
+
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+       }
+
+       /* Second arg is the Bank Register */
+
+       arg = arg->next;
+
+       status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
+                        INTERNAL_TYPE_BANK_FIELD_DEFN,
+                        IMODE_LOAD_PASS1,
+                        NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                        NULL, &register_node);
+
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Third arg is the Bank_value */
+
+       arg = arg->next;
+       bank_value = arg->value.integer;
+
+
+       /* Next arg is the field flags */
+
+       arg = arg->next;
+       field_flags = (u8) arg->value.integer;
+
+       /* Each remaining arg is a Named Field */
+
+       arg = arg->next;
+       while (arg) {
+               switch (arg->opcode) {
+               case AML_RESERVEDFIELD_OP:
+
+                       field_bit_position += arg->value.size;
+                       break;
+
+
+               case AML_ACCESSFIELD_OP:
+
+                       /*
+                        * Get a new Access_type and Access_attribute for
+                        * all entries (until end or another Access_as keyword)
+                        */
+
+                       access_attribute = (u8) arg->value.integer;
+                       field_flags     = (u8)
+                                         ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
+                                         ((u8) (arg->value.integer >> 8)));
+                       break;
+
+
+               case AML_NAMEDFIELD_OP:
+
+                       status = acpi_ns_lookup (walk_state->scope_info,
+                                         (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name,
+                                         INTERNAL_TYPE_DEF_FIELD,
+                                         IMODE_LOAD_PASS1,
+                                         NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                                         NULL, &node);
+
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /*
+                        * Initialize an object for the new Node that is on
+                        * the object stack
+                        */
+
+                       status = acpi_aml_prep_bank_field_value (node, region_node, register_node,
+                                         bank_value, field_flags, access_attribute,
+                                         field_bit_position, arg->value.size);
+
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /* Keep track of bit position for the *next* field */
+
+                       field_bit_position += arg->value.size;
+                       break;
+
+               }
+
+               arg = arg->next;
+       }
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_index_field
+ *
+ * PARAMETERS:  Op              - Op containing the Field definition and args
+ *              Region_node - Object for the containing Operation Region
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a new index field in the specified operation region
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_index_field (
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_HANDLE             region_node,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       ACPI_PARSE_OBJECT       *arg;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_NAMESPACE_NODE     *index_register_node;
+       ACPI_NAMESPACE_NODE     *data_register_node;
+       u8                      field_flags;
+       u8                      access_attribute = 0;
+       u32                     field_bit_position = 0;
+
+
+       arg = op->value.arg;
+
+       /* First arg is the name of the Index register */
+
+       status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
+                        ACPI_TYPE_ANY, IMODE_LOAD_PASS1,
+                        NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                        NULL, &index_register_node);
+
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Second arg is the data register */
+
+       arg = arg->next;
+
+       status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
+                        INTERNAL_TYPE_INDEX_FIELD_DEFN,
+                        IMODE_LOAD_PASS1,
+                        NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                        NULL, &data_register_node);
+
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+
+       /* Next arg is the field flags */
+
+       arg = arg->next;
+       field_flags = (u8) arg->value.integer;
+
+
+       /* Each remaining arg is a Named Field */
+
+       arg = arg->next;
+       while (arg) {
+               switch (arg->opcode) {
+               case AML_RESERVEDFIELD_OP:
+
+                       field_bit_position += arg->value.size;
+                       break;
+
+
+               case AML_ACCESSFIELD_OP:
+
+                       /*
+                        * Get a new Access_type and Access_attribute for all
+                        * entries (until end or another Access_as keyword)
+                        */
+
+                       access_attribute = (u8) arg->value.integer;
+                       field_flags     = (u8)
+                                          ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
+                                          ((u8) (arg->value.integer >> 8)));
+                       break;
+
+
+               case AML_NAMEDFIELD_OP:
+
+                       status = acpi_ns_lookup (walk_state->scope_info,
+                                        (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name,
+                                        INTERNAL_TYPE_INDEX_FIELD,
+                                        IMODE_LOAD_PASS1,
+                                        NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                                        NULL, &node);
+
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /*
+                        * Initialize an object for the new Node that is on
+                        * the object stack
+                        */
+
+                       status = acpi_aml_prep_index_field_value (node, index_register_node, data_register_node,
+                                         field_flags, access_attribute,
+                                         field_bit_position, arg->value.size);
+
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /* Keep track of bit position for the *next* field */
+
+                       field_bit_position += arg->value.size;
+                       break;
+
+
+               default:
+
+                       status = AE_AML_ERROR;
+                       break;
+               }
+
+               arg = arg->next;
+       }
+
+       return (status);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dsmethod.c b/reactos/drivers/bus/acpi/dispatcher/dsmethod.c
new file mode 100644 (file)
index 0000000..c400a9a
--- /dev/null
@@ -0,0 +1,497 @@
+/******************************************************************************
+ *
+ * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
+ *              $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"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "actables.h"
+#include "acdebug.h"
+
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dsmethod")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_parse_method
+ *
+ * PARAMETERS:  Obj_handle      - Node of the method
+ *              Level           - Current nesting level
+ *              Context         - Points to a method counter
+ *              Return_value    - Not used
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Call the parser and parse the AML that is
+ *              associated with the method.
+ *
+ * MUTEX:       Assumes parser is locked
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_parse_method (
+       ACPI_HANDLE             obj_handle)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_PARSE_OBJECT       *op;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_OWNER_ID           owner_id;
+
+
+       /* Parameter Validation */
+
+       if (!obj_handle) {
+               return (AE_NULL_ENTRY);
+       }
+
+
+       /* Extract the method object from the method Node */
+
+       node = (ACPI_NAMESPACE_NODE *) obj_handle;
+       obj_desc = node->object;
+       if (!obj_desc) {
+               return (AE_NULL_OBJECT);
+       }
+
+        /* Create a mutex for the method if there is a concurrency limit */
+
+       if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) &&
+               (!obj_desc->method.semaphore)) {
+               status = acpi_os_create_semaphore (obj_desc->method.concurrency,
+                                  obj_desc->method.concurrency,
+                                  &obj_desc->method.semaphore);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+       }
+
+       /*
+        * Allocate a new parser op to be the root of the parsed
+        * method tree
+        */
+       op = acpi_ps_alloc_op (AML_METHOD_OP);
+       if (!op) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* Init new op with the method name and pointer back to the Node */
+
+       acpi_ps_set_name (op, node->name);
+       op->node = node;
+
+
+       /*
+        * Parse the method, first pass
+        *
+        * The first pass load is
+        * where newly declared named objects are
+        * added into the namespace.  Actual evaluation of
+        * the named objects (what would be called a "second
+        * pass") happens during the actual execution of the
+        * method so that operands to the named objects can
+        * take on dynamic run-time values.
+        */
+       status = acpi_ps_parse_aml (op, obj_desc->method.pcode,
+                          obj_desc->method.pcode_length,
+                          ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
+                          node, NULL, NULL,
+                          acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
+
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Get a new Owner_id for objects created by this method */
+
+       owner_id = acpi_cm_allocate_owner_id (OWNER_TYPE_METHOD);
+       obj_desc->method.owning_id = owner_id;
+
+       /* Install the parsed tree in the method object */
+       /* TBD: [Restructure] Obsolete field? */
+
+       acpi_ps_delete_parse_tree (op);
+
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_begin_method_execution
+ *
+ * PARAMETERS:  Method_node         - Node of the method
+ *              Obj_desc            - The method object
+ *              Calling_method_node - Caller of this method (if non-null)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
+ *              increments the thread count, and waits at the method semaphore
+ *              for clearance to execute.
+ *
+ * MUTEX:       Locks/unlocks parser.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_begin_method_execution (
+       ACPI_NAMESPACE_NODE     *method_node,
+       ACPI_OPERAND_OBJECT     *obj_desc,
+       ACPI_NAMESPACE_NODE     *calling_method_node)
+{
+       ACPI_STATUS             status = AE_OK;
+
+
+       if (!method_node) {
+               return (AE_NULL_ENTRY);
+       }
+
+
+       /*
+        * If there is a concurrency limit on this method, we need to
+        * obtain a unit from the method semaphore.
+        */
+       if (obj_desc->method.semaphore) {
+               /*
+                * Allow recursive method calls, up to the reentrancy/concurrency
+                * limit imposed by the SERIALIZED rule and the Sync_level method
+                * parameter.
+                *
+                * The point of this code is to avoid permanently blocking a
+                * thread that is making recursive method calls.
+                */
+               if (method_node == calling_method_node) {
+                       if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
+                               return (AE_AML_METHOD_LIMIT);
+                       }
+               }
+
+               /*
+                * Get a unit from the method semaphore. This releases the
+                * interpreter if we block
+                */
+               status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore,
+                                WAIT_FOREVER);
+       }
+
+
+       /*
+        * Increment the method parse tree thread count since it has been
+        * reentered one more time (even if it is the same thread)
+        */
+       obj_desc->method.thread_count++;
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_call_control_method
+ *
+ * PARAMETERS:  Walk_state          - Current state of the walk
+ *              Op                  - Current Op to be walked
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Transfer execution to a called control method
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_call_control_method (
+       ACPI_WALK_LIST          *walk_list,
+       ACPI_WALK_STATE         *this_walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status;
+       ACPI_NAMESPACE_NODE     *method_node;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_WALK_STATE         *next_walk_state;
+       ACPI_PARSE_STATE        *parser_state;
+       u32                     i;
+
+
+       /*
+        * Get the namespace entry for the control method we are about to call
+        */
+       method_node = this_walk_state->method_call_node;
+       if (!method_node) {
+               return (AE_NULL_ENTRY);
+       }
+
+       obj_desc = acpi_ns_get_attached_object (method_node);
+       if (!obj_desc) {
+               return (AE_NULL_OBJECT);
+       }
+
+
+       /* Init for new method, wait on concurrency semaphore */
+
+       status = acpi_ds_begin_method_execution (method_node, obj_desc,
+                         this_walk_state->method_node);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Create and initialize a new parser state */
+
+       parser_state = acpi_ps_create_state (obj_desc->method.pcode,
+                          obj_desc->method.pcode_length);
+       if (!parser_state) {
+               return (AE_NO_MEMORY);
+       }
+
+       acpi_ps_init_scope (parser_state, NULL);
+       parser_state->start_node = method_node;
+
+
+       /* Create a new state for the preempting walk */
+
+       next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
+                         NULL, obj_desc, walk_list);
+       if (!next_walk_state) {
+               /* TBD: delete parser state */
+
+               return (AE_NO_MEMORY);
+       }
+
+       next_walk_state->walk_type          = WALK_METHOD;
+       next_walk_state->method_node        = method_node;
+       next_walk_state->parser_state       = parser_state;
+       next_walk_state->parse_flags        = this_walk_state->parse_flags;
+       next_walk_state->descending_callback = this_walk_state->descending_callback;
+       next_walk_state->ascending_callback = this_walk_state->ascending_callback;
+
+       /* The Next_op of the Next_walk will be the beginning of the method */
+       /* TBD: [Restructure] -- obsolete? */
+
+       next_walk_state->next_op = NULL;
+
+       /* Open a new scope */
+
+       status = acpi_ds_scope_stack_push (method_node,
+                          ACPI_TYPE_METHOD, next_walk_state);
+       if (ACPI_FAILURE (status)) {
+               goto cleanup;
+       }
+
+
+       /*
+        * Initialize the arguments for the method.  The resolved
+        * arguments were put on the previous walk state's operand
+        * stack.  Operands on the previous walk state stack always
+        * start at index 0.
+        */
+       status = acpi_ds_method_data_init_args (&this_walk_state->operands[0],
+                        this_walk_state->num_operands,
+                        next_walk_state);
+       if (ACPI_FAILURE (status)) {
+               goto cleanup;
+       }
+
+
+       /* Create and init a Root Node */
+
+       op = acpi_ps_alloc_op (AML_SCOPE_OP);
+       if (!op) {
+               return (AE_NO_MEMORY);
+       }
+
+       status = acpi_ps_parse_aml (op, obj_desc->method.pcode,
+                         obj_desc->method.pcode_length,
+                         ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
+                         method_node, NULL, NULL,
+                         acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
+       acpi_ps_delete_parse_tree (op);
+
+
+       /*
+        * Delete the operands on the previous walkstate operand stack
+        * (they were copied to new objects)
+        */
+       for (i = 0; i < obj_desc->method.param_count; i++) {
+               acpi_cm_remove_reference (this_walk_state->operands [i]);
+               this_walk_state->operands [i] = NULL;
+       }
+
+       /* Clear the operand stack */
+
+       this_walk_state->num_operands = 0;
+
+
+       return (AE_OK);
+
+
+       /* On error, we must delete the new walk state */
+
+cleanup:
+       acpi_ds_terminate_control_method (next_walk_state);
+       acpi_ds_delete_walk_state (next_walk_state);
+       return (status);
+
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_restart_control_method
+ *
+ * PARAMETERS:  Walk_state          - State of the method when it was preempted
+ *              Op                  - Pointer to new current op
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Restart a method that was preempted
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_restart_control_method (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_OPERAND_OBJECT     *return_desc)
+{
+       ACPI_STATUS             status;
+
+
+       if (return_desc) {
+               if (walk_state->return_used) {
+                       /*
+                        * Get the return value (if any) from the previous method.
+                        * NULL if no return value
+                        */
+                       status = acpi_ds_result_push (return_desc, walk_state);
+                       if (ACPI_FAILURE (status)) {
+                               acpi_cm_remove_reference (return_desc);
+                               return (status);
+                       }
+               }
+
+               else {
+                       /*
+                        * Delete the return value if it will not be used by the
+                        * calling method
+                        */
+                       acpi_cm_remove_reference (return_desc);
+               }
+
+       }
+
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_terminate_control_method
+ *
+ * PARAMETERS:  Walk_state          - State of the method
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Terminate a control method.  Delete everything that the method
+ *              created, delete all locals and arguments, and delete the parse
+ *              tree if requested.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_terminate_control_method (
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_NAMESPACE_NODE     *method_node;
+
+
+       /* The method object should be stored in the walk state */
+
+       obj_desc = walk_state->method_desc;
+       if (!obj_desc) {
+               return (AE_OK);
+       }
+
+       /* Delete all arguments and locals */
+
+       acpi_ds_method_data_delete_all (walk_state);
+
+       /*
+        * Lock the parser while we terminate this method.
+        * If this is the last thread executing the method,
+        * we have additional cleanup to perform
+        */
+       acpi_cm_acquire_mutex (ACPI_MTX_PARSER);
+
+
+       /* Signal completion of the execution of this method if necessary */
+
+       if (walk_state->method_desc->method.semaphore) {
+               status = acpi_os_signal_semaphore (
+                                walk_state->method_desc->method.semaphore, 1);
+       }
+
+       /* Decrement the thread count on the method parse tree */
+
+       walk_state->method_desc->method.thread_count--;
+       if (!walk_state->method_desc->method.thread_count) {
+               /*
+                * There are no more threads executing this method.  Perform
+                * additional cleanup.
+                *
+                * The method Node is stored in the walk state
+                */
+               method_node = walk_state->method_node;
+
+               /*
+                * Delete any namespace entries created immediately underneath
+                * the method
+                */
+               acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+               if (method_node->child) {
+                       acpi_ns_delete_namespace_subtree (method_node);
+               }
+
+               /*
+                * Delete any namespace entries created anywhere else within
+                * the namespace
+                */
+               acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
+               acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+       }
+
+       acpi_cm_release_mutex (ACPI_MTX_PARSER);
+       return (AE_OK);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dsmthdat.c b/reactos/drivers/bus/acpi/dispatcher/dsmthdat.c
new file mode 100644 (file)
index 0000000..69a4a92
--- /dev/null
@@ -0,0 +1,693 @@
+/*******************************************************************************
+ *
+ * Module Name: dsmthdat - control method arguments and local variables
+ *              $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"
+#include "acparser.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dsmthdat")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_init
+ *
+ * PARAMETERS:  Walk_state          - Current walk state object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize the data structures that hold the method's arguments
+ *              and locals.  The data struct is an array of NTEs for each.
+ *              This allows Ref_of and De_ref_of to work properly for these
+ *              special data types.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_init (
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     i;
+
+
+       /*
+        * Walk_state fields are initialized to zero by the
+        * Acpi_cm_callocate().
+        *
+        * An Node is assigned to each argument and local so
+        * that Ref_of() can return a pointer to the Node.
+        */
+
+       /* Init the method arguments */
+
+       for (i = 0; i < MTH_NUM_ARGS; i++) {
+               MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name,
+                                NAMEOF_ARG_NTE);
+               walk_state->arguments[i].name      |= (i << 24);
+               walk_state->arguments[i].data_type  = ACPI_DESC_TYPE_NAMED;
+               walk_state->arguments[i].type       = ACPI_TYPE_ANY;
+               walk_state->arguments[i].flags      = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
+       }
+
+       /* Init the method locals */
+
+       for (i = 0; i < MTH_NUM_LOCALS; i++) {
+               MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name,
+                                NAMEOF_LOCAL_NTE);
+
+               walk_state->local_variables[i].name  |= (i << 24);
+               walk_state->local_variables[i].data_type = ACPI_DESC_TYPE_NAMED;
+               walk_state->local_variables[i].type   = ACPI_TYPE_ANY;
+               walk_state->local_variables[i].flags  = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_delete_all
+ *
+ * PARAMETERS:  Walk_state          - Current walk state object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Delete method locals and arguments.  Arguments are only
+ *              deleted if this method was called from another method.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_delete_all (
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     index;
+       ACPI_OPERAND_OBJECT     *object;
+
+
+       /* Delete the locals */
+
+       for (index = 0; index < MTH_NUM_LOCALS; index++) {
+               object = walk_state->local_variables[index].object;
+               if (object) {
+                       /* Remove first */
+
+                       walk_state->local_variables[index].object = NULL;
+
+                       /* Was given a ref when stored */
+
+                       acpi_cm_remove_reference (object);
+          }
+       }
+
+
+       /* Delete the arguments */
+
+       for (index = 0; index < MTH_NUM_ARGS; index++) {
+               object = walk_state->arguments[index].object;
+               if (object) {
+                       /* Remove first */
+
+                       walk_state->arguments[index].object = NULL;
+
+                        /* Was given a ref when stored */
+
+                       acpi_cm_remove_reference (object);
+               }
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_init_args
+ *
+ * PARAMETERS:  *Params         - Pointer to a parameter list for the method
+ *              Max_param_count - The arg count for this method
+ *              Walk_state      - Current walk state object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize arguments for a method
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_init_args (
+       ACPI_OPERAND_OBJECT     **params,
+       u32                     max_param_count,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       u32                     mindex;
+       u32                     pindex;
+
+
+       if (!params) {
+               return (AE_OK);
+       }
+
+       /* Copy passed parameters into the new method stack frame  */
+
+       for (pindex = mindex = 0;
+               (mindex < MTH_NUM_ARGS) && (pindex < max_param_count);
+               mindex++) {
+               if (params[pindex]) {
+                       /*
+                        * A valid parameter.
+                        * Set the current method argument to the
+                        * Params[Pindex++] argument object descriptor
+                        */
+                       status = acpi_ds_store_object_to_local (AML_ARG_OP, mindex,
+                                        params[pindex], walk_state);
+                       if (ACPI_FAILURE (status)) {
+                               break;
+                       }
+
+                       pindex++;
+               }
+
+               else {
+                       break;
+               }
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_get_entry
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument to get
+ *              Entry               - Pointer to where a pointer to the stack
+ *                                    entry is returned.
+ *              Walk_state          - Current walk state object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get the address of the object entry given by Opcode:Index
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_get_entry (
+       u16                     opcode,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_OPERAND_OBJECT     ***entry)
+{
+
+
+       /*
+        * Get the requested object.
+        * The stack "Opcode" is either a Local_variable or an Argument
+        */
+
+       switch (opcode) {
+
+       case AML_LOCAL_OP:
+
+               if (index > MTH_MAX_LOCAL) {
+                       return (AE_BAD_PARAMETER);
+               }
+
+               *entry = (ACPI_OPERAND_OBJECT  **)
+                                &walk_state->local_variables[index].object;
+               break;
+
+
+       case AML_ARG_OP:
+
+               if (index > MTH_MAX_ARG) {
+                       return (AE_BAD_PARAMETER);
+               }
+
+               *entry = (ACPI_OPERAND_OBJECT  **)
+                                &walk_state->arguments[index].object;
+               break;
+
+
+       default:
+               return (AE_BAD_PARAMETER);
+       }
+
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_set_entry
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument to get
+ *              Object              - Object to be inserted into the stack entry
+ *              Walk_state          - Current walk state object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_set_entry (
+       u16                     opcode,
+       u32                     index,
+       ACPI_OPERAND_OBJECT     *object,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     **entry;
+
+
+       /* Get a pointer to the stack entry to set */
+
+       status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Increment ref count so object can't be deleted while installed */
+
+       acpi_cm_add_reference (object);
+
+       /* Install the object into the stack entry */
+
+       *entry = object;
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_get_type
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument whose type
+ *                                      to get
+ *              Walk_state          - Current walk state object
+ *
+ * RETURN:      Data type of selected Arg or Local
+ *              Used only in Exec_monadic2()/Type_op.
+ *
+ ******************************************************************************/
+
+OBJECT_TYPE_INTERNAL
+acpi_ds_method_data_get_type (
+       u16                     opcode,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     **entry;
+       ACPI_OPERAND_OBJECT     *object;
+
+
+       /* Get a pointer to the requested stack entry */
+
+       status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
+       if (ACPI_FAILURE (status)) {
+               return ((ACPI_TYPE_NOT_FOUND));
+       }
+
+       /* Get the object from the method stack */
+
+       object = *entry;
+
+       /* Get the object type */
+
+       if (!object) {
+               /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */
+               return (ACPI_TYPE_ANY);
+       }
+
+       return (object->common.type);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_get_node
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument whose type
+ *                                      to get
+ *              Walk_state          - Current walk state object
+ *
+ * RETURN:      Get the Node associated with a local or arg.
+ *
+ ******************************************************************************/
+
+ACPI_NAMESPACE_NODE *
+acpi_ds_method_data_get_node (
+       u16                     opcode,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_NAMESPACE_NODE     *node = NULL;
+
+
+       switch (opcode) {
+
+       case AML_LOCAL_OP:
+
+               if (index > MTH_MAX_LOCAL) {
+                       return (node);
+               }
+
+               node =  &walk_state->local_variables[index];
+               break;
+
+
+       case AML_ARG_OP:
+
+               if (index > MTH_MAX_ARG) {
+                       return (node);
+               }
+
+               node = &walk_state->arguments[index];
+               break;
+
+
+       default:
+               break;
+       }
+
+
+       return (node);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_get_value
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument to get
+ *              Walk_state          - Current walk state object
+ *              *Dest_desc          - Ptr to Descriptor into which selected Arg
+ *                                    or Local value should be copied
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame
+ *              at the current top of the method stack.
+ *              Used only in Acpi_aml_resolve_to_value().
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_get_value (
+       u16                     opcode,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_OPERAND_OBJECT     **dest_desc)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     **entry;
+       ACPI_OPERAND_OBJECT     *object;
+
+
+       /* Validate the object descriptor */
+
+       if (!dest_desc) {
+               return (AE_BAD_PARAMETER);
+       }
+
+
+       /* Get a pointer to the requested method stack entry */
+
+       status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Get the object from the method stack */
+
+       object = *entry;
+
+
+       /* Examine the returned object, it must be valid. */
+
+       if (!object) {
+               /*
+                * Index points to uninitialized object stack value.
+                * This means that either 1) The expected argument was
+                * not passed to the method, or 2) A local variable
+                * was referenced by the method (via the ASL)
+                * before it was initialized.  Either case is an error.
+                */
+
+               switch (opcode) {
+               case AML_ARG_OP:
+
+                       return (AE_AML_UNINITIALIZED_ARG);
+                       break;
+
+               case AML_LOCAL_OP:
+
+                       return (AE_AML_UNINITIALIZED_LOCAL);
+                       break;
+               }
+       }
+
+
+       /*
+        * Index points to initialized and valid object stack value.
+        * Return an additional reference to the object
+        */
+
+       *dest_desc = object;
+       acpi_cm_add_reference (object);
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_method_data_delete_value
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument to delete
+ *              Walk_state          - Current walk state object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Delete the entry at Opcode:Index on the method stack.  Inserts
+ *              a null into the stack slot after the object is deleted.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_method_data_delete_value (
+       u16                     opcode,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     **entry;
+       ACPI_OPERAND_OBJECT     *object;
+
+
+       /* Get a pointer to the requested entry */
+
+       status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Get the current entry in this slot k */
+
+       object = *entry;
+
+       /*
+        * Undefine the Arg or Local by setting its descriptor
+        * pointer to NULL. Locals/Args can contain both
+        * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
+        */
+       *entry = NULL;
+
+
+       if ((object) &&
+               (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) {
+               /*
+                * There is a valid object in this slot
+                * Decrement the reference count by one to balance the
+                * increment when the object was stored in the slot.
+                */
+               acpi_cm_remove_reference (object);
+       }
+
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_store_object_to_local
+ *
+ * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ *              Index               - Which local_var or argument to set
+ *              Src_desc            - Value to be stored
+ *              Walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Store a value in an Arg or Local.  The Src_desc is installed
+ *              as the new value for the Arg or Local and the reference count
+ *              for Src_desc is incremented.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_store_object_to_local (
+       u16                     opcode,
+       u32                     index,
+       ACPI_OPERAND_OBJECT     *src_desc,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     **entry;
+
+
+       /* Parameter validation */
+
+       if (!src_desc) {
+               return (AE_BAD_PARAMETER);
+       }
+
+
+       /* Get a pointer to the requested method stack entry */
+
+       status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
+       if (ACPI_FAILURE (status)) {
+               goto cleanup;
+       }
+
+       if (*entry == src_desc) {
+               goto cleanup;
+       }
+
+
+       /*
+        * If there is an object already in this slot, we either
+        * have to delete it, or if this is an argument and there
+        * is an object reference stored there, we have to do
+        * an indirect store!
+        */
+
+       if (*entry) {
+               /*
+                * Check for an indirect store if an argument
+                * contains an object reference (stored as an Node).
+                * We don't allow this automatic dereferencing for
+                * locals, since a store to a local should overwrite
+                * anything there, including an object reference.
+                *
+                * If both Arg0 and Local0 contain Ref_of (Local4):
+                *
+                * Store (1, Arg0)             - Causes indirect store to local4
+                * Store (1, Local0)           - Stores 1 in local0, overwriting
+                *                                  the reference to local4
+                * Store (1, De_refof (Local0)) - Causes indirect store to local4
+                *
+                * Weird, but true.
+                */
+
+               if ((opcode == AML_ARG_OP) &&
+                       (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) {
+                       /* Detach an existing object from the Node */
+
+                       acpi_ns_detach_object ((ACPI_NAMESPACE_NODE *) *entry);
+
+                       /*
+                        * Store this object into the Node
+                        * (do the indirect store)
+                        */
+                       status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc,
+                                          src_desc->common.type);
+                       return (status);
+               }
+
+
+#ifdef ACPI_ENABLE_IMPLICIT_CONVERSION
+               /*
+                * Perform "Implicit conversion" of the new object to the type of the
+                * existing object
+                */
+               status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+#endif
+
+               /*
+                * Delete the existing object
+                * before storing the new one
+                */
+               acpi_ds_method_data_delete_value (opcode, index, walk_state);
+       }
+
+
+       /*
+        * Install the Obj_stack descriptor (*Src_desc) into
+        * the descriptor for the Arg or Local.
+        * Install the new object in the stack entry
+        * (increments the object reference count by one)
+        */
+       status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state);
+       if (ACPI_FAILURE (status)) {
+               goto cleanup;
+       }
+
+       /* Normal exit */
+
+       return (AE_OK);
+
+
+       /* Error exit */
+
+cleanup:
+
+       return (status);
+}
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dsobject.c b/reactos/drivers/bus/acpi/dispatcher/dsobject.c
new file mode 100644 (file)
index 0000000..7bedc0f
--- /dev/null
@@ -0,0 +1,641 @@
+/******************************************************************************
+ *
+ * Module Name: dsobject - Dispatcher object management routines
+ *              $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"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dsobject")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_init_one_object
+ *
+ * PARAMETERS:  Obj_handle      - Node
+ *              Level           - Current nesting level
+ *              Context         - Points to a init info struct
+ *              Return_value    - Not used
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
+ *              within the  namespace.
+ *
+ *              Currently, the only objects that require initialization are:
+ *              1) Methods
+ *              2) Op Regions
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_init_one_object (
+       ACPI_HANDLE             obj_handle,
+       u32                     level,
+       void                    *context,
+       void                    **return_value)
+{
+       OBJECT_TYPE_INTERNAL    type;
+       ACPI_STATUS             status;
+       ACPI_INIT_WALK_INFO     *info = (ACPI_INIT_WALK_INFO *) context;
+       u8                      table_revision;
+
+
+       info->object_count++;
+       table_revision = info->table_desc->pointer->revision;
+
+       /*
+        * We are only interested in objects owned by the table that
+        * was just loaded
+        */
+
+       if (((ACPI_NAMESPACE_NODE *) obj_handle)->owner_id !=
+                       info->table_desc->table_id) {
+               return (AE_OK);
+       }
+
+
+       /* And even then, we are only interested in a few object types */
+
+       type = acpi_ns_get_type (obj_handle);
+
+       switch (type) {
+
+       case ACPI_TYPE_REGION:
+
+               acpi_ds_initialize_region (obj_handle);
+
+               info->op_region_count++;
+               break;
+
+
+       case ACPI_TYPE_METHOD:
+
+               info->method_count++;
+
+
+               /*
+                * Set the execution data width (32 or 64) based upon the
+                * revision number of the parent ACPI table.
+                */
+
+               if (table_revision == 1) {
+                       ((ACPI_NAMESPACE_NODE *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
+               }
+
+               /*
+                * Always parse methods to detect errors, we may delete
+                * the parse tree below
+                */
+
+               status = acpi_ds_parse_method (obj_handle);
+
+               /* TBD: [Errors] what do we do with an error? */
+
+               if (ACPI_FAILURE (status)) {
+                       break;
+               }
+
+               /*
+                * Delete the parse tree.  We simple re-parse the method
+                * for every execution since there isn't much overhead
+                */
+               acpi_ns_delete_namespace_subtree (obj_handle);
+               break;
+
+       default:
+               break;
+       }
+
+       /*
+        * We ignore errors from above, and always return OK, since
+        * we don't want to abort the walk on a single error.
+        */
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_initialize_objects
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk the entire namespace and perform any necessary
+ *              initialization on the objects found therein
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_initialize_objects (
+       ACPI_TABLE_DESC         *table_desc,
+       ACPI_NAMESPACE_NODE     *start_node)
+{
+       ACPI_STATUS             status;
+       ACPI_INIT_WALK_INFO     info;
+
+
+       info.method_count   = 0;
+       info.op_region_count = 0;
+       info.object_count   = 0;
+       info.table_desc     = table_desc;
+
+
+       /* Walk entire namespace from the supplied root */
+
+       status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node,
+                         ACPI_UINT32_MAX, acpi_ds_init_one_object,
+                         &info, NULL);
+
+       return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_init_object_from_op
+ *
+ * PARAMETERS:  Op              - Parser op used to init the internal object
+ *              Opcode          - AML opcode associated with the object
+ *              Obj_desc        - Namespace object to be initialized
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize a namespace object from a parser Op and its
+ *              associated arguments.  The namespace object is a more compact
+ *              representation of the Op and its arguments.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_init_object_from_op (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op,
+       u16                     opcode,
+       ACPI_OPERAND_OBJECT     **obj_desc)
+{
+       ACPI_STATUS             status;
+       ACPI_PARSE_OBJECT       *arg;
+       ACPI_PARSE2_OBJECT      *byte_list;
+       ACPI_OPERAND_OBJECT     *arg_desc;
+       ACPI_OPCODE_INFO        *op_info;
+
+
+       op_info = acpi_ps_get_opcode_info (opcode);
+       if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
+               /* Unknown opcode */
+
+               return (AE_TYPE);
+       }
+
+
+       /* Get and prepare the first argument */
+
+       switch ((*obj_desc)->common.type) {
+       case ACPI_TYPE_BUFFER:
+
+               /* First arg is a number */
+
+               acpi_ds_create_operand (walk_state, op->value.arg, 0);
+               arg_desc = walk_state->operands [walk_state->num_operands - 1];
+               acpi_ds_obj_stack_pop (1, walk_state);
+
+               /* Resolve the object (could be an arg or local) */
+
+               status = acpi_aml_resolve_to_value (&arg_desc, walk_state);
+               if (ACPI_FAILURE (status)) {
+                       acpi_cm_remove_reference (arg_desc);
+                       return (status);
+               }
+
+               /* We are expecting a number */
+
+               if (arg_desc->common.type != ACPI_TYPE_INTEGER) {
+                       acpi_cm_remove_reference (arg_desc);
+                       return (AE_TYPE);
+               }
+
+               /* Get the value, delete the internal object */
+
+               (*obj_desc)->buffer.length = (u32) arg_desc->integer.value;
+               acpi_cm_remove_reference (arg_desc);
+
+               /* Allocate the buffer */
+
+               if ((*obj_desc)->buffer.length == 0) {
+                       (*obj_desc)->buffer.pointer = NULL;
+                       REPORT_WARNING (("Buffer created with zero length in AML\n"));
+                       break;
+               }
+
+               else {
+                       (*obj_desc)->buffer.pointer =
+                                         acpi_cm_callocate ((*obj_desc)->buffer.length);
+
+                       if (!(*obj_desc)->buffer.pointer) {
+                               return (AE_NO_MEMORY);
+                       }
+               }
+
+               /*
+                * Second arg is the buffer data (optional)
+                * Byte_list can be either individual bytes or a
+                * string initializer!
+                */
+
+               /* skip first arg */
+               arg = op->value.arg;
+               byte_list = (ACPI_PARSE2_OBJECT *) arg->next;
+               if (byte_list) {
+                       if (byte_list->opcode != AML_BYTELIST_OP) {
+                               return (AE_TYPE);
+                       }
+
+                       MEMCPY ((*obj_desc)->buffer.pointer, byte_list->data,
+                                       (*obj_desc)->buffer.length);
+               }
+
+               break;
+
+
+       case ACPI_TYPE_PACKAGE:
+
+               /*
+                * When called, an internal package object has already
+                *  been built and is pointed to by *Obj_desc.
+                *  Acpi_ds_build_internal_object build another internal
+                *  package object, so remove reference to the original
+                *  so that it is deleted.  Error checking is done
+                *  within the remove reference function.
+                */
+               acpi_cm_remove_reference(*obj_desc);
+
+               status = acpi_ds_build_internal_object (walk_state, op, obj_desc);
+               break;
+
+       case ACPI_TYPE_INTEGER:
+               (*obj_desc)->integer.value = op->value.integer;
+               break;
+
+
+       case ACPI_TYPE_STRING:
+               (*obj_desc)->string.pointer = op->value.string;
+               (*obj_desc)->string.length = STRLEN (op->value.string);
+               break;
+
+
+       case ACPI_TYPE_METHOD:
+               break;
+
+
+       case INTERNAL_TYPE_REFERENCE:
+
+               switch (ACPI_GET_OP_CLASS (op_info)) {
+               case OPTYPE_LOCAL_VARIABLE:
+
+                       /* Split the opcode into a base opcode + offset */
+
+                       (*obj_desc)->reference.opcode = AML_LOCAL_OP;
+                       (*obj_desc)->reference.offset = opcode - AML_LOCAL_OP;
+                       break;
+
+               case OPTYPE_METHOD_ARGUMENT:
+
+                       /* Split the opcode into a base opcode + offset */
+
+                       (*obj_desc)->reference.opcode = AML_ARG_OP;
+                       (*obj_desc)->reference.offset = opcode - AML_ARG_OP;
+                       break;
+
+               default: /* Constants, Literals, etc.. */
+
+                       if (op->opcode == AML_NAMEPATH_OP) {
+                               /* Node was saved in Op */
+
+                               (*obj_desc)->reference.node = op->node;
+                       }
+
+                       (*obj_desc)->reference.opcode = opcode;
+                       break;
+               }
+
+               break;
+
+
+       default:
+
+               break;
+       }
+
+       return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_build_internal_simple_obj
+ *
+ * PARAMETERS:  Op              - Parser object to be translated
+ *              Obj_desc_ptr    - Where the ACPI internal object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
+ *              Simple objects are any objects other than a package object!
+ *
+ ****************************************************************************/
+
+static ACPI_STATUS
+acpi_ds_build_internal_simple_obj (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_OPERAND_OBJECT     **obj_desc_ptr)
+{
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       OBJECT_TYPE_INTERNAL    type;
+       ACPI_STATUS             status;
+       u32                     length;
+       char                    *name;
+
+
+       if (op->opcode == AML_NAMEPATH_OP) {
+               /*
+                * This is an object reference.  If The name was
+                * previously looked up in the NS, it is stored in this op.
+                * Otherwise, go ahead and look it up now
+                */
+
+               if (!op->node) {
+                       status = acpi_ns_lookup (walk_state->scope_info,
+                                         op->value.string, ACPI_TYPE_ANY,
+                                         IMODE_EXECUTE,
+                                         NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
+                                         NULL,
+                                         (ACPI_NAMESPACE_NODE **)&(op->node));
+
+                       if (ACPI_FAILURE (status)) {
+                               if (status == AE_NOT_FOUND) {
+                                       name = NULL;
+                                       acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name);
+
+                                       if (name) {
+                                               REPORT_WARNING (("Reference %s at AML %X not found\n",
+                                                                name, op->aml_offset));
+                                               acpi_cm_free (name);
+                                       }
+                                       else {
+                                               REPORT_WARNING (("Reference %s at AML %X not found\n",
+                                                                  op->value.string, op->aml_offset));
+                                       }
+                                       *obj_desc_ptr = NULL;
+                               }
+
+                               else {
+                                       return (status);
+                               }
+                       }
+               }
+
+               /*
+                * The reference will be a Reference
+                * TBD: [Restructure] unless we really need a separate
+                *  type of INTERNAL_TYPE_REFERENCE change
+                *  Acpi_ds_map_opcode_to_data_type to handle this case
+                */
+               type = INTERNAL_TYPE_REFERENCE;
+       }
+       else {
+               type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL);
+       }
+
+
+       /* Create and init the internal ACPI object */
+
+       obj_desc = acpi_cm_create_internal_object (type);
+       if (!obj_desc) {
+               return (AE_NO_MEMORY);
+       }
+
+       status = acpi_ds_init_object_from_op (walk_state, op,
+                        op->opcode, &obj_desc);
+
+       if (ACPI_FAILURE (status)) {
+               acpi_cm_remove_reference (obj_desc);
+               return (status);
+       }
+
+       *obj_desc_ptr = obj_desc;
+
+       return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_build_internal_package_obj
+ *
+ * PARAMETERS:  Op              - Parser object to be translated
+ *              Obj_desc_ptr    - Where the ACPI internal object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Translate a parser Op package object to the equivalent
+ *              namespace object
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_build_internal_package_obj (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_OPERAND_OBJECT     **obj_desc_ptr)
+{
+       ACPI_PARSE_OBJECT       *arg;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_STATUS             status = AE_OK;
+
+
+       obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
+       if (!obj_desc) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* The first argument must be the package length */
+
+       arg = op->value.arg;
+       obj_desc->package.count = arg->value.integer;
+
+       /*
+        * Allocate the array of pointers (ptrs to the
+        * individual objects) Add an extra pointer slot so
+        * that the list is always null terminated.
+        */
+
+       obj_desc->package.elements =
+                        acpi_cm_callocate ((obj_desc->package.count + 1) *
+                        sizeof (void *));
+
+       if (!obj_desc->package.elements) {
+               /* Package vector allocation failure   */
+
+               REPORT_ERROR (("Ds_build_internal_package_obj: Package vector allocation failure\n"));
+
+               acpi_cm_delete_object_desc (obj_desc);
+               return (AE_NO_MEMORY);
+       }
+
+       obj_desc->package.next_element = obj_desc->package.elements;
+
+       /*
+        * Now init the elements of the package
+        */
+
+       arg = arg->next;
+       while (arg) {
+               if (arg->opcode == AML_PACKAGE_OP) {
+                       status = acpi_ds_build_internal_package_obj (walk_state, arg,
+                                         obj_desc->package.next_element);
+               }
+
+               else {
+                       status = acpi_ds_build_internal_simple_obj (walk_state, arg,
+                                         obj_desc->package.next_element);
+               }
+
+               obj_desc->package.next_element++;
+               arg = arg->next;
+       }
+
+       *obj_desc_ptr = obj_desc;
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_build_internal_object
+ *
+ * PARAMETERS:  Op              - Parser object to be translated
+ *              Obj_desc_ptr    - Where the ACPI internal object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Translate a parser Op object to the equivalent namespace
+ *              object
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_build_internal_object (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_OPERAND_OBJECT     **obj_desc_ptr)
+{
+       ACPI_STATUS             status;
+
+
+       if (op->opcode == AML_PACKAGE_OP) {
+               status = acpi_ds_build_internal_package_obj (walk_state, op,
+                                 obj_desc_ptr);
+       }
+
+       else {
+               status = acpi_ds_build_internal_simple_obj (walk_state, op,
+                                 obj_desc_ptr);
+       }
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_node
+ *
+ * PARAMETERS:  Op              - Parser object to be translated
+ *              Obj_desc_ptr    - Where the ACPI internal object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_node (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_NAMESPACE_NODE     *node,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+
+
+       if (!op->value.arg) {
+               /* No arguments, there is nothing to do */
+
+               return (AE_OK);
+       }
+
+
+       /* Build an internal object for the argument(s) */
+
+       status = acpi_ds_build_internal_object (walk_state,
+                        op->value.arg, &obj_desc);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+
+       /* Re-type the object according to it's argument */
+
+       node->type = obj_desc->common.type;
+
+       /* Init obj */
+
+       status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc,
+                          (u8) node->type);
+       if (ACPI_FAILURE (status)) {
+               goto cleanup;
+       }
+
+       return (status);
+
+
+cleanup:
+
+       acpi_cm_remove_reference (obj_desc);
+
+       return (status);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dsopcode.c b/reactos/drivers/bus/acpi/dispatcher/dsopcode.c
new file mode 100644 (file)
index 0000000..459b81a
--- /dev/null
@@ -0,0 +1,875 @@
+/******************************************************************************
+ *
+ * Module Name: dsopcode - Dispatcher Op Region support and handling of
+ *                         "control" opcodes
+ *              $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"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acevents.h"
+#include "actables.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dsopcode")
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_get_field_unit_arguments
+ *
+ * PARAMETERS:  Obj_desc        - A valid Field_unit object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get Field_unit Buffer and Index. This implements the late
+ *              evaluation of these field attributes.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_get_field_unit_arguments (
+       ACPI_OPERAND_OBJECT     *obj_desc)
+{
+       ACPI_OPERAND_OBJECT     *extra_desc;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_PARSE_OBJECT       *op;
+       ACPI_PARSE_OBJECT       *field_op;
+       ACPI_STATUS             status;
+       ACPI_TABLE_DESC         *table_desc;
+
+
+       if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+               return (AE_OK);
+       }
+
+
+       /* Get the AML pointer (method object) and Field_unit node */
+
+       extra_desc = obj_desc->field_unit.extra;
+       node = obj_desc->field_unit.node;
+
+       /*
+        * Allocate a new parser op to be the root of the parsed
+        * Op_region tree
+        */
+
+       op = acpi_ps_alloc_op (AML_SCOPE_OP);
+       if (!op) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* Save the Node for use in Acpi_ps_parse_aml */
+
+       op->node = acpi_ns_get_parent_object (node);
+
+       /* Get a handle to the parent ACPI table */
+
+       status = acpi_tb_handle_to_object (node->owner_id, &table_desc);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Pass1: Parse the entire Field_unit declaration */
+
+       status = acpi_ps_parse_aml (op, extra_desc->extra.pcode,
+                         extra_desc->extra.pcode_length, 0,
+                         NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
+       if (ACPI_FAILURE (status)) {
+               acpi_ps_delete_parse_tree (op);
+               return (status);
+       }
+
+
+       /* Get and init the actual Fiel_unit_op created above */
+
+       field_op = op->value.arg;
+       op->node = node;
+
+
+       field_op = op->value.arg;
+       field_op->node = node;
+       acpi_ps_delete_parse_tree (op);
+
+       /* Acpi_evaluate the address and length arguments for the Op_region */
+
+       op = acpi_ps_alloc_op (AML_SCOPE_OP);
+       if (!op) {
+               return (AE_NO_MEMORY);
+       }
+
+       op->node = acpi_ns_get_parent_object (node);
+
+       status = acpi_ps_parse_aml (op, extra_desc->extra.pcode,
+                         extra_desc->extra.pcode_length,
+                         ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE,
+                         NULL /*Method_desc*/, NULL, NULL,
+                         acpi_ds_exec_begin_op, acpi_ds_exec_end_op);
+       /* All done with the parse tree, delete it */
+
+       acpi_ps_delete_parse_tree (op);
+
+
+       /*
+        * The pseudo-method object is no longer needed since the region is
+        * now initialized
+        */
+       acpi_cm_remove_reference (obj_desc->field_unit.extra);
+       obj_desc->field_unit.extra = NULL;
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_get_region_arguments
+ *
+ * PARAMETERS:  Obj_desc        - A valid region object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get region address and length.  This implements the late
+ *              evaluation of these region attributes.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_get_region_arguments (
+       ACPI_OPERAND_OBJECT     *obj_desc)
+{
+       ACPI_OPERAND_OBJECT     *extra_desc = NULL;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_PARSE_OBJECT       *op;
+       ACPI_PARSE_OBJECT       *region_op;
+       ACPI_STATUS             status;
+       ACPI_TABLE_DESC         *table_desc;
+
+
+       if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
+               return (AE_OK);
+       }
+
+
+       /* Get the AML pointer (method object) and region node */
+
+       extra_desc = obj_desc->region.extra;
+       node = obj_desc->region.node;
+
+       /*
+        * Allocate a new parser op to be the root of the parsed
+        * Op_region tree
+        */
+
+       op = acpi_ps_alloc_op (AML_SCOPE_OP);
+       if (!op) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* Save the Node for use in Acpi_ps_parse_aml */
+
+       op->node = acpi_ns_get_parent_object (node);
+
+       /* Get a handle to the parent ACPI table */
+
+       status = acpi_tb_handle_to_object (node->owner_id, &table_desc);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Parse the entire Op_region declaration, creating a parse tree */
+
+       status = acpi_ps_parse_aml (op, extra_desc->extra.pcode,
+                         extra_desc->extra.pcode_length, 0,
+                         NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
+
+       if (ACPI_FAILURE (status)) {
+               acpi_ps_delete_parse_tree (op);
+               return (status);
+       }
+
+
+       /* Get and init the actual Region_op created above */
+
+       region_op = op->value.arg;
+       op->node = node;
+
+
+       region_op = op->value.arg;
+       region_op->node = node;
+       acpi_ps_delete_parse_tree (op);
+
+       /* Acpi_evaluate the address and length arguments for the Op_region */
+
+       op = acpi_ps_alloc_op (AML_SCOPE_OP);
+       if (!op) {
+               return (AE_NO_MEMORY);
+       }
+
+       op->node = acpi_ns_get_parent_object (node);
+
+       status = acpi_ps_parse_aml (op, extra_desc->extra.pcode,
+                         extra_desc->extra.pcode_length,
+                         ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE,
+                         NULL /*Method_desc*/, NULL, NULL,
+                         acpi_ds_exec_begin_op, acpi_ds_exec_end_op);
+
+       /* All done with the parse tree, delete it */
+
+       acpi_ps_delete_parse_tree (op);
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_initialize_region
+ *
+ * PARAMETERS:  Op              - A valid region Op object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_initialize_region (
+       ACPI_HANDLE             obj_handle)
+{
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_STATUS             status;
+
+
+       obj_desc = acpi_ns_get_attached_object (obj_handle);
+
+       /* Namespace is NOT locked */
+
+       status = acpi_ev_initialize_region (obj_desc, FALSE);
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_eval_field_unit_operands
+ *
+ * PARAMETERS:  Op              - A valid Field_unit Op object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get Field_unit Buffer and Index
+ *              Called from Acpi_ds_exec_end_op during Field_unit parse tree walk
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_eval_field_unit_operands (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     *field_desc;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_PARSE_OBJECT       *next_op;
+       u32                     offset;
+       u32                     bit_offset;
+       u16                     bit_count;
+
+
+       ACPI_OPERAND_OBJECT     *res_desc = NULL;
+       ACPI_OPERAND_OBJECT     *cnt_desc = NULL;
+       ACPI_OPERAND_OBJECT     *off_desc = NULL;
+       ACPI_OPERAND_OBJECT     *src_desc = NULL;
+       u32                     num_operands = 3;
+
+
+       /*
+        * This is where we evaluate the address and length fields of the Op_field_unit declaration
+        */
+
+       node =  op->node;
+
+       /* Next_op points to the op that holds the Buffer */
+       next_op = op->value.arg;
+
+       /* Acpi_evaluate/create the address and length operands */
+
+       status = acpi_ds_create_operands (walk_state, next_op);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       field_desc = acpi_ns_get_attached_object (node);
+       if (!field_desc) {
+               return (AE_NOT_EXIST);
+       }
+
+
+       /* Resolve the operands */
+
+       status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state);
+
+       /* Get the operands */
+
+       status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state);
+       if (AML_CREATE_FIELD_OP == op->opcode) {
+               num_operands = 4;
+               status |= acpi_ds_obj_stack_pop_object (&cnt_desc, walk_state);
+       }
+
+       status |= acpi_ds_obj_stack_pop_object (&off_desc, walk_state);
+       status |= acpi_ds_obj_stack_pop_object (&src_desc, walk_state);
+
+       if (ACPI_FAILURE (status)) {
+               /* Invalid parameters on object stack  */
+
+               goto cleanup;
+       }
+
+
+       offset = (u32) off_desc->integer.value;
+
+
+       /*
+        * If Res_desc is a Name, it will be a direct name pointer after
+        * Acpi_aml_resolve_operands()
+        */
+
+       if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) {
+               status = AE_AML_OPERAND_TYPE;
+               goto cleanup;
+       }
+
+
+       /*
+        * Setup the Bit offsets and counts, according to the opcode
+        */
+
+       switch (op->opcode) {
+
+       /* Def_create_bit_field */
+
+       case AML_BIT_FIELD_OP:
+
+               /* Offset is in bits, Field is a bit */
+
+               bit_offset = offset;
+               bit_count = 1;
+               break;
+
+
+       /* Def_create_byte_field */
+
+       case AML_BYTE_FIELD_OP:
+
+               /* Offset is in bytes, field is a byte */
+
+               bit_offset = 8 * offset;
+               bit_count = 8;
+               break;
+
+
+       /* Def_create_word_field */
+
+       case AML_WORD_FIELD_OP:
+
+               /* Offset is in bytes, field is a word */
+
+               bit_offset = 8 * offset;
+               bit_count = 16;
+               break;
+
+
+       /* Def_create_dWord_field */
+
+       case AML_DWORD_FIELD_OP:
+
+               /* Offset is in bytes, field is a dword */
+
+               bit_offset = 8 * offset;
+               bit_count = 32;
+               break;
+
+
+       /* Def_create_field */
+
+       case AML_CREATE_FIELD_OP:
+
+               /* Offset is in bits, count is in bits */
+
+               bit_offset = offset;
+               bit_count = (u16) cnt_desc->integer.value;
+               break;
+
+
+       default:
+
+               status = AE_AML_BAD_OPCODE;
+               goto cleanup;
+       }
+
+
+       /*
+        * Setup field according to the object type
+        */
+
+       switch (src_desc->common.type) {
+
+       /* Source_buff :=  Term_arg=>Buffer */
+
+       case ACPI_TYPE_BUFFER:
+
+               if (bit_offset + (u32) bit_count >
+                       (8 * (u32) src_desc->buffer.length)) {
+                       status = AE_AML_BUFFER_LIMIT;
+                       goto cleanup;
+               }
+
+
+               /* Construct the remainder of the field object */
+
+               field_desc->field_unit.access     = (u8) ACCESS_ANY_ACC;
+               field_desc->field_unit.lock_rule  = (u8) GLOCK_NEVER_LOCK;
+               field_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE;
+               field_desc->field_unit.length     = bit_count;
+               field_desc->field_unit.bit_offset = (u8) (bit_offset % 8);
+               field_desc->field_unit.offset     = DIV_8 (bit_offset);
+               field_desc->field_unit.container  = src_desc;
+
+               /* Reference count for Src_desc inherits Field_desc count */
+
+               src_desc->common.reference_count = (u16) (src_desc->common.reference_count +
+                                  field_desc->common.reference_count);
+
+               break;
+
+
+       /* Improper object type */
+
+       default:
+
+
+
+               status = AE_AML_OPERAND_TYPE;
+               goto cleanup;
+       }
+
+
+       if (AML_CREATE_FIELD_OP == op->opcode) {
+               /* Delete object descriptor unique to Create_field */
+
+               acpi_cm_remove_reference (cnt_desc);
+               cnt_desc = NULL;
+       }
+
+
+cleanup:
+
+       /* Always delete the operands */
+
+       acpi_cm_remove_reference (off_desc);
+       acpi_cm_remove_reference (src_desc);
+
+       if (AML_CREATE_FIELD_OP == op->opcode) {
+               acpi_cm_remove_reference (cnt_desc);
+       }
+
+       /* On failure, delete the result descriptor */
+
+       if (ACPI_FAILURE (status)) {
+               acpi_cm_remove_reference (res_desc); /* Result descriptor */
+       }
+
+       else {
+               /* Now the address and length are valid for this op_field_unit */
+
+               field_desc->field_unit.flags |= AOPOBJ_DATA_VALID;
+       }
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_eval_region_operands
+ *
+ * PARAMETERS:  Op              - A valid region Op object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get region address and length
+ *              Called from Acpi_ds_exec_end_op during Op_region parse tree walk
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_eval_region_operands (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_OPERAND_OBJECT     *operand_desc;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_PARSE_OBJECT       *next_op;
+
+
+       /*
+        * This is where we evaluate the address and length fields of the Op_region declaration
+        */
+
+       node =  op->node;
+
+       /* Next_op points to the op that holds the Space_iD */
+       next_op = op->value.arg;
+
+       /* Next_op points to address op */
+       next_op = next_op->next;
+
+       /* Acpi_evaluate/create the address and length operands */
+
+       status = acpi_ds_create_operands (walk_state, next_op);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Resolve the length and address operands to numbers */
+
+       status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+
+       obj_desc = acpi_ns_get_attached_object (node);
+       if (!obj_desc) {
+               return (AE_NOT_EXIST);
+       }
+
+       /*
+        * Get the length operand and save it
+        * (at Top of stack)
+        */
+       operand_desc = walk_state->operands[walk_state->num_operands - 1];
+
+       obj_desc->region.length = (u32) operand_desc->integer.value;
+       acpi_cm_remove_reference (operand_desc);
+
+       /*
+        * Get the address and save it
+        * (at top of stack - 1)
+        */
+       operand_desc = walk_state->operands[walk_state->num_operands - 2];
+
+       obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value;
+       acpi_cm_remove_reference (operand_desc);
+
+
+       /* Now the address and length are valid for this opregion */
+
+       obj_desc->region.flags |= AOPOBJ_DATA_VALID;
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_exec_begin_control_op
+ *
+ * PARAMETERS:  Walk_list       - The list that owns the walk stack
+ *              Op              - The control Op
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Handles all control ops encountered during control method
+ *              execution.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_exec_begin_control_op (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status = AE_OK;
+       ACPI_GENERIC_STATE      *control_state;
+
+
+       switch (op->opcode) {
+       case AML_IF_OP:
+       case AML_WHILE_OP:
+
+               /*
+                * IF/WHILE: Create a new control state to manage these
+                * constructs. We need to manage these as a stack, in order
+                * to handle nesting.
+                */
+
+               control_state = acpi_cm_create_control_state ();
+               if (!control_state) {
+                       status = AE_NO_MEMORY;
+                       break;
+               }
+
+               acpi_cm_push_generic_state (&walk_state->control_state, control_state);
+
+               /*
+                * Save a pointer to the predicate for multiple executions
+                * of a loop
+                */
+               walk_state->control_state->control.aml_predicate_start =
+                                walk_state->parser_state->aml - 1;
+                                /* TBD: can this be removed? */
+                                /*Acpi_ps_pkg_length_encoding_size (GET8 (Walk_state->Parser_state->Aml));*/
+               break;
+
+
+       case AML_ELSE_OP:
+
+               /* Predicate is in the state object */
+               /* If predicate is true, the IF was executed, ignore ELSE part */
+
+               if (walk_state->last_predicate) {
+                       status = AE_CTRL_TRUE;
+               }
+
+               break;
+
+
+       case AML_RETURN_OP:
+
+               break;
+
+
+       default:
+               break;
+       }
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_exec_end_control_op
+ *
+ * PARAMETERS:  Walk_list       - The list that owns the walk stack
+ *              Op              - The control Op
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Handles all control ops encountered during control method
+ *              execution.
+ *
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_exec_end_control_op (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status = AE_OK;
+       ACPI_GENERIC_STATE      *control_state;
+
+
+       switch (op->opcode) {
+       case AML_IF_OP:
+
+               /*
+                * Save the result of the predicate in case there is an
+                * ELSE to come
+                */
+
+               walk_state->last_predicate =
+                               (u8) walk_state->control_state->common.value;
+
+               /*
+                * Pop the control state that was created at the start
+                * of the IF and free it
+                */
+
+               control_state =
+                               acpi_cm_pop_generic_state (&walk_state->control_state);
+
+               acpi_cm_delete_generic_state (control_state);
+
+               break;
+
+
+       case AML_ELSE_OP:
+
+               break;
+
+
+       case AML_WHILE_OP:
+
+               if (walk_state->control_state->common.value) {
+                       /* Predicate was true, go back and evaluate it again! */
+
+                       status = AE_CTRL_PENDING;
+               }
+
+
+               /* Pop this control state and free it */
+
+               control_state =
+                               acpi_cm_pop_generic_state (&walk_state->control_state);
+
+               walk_state->aml_last_while = control_state->control.aml_predicate_start;
+               acpi_cm_delete_generic_state (control_state);
+
+               break;
+
+
+       case AML_RETURN_OP:
+
+
+               /*
+                * One optional operand -- the return value
+                * It can be either an immediate operand or a result that
+                * has been bubbled up the tree
+                */
+               if (op->value.arg) {
+                       /* Return statement has an immediate operand */
+
+                       status = acpi_ds_create_operands (walk_state, op->value.arg);
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /*
+                        * If value being returned is a Reference (such as
+                        * an arg or local), resolve it now because it may
+                        * cease to exist at the end of the method.
+                        */
+                       status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state);
+                       if (ACPI_FAILURE (status)) {
+                               return (status);
+                       }
+
+                       /*
+                        * Get the return value and save as the last result
+                        * value.  This is the only place where Walk_state->Return_desc
+                        * is set to anything other than zero!
+                        */
+
+                       walk_state->return_desc = walk_state->operands[0];
+               }
+
+               else if ((walk_state->results) &&
+                                (walk_state->results->results.num_results > 0)) {
+                       /*
+                        * The return value has come from a previous calculation.
+                        *
+                        * If value being returned is a Reference (such as
+                        * an arg or local), resolve it now because it may
+                        * cease to exist at the end of the method.
+                        *
+                        * Allow references created by the Index operator to return unchanged.
+                        */
+
+                       if (VALID_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc [0], ACPI_DESC_TYPE_INTERNAL) &&
+                               ((walk_state->results->results.obj_desc [0])->common.type == INTERNAL_TYPE_REFERENCE) &&
+                               ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) {
+                                       status = acpi_aml_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state);
+                                       if (ACPI_FAILURE (status)) {
+                                               return (status);
+                                       }
+                       }
+
+                       walk_state->return_desc = walk_state->results->results.obj_desc [0];
+               }
+
+               else {
+                       /* No return operand */
+
+                       if (walk_state->num_operands) {
+                               acpi_cm_remove_reference (walk_state->operands [0]);
+                       }
+
+                       walk_state->operands [0]    = NULL;
+                       walk_state->num_operands    = 0;
+                       walk_state->return_desc     = NULL;
+               }
+
+
+               /* End the control method execution right now */
+               status = AE_CTRL_TERMINATE;
+               break;
+
+
+       case AML_NOOP_OP:
+
+               /* Just do nothing! */
+               break;
+
+
+       case AML_BREAK_POINT_OP:
+
+               /* Call up to the OS dependent layer to handle this */
+
+               acpi_os_breakpoint (NULL);
+
+               /* If it returns, we are done! */
+
+               break;
+
+
+       case AML_BREAK_OP:
+
+               /*
+                * As per the ACPI specification:
+                *      "The break operation causes the current package
+                *          execution to complete"
+                *      "Break -- Stop executing the current code package
+                *          at this point"
+                *
+                * Returning AE_FALSE here will cause termination of
+                * the current package, and execution will continue one
+                * level up, starting with the completion of the parent Op.
+                */
+
+               status = AE_CTRL_FALSE;
+               break;
+
+
+       default:
+
+               status = AE_AML_BAD_OPCODE;
+               break;
+       }
+
+
+       return (status);
+}
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dsutils.c b/reactos/drivers/bus/acpi/dispatcher/dsutils.c
new file mode 100644 (file)
index 0000000..c97204d
--- /dev/null
@@ -0,0 +1,750 @@
+/*******************************************************************************
+ *
+ * Module Name: dsutils - Dispatcher utilities
+ *              $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"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dsutils")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_is_result_used
+ *
+ * PARAMETERS:  Op
+ *              Result_obj
+ *              Walk_state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Check if a result object will be used by the parent
+ *
+ ******************************************************************************/
+
+u8
+acpi_ds_is_result_used (
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_OPCODE_INFO        *parent_info;
+
+
+       /* Must have both an Op and a Result Object */
+
+       if (!op) {
+               return (TRUE);
+       }
+
+
+       /*
+        * If there is no parent, the result can't possibly be used!
+        * (An executing method typically has no parent, since each
+        * method is parsed separately)  However, a method that is
+        * invoked from another method has a parent.
+        */
+       if (!op->parent) {
+               return (FALSE);
+       }
+
+
+       /*
+        * Get info on the parent.  The root Op is AML_SCOPE
+        */
+
+       parent_info = acpi_ps_get_opcode_info (op->parent->opcode);
+       if (ACPI_GET_OP_TYPE (parent_info) != ACPI_OP_TYPE_OPCODE) {
+               return (FALSE);
+       }
+
+
+       /*
+        * Decide what to do with the result based on the parent.  If
+        * the parent opcode will not use the result, delete the object.
+        * Otherwise leave it as is, it will be deleted when it is used
+        * as an operand later.
+        */
+
+       switch (ACPI_GET_OP_CLASS (parent_info)) {
+       /*
+        * In these cases, the parent will never use the return object
+        */
+       case OPTYPE_CONTROL:        /* IF, ELSE, WHILE only */
+
+               switch (op->parent->opcode) {
+               case AML_RETURN_OP:
+
+                       /* Never delete the return value associated with a return opcode */
+
+                       return (TRUE);
+                       break;
+
+               case AML_IF_OP:
+               case AML_WHILE_OP:
+
+                       /*
+                        * If we are executing the predicate AND this is the predicate op,
+                        * we will use the return value!
+                        */
+
+                       if ((walk_state->control_state->common.state == CONTROL_PREDICATE_EXECUTING) &&
+                               (walk_state->control_state->control.predicate_op == op)) {
+                               return (TRUE);
+                       }
+
+                       break;
+               }
+
+
+               /* Fall through to not used case below */
+
+
+       case OPTYPE_NAMED_OBJECT:   /* Scope, method, etc. */
+
+               /*
+                * These opcodes allow Term_arg(s) as operands and therefore
+                * method calls.  The result is used.
+                */
+               if ((op->parent->opcode == AML_REGION_OP)       ||
+                       (op->parent->opcode == AML_CREATE_FIELD_OP) ||
+                       (op->parent->opcode == AML_BIT_FIELD_OP)    ||
+                       (op->parent->opcode == AML_BYTE_FIELD_OP)   ||
+                       (op->parent->opcode == AML_WORD_FIELD_OP)   ||
+                       (op->parent->opcode == AML_DWORD_FIELD_OP)  ||
+                       (op->parent->opcode == AML_QWORD_FIELD_OP)) {
+                       return (TRUE);
+               }
+
+               return (FALSE);
+               break;
+
+       /*
+        * In all other cases. the parent will actually use the return
+        * object, so keep it.
+        */
+       default:
+               break;
+       }
+
+       return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_delete_result_if_not_used
+ *
+ * PARAMETERS:  Op
+ *              Result_obj
+ *              Walk_state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
+ *              result descriptor, check if the parent opcode will actually use
+ *              this result.  If not, delete the result now so that it will
+ *              not become orphaned.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_delete_result_if_not_used (
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_OPERAND_OBJECT     *result_obj,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_STATUS             status;
+
+
+       if (!op) {
+               return;
+       }
+
+       if (!result_obj) {
+               return;
+       }
+
+
+       if (!acpi_ds_is_result_used (op, walk_state)) {
+               /*
+                * Must pop the result stack (Obj_desc should be equal
+                *  to Result_obj)
+                */
+
+               status = acpi_ds_result_pop (&obj_desc, walk_state);
+               if (ACPI_SUCCESS (status)) {
+                       acpi_cm_remove_reference (result_obj);
+               }
+       }
+
+       return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_operand
+ *
+ * PARAMETERS:  Walk_state
+ *              Arg
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Translate a parse tree object that is an argument to an AML
+ *              opcode to the equivalent interpreter object.  This may include
+ *              looking up a name or entering a new name into the internal
+ *              namespace.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_operand (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *arg,
+       u32                     arg_index)
+{
+       ACPI_STATUS             status = AE_OK;
+       NATIVE_CHAR             *name_string;
+       u32                     name_length;
+       OBJECT_TYPE_INTERNAL    data_type;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_PARSE_OBJECT       *parent_op;
+       u16                     opcode;
+       u32                     flags;
+       OPERATING_MODE          interpreter_mode;
+
+
+       /* A valid name must be looked up in the namespace */
+
+       if ((arg->opcode == AML_NAMEPATH_OP) &&
+               (arg->value.string)) {
+               /* Get the entire name string from the AML stream */
+
+               status = acpi_aml_get_name_string (ACPI_TYPE_ANY,
+                                  arg->value.buffer,
+                                  &name_string,
+                                  &name_length);
+
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               /*
+                * All prefixes have been handled, and the name is
+                * in Name_string
+                */
+
+               /*
+                * Differentiate between a namespace "create" operation
+                * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
+                * IMODE_EXECUTE) in order to support the creation of
+                * namespace objects during the execution of control methods.
+                */
+
+               parent_op = arg->parent;
+               if ((acpi_ps_is_node_op (parent_op->opcode)) &&
+                       (parent_op->opcode != AML_METHODCALL_OP) &&
+                       (parent_op->opcode != AML_REGION_OP) &&
+                       (parent_op->opcode != AML_NAMEPATH_OP)) {
+                       /* Enter name into namespace if not found */
+
+                       interpreter_mode = IMODE_LOAD_PASS2;
+               }
+
+               else {
+                       /* Return a failure if name not found */
+
+                       interpreter_mode = IMODE_EXECUTE;
+               }
+
+               status = acpi_ns_lookup (walk_state->scope_info, name_string,
+                                ACPI_TYPE_ANY, interpreter_mode,
+                                NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
+                                walk_state,
+                                (ACPI_NAMESPACE_NODE **) &obj_desc);
+
+               /* Free the namestring created above */
+
+               acpi_cm_free (name_string);
+
+               /*
+                * The only case where we pass through (ignore) a NOT_FOUND
+                * error is for the Cond_ref_of opcode.
+                */
+
+               if (status == AE_NOT_FOUND) {
+                       if (parent_op->opcode == AML_COND_REF_OF_OP) {
+                               /*
+                                * For the Conditional Reference op, it's OK if
+                                * the name is not found;  We just need a way to
+                                * indicate this to the interpreter, set the
+                                * object to the root
+                                */
+                               obj_desc = (ACPI_OPERAND_OBJECT *) acpi_gbl_root_node;
+                               status = AE_OK;
+                       }
+
+                       else {
+                               /*
+                                * We just plain didn't find it -- which is a
+                                * very serious error at this point
+                                */
+                               status = AE_AML_NAME_NOT_FOUND;
+                       }
+               }
+
+               /* Check status from the lookup */
+
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               /* Put the resulting object onto the current object stack */
+
+               status = acpi_ds_obj_stack_push (obj_desc, walk_state);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+               DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+       }
+
+
+       else {
+               /* Check for null name case */
+
+               if (arg->opcode == AML_NAMEPATH_OP) {
+                       /*
+                        * If the name is null, this means that this is an
+                        * optional result parameter that was not specified
+                        * in the original ASL.  Create an Reference for a
+                        * placeholder
+                        */
+                       opcode = AML_ZERO_OP;       /* Has no arguments! */
+
+                       /*
+                        * TBD: [Investigate] anything else needed for the
+                        * zero op lvalue?
+                        */
+               }
+
+               else {
+                       opcode = arg->opcode;
+               }
+
+
+               /* Get the data type of the argument */
+
+               data_type = acpi_ds_map_opcode_to_data_type (opcode, &flags);
+               if (data_type == INTERNAL_TYPE_INVALID) {
+                       return (AE_NOT_IMPLEMENTED);
+               }
+
+               if (flags & OP_HAS_RETURN_VALUE) {
+                       DEBUGGER_EXEC (acpi_db_display_argument_object (walk_state->operands [walk_state->num_operands - 1], walk_state));
+
+                       /*
+                        * Use value that was already previously returned
+                        * by the evaluation of this argument
+                        */
+
+                       status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
+                       if (ACPI_FAILURE (status)) {
+                               /*
+                                * Only error is underflow, and this indicates
+                                * a missing or null operand!
+                                */
+                               return (status);
+                       }
+
+               }
+
+               else {
+                       /* Create an ACPI_INTERNAL_OBJECT for the argument */
+
+                       obj_desc = acpi_cm_create_internal_object (data_type);
+                       if (!obj_desc) {
+                               return (AE_NO_MEMORY);
+                       }
+
+                       /* Initialize the new object */
+
+                       status = acpi_ds_init_object_from_op (walk_state, arg,
+                                        opcode, &obj_desc);
+                       if (ACPI_FAILURE (status)) {
+                               acpi_cm_delete_object_desc (obj_desc);
+                               return (status);
+                       }
+          }
+
+               /* Put the operand object on the object stack */
+
+               status = acpi_ds_obj_stack_push (obj_desc, walk_state);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_operands
+ *
+ * PARAMETERS:  First_arg           - First argument of a parser argument tree
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an operator's arguments from a parse tree format to
+ *              namespace objects and place those argument object on the object
+ *              stack in preparation for evaluation by the interpreter.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_operands (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *first_arg)
+{
+       ACPI_STATUS             status = AE_OK;
+       ACPI_PARSE_OBJECT       *arg;
+       u32                     arg_count = 0;
+
+
+       /* For all arguments in the list... */
+
+       arg = first_arg;
+       while (arg) {
+               status = acpi_ds_create_operand (walk_state, arg, arg_count);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               /* Move on to next argument, if any */
+
+               arg = arg->next;
+               arg_count++;
+       }
+
+       return (status);
+
+
+cleanup:
+       /*
+        * We must undo everything done above; meaning that we must
+        * pop everything off of the operand stack and delete those
+        * objects
+        */
+
+       acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_resolve_operands
+ *
+ * PARAMETERS:  Walk_state          - Current walk state with operands on stack
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Resolve all operands to their values.  Used to prepare
+ *              arguments to a control method invocation (a call from one
+ *              method to another.)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_resolve_operands (
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     i;
+       ACPI_STATUS             status = AE_OK;
+
+
+       /*
+        * Attempt to resolve each of the valid operands
+        * Method arguments are passed by value, not by reference
+        */
+
+       /*
+        * TBD: [Investigate] Note from previous parser:
+        *   Ref_of problem with Acpi_aml_resolve_to_value() conversion.
+        */
+
+       for (i = 0; i < walk_state->num_operands; i++) {
+               status = acpi_aml_resolve_to_value (&walk_state->operands[i], walk_state);
+               if (ACPI_FAILURE (status)) {
+                       break;
+               }
+       }
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_map_opcode_to_data_type
+ *
+ * PARAMETERS:  Opcode          - AML opcode to map
+ *              Out_flags       - Additional info about the opcode
+ *
+ * RETURN:      The ACPI type associated with the opcode
+ *
+ * DESCRIPTION: Convert a raw AML opcode to the associated ACPI data type,
+ *              if any.  If the opcode returns a value as part of the
+ *              intepreter execution, a flag is returned in Out_flags.
+ *
+ ******************************************************************************/
+
+OBJECT_TYPE_INTERNAL
+acpi_ds_map_opcode_to_data_type (
+       u16                     opcode,
+       u32                     *out_flags)
+{
+       OBJECT_TYPE_INTERNAL    data_type = INTERNAL_TYPE_INVALID;
+       ACPI_OPCODE_INFO        *op_info;
+       u32                     flags = 0;
+
+
+       op_info = acpi_ps_get_opcode_info (opcode);
+       if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
+               /* Unknown opcode */
+
+               return (data_type);
+       }
+
+       switch (ACPI_GET_OP_CLASS (op_info)) {
+
+       case OPTYPE_LITERAL:
+
+               switch (opcode) {
+               case AML_BYTE_OP:
+               case AML_WORD_OP:
+               case AML_DWORD_OP:
+
+                       data_type = ACPI_TYPE_INTEGER;
+                       break;
+
+
+               case AML_STRING_OP:
+
+                       data_type = ACPI_TYPE_STRING;
+                       break;
+
+               case AML_NAMEPATH_OP:
+                       data_type = INTERNAL_TYPE_REFERENCE;
+                       break;
+
+               default:
+                       break;
+               }
+               break;
+
+
+       case OPTYPE_DATA_TERM:
+
+               switch (opcode) {
+               case AML_BUFFER_OP:
+
+                       data_type = ACPI_TYPE_BUFFER;
+                       break;
+
+               case AML_PACKAGE_OP:
+
+                       data_type = ACPI_TYPE_PACKAGE;
+                       break;
+
+               default:
+                       break;
+               }
+               break;
+
+
+       case OPTYPE_CONSTANT:
+       case OPTYPE_METHOD_ARGUMENT:
+       case OPTYPE_LOCAL_VARIABLE:
+
+               data_type = INTERNAL_TYPE_REFERENCE;
+               break;
+
+
+       case OPTYPE_MONADIC2:
+       case OPTYPE_MONADIC2_r:
+       case OPTYPE_DYADIC2:
+       case OPTYPE_DYADIC2_r:
+       case OPTYPE_DYADIC2_s:
+       case OPTYPE_INDEX:
+       case OPTYPE_MATCH:
+       case OPTYPE_RETURN:
+
+               flags = OP_HAS_RETURN_VALUE;
+               data_type = ACPI_TYPE_ANY;
+               break;
+
+       case OPTYPE_METHOD_CALL:
+
+               flags = OP_HAS_RETURN_VALUE;
+               data_type = ACPI_TYPE_METHOD;
+               break;
+
+
+       case OPTYPE_NAMED_OBJECT:
+
+               data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
+               break;
+
+
+       case OPTYPE_DYADIC1:
+       case OPTYPE_CONTROL:
+
+               /* No mapping needed at this time */
+
+               break;
+
+
+       default:
+
+               break;
+       }
+
+       /* Return flags to caller if requested */
+
+       if (out_flags) {
+               *out_flags = flags;
+       }
+
+       return (data_type);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_map_named_opcode_to_data_type
+ *
+ * PARAMETERS:  Opcode              - The Named AML opcode to map
+ *
+ * RETURN:      The ACPI type associated with the named opcode
+ *
+ * DESCRIPTION: Convert a raw Named AML opcode to the associated data type.
+ *              Named opcodes are a subsystem of the AML opcodes.
+ *
+ ******************************************************************************/
+
+OBJECT_TYPE_INTERNAL
+acpi_ds_map_named_opcode_to_data_type (
+       u16                     opcode)
+{
+       OBJECT_TYPE_INTERNAL    data_type;
+
+
+       /* Decode Opcode */
+
+       switch (opcode) {
+       case AML_SCOPE_OP:
+               data_type = INTERNAL_TYPE_SCOPE;
+               break;
+
+       case AML_DEVICE_OP:
+               data_type = ACPI_TYPE_DEVICE;
+               break;
+
+       case AML_THERMAL_ZONE_OP:
+               data_type = ACPI_TYPE_THERMAL;
+               break;
+
+       case AML_METHOD_OP:
+               data_type = ACPI_TYPE_METHOD;
+               break;
+
+       case AML_POWER_RES_OP:
+               data_type = ACPI_TYPE_POWER;
+               break;
+
+       case AML_PROCESSOR_OP:
+               data_type = ACPI_TYPE_PROCESSOR;
+               break;
+
+       case AML_DEF_FIELD_OP:                          /* Def_field_op */
+               data_type = INTERNAL_TYPE_DEF_FIELD_DEFN;
+               break;
+
+       case AML_INDEX_FIELD_OP:                        /* Index_field_op */
+               data_type = INTERNAL_TYPE_INDEX_FIELD_DEFN;
+               break;
+
+       case AML_BANK_FIELD_OP:                         /* Bank_field_op */
+               data_type = INTERNAL_TYPE_BANK_FIELD_DEFN;
+               break;
+
+       case AML_NAMEDFIELD_OP:                         /* NO CASE IN ORIGINAL  */
+               data_type = ACPI_TYPE_ANY;
+               break;
+
+       case AML_NAME_OP:                               /* Name_op - special code in original */
+       case AML_NAMEPATH_OP:
+               data_type = ACPI_TYPE_ANY;
+               break;
+
+       case AML_ALIAS_OP:
+               data_type = INTERNAL_TYPE_ALIAS;
+               break;
+
+       case AML_MUTEX_OP:
+               data_type = ACPI_TYPE_MUTEX;
+               break;
+
+       case AML_EVENT_OP:
+               data_type = ACPI_TYPE_EVENT;
+               break;
+
+       case AML_REGION_OP:
+               data_type = ACPI_TYPE_REGION;
+               break;
+
+
+       default:
+               data_type = ACPI_TYPE_ANY;
+               break;
+
+       }
+
+       return (data_type);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dswexec.c b/reactos/drivers/bus/acpi/dispatcher/dswexec.c
new file mode 100644 (file)
index 0000000..3105525
--- /dev/null
@@ -0,0 +1,653 @@
+/******************************************************************************
+ *
+ * Module Name: dswexec - Dispatcher method execution callbacks;
+ *                        dispatch to interpreter.
+ *              $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"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dswexec")
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_get_predicate_value
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get the result of a predicate evaluation
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_get_predicate_value (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op,
+       u32                     has_result_obj)
+{
+       ACPI_STATUS             status = AE_OK;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+
+
+       walk_state->control_state->common.state = 0;
+
+       if (has_result_obj) {
+               status = acpi_ds_result_pop (&obj_desc, walk_state);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+       }
+
+       else {
+               status = acpi_ds_create_operand (walk_state, op, 0);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               obj_desc = walk_state->operands [0];
+       }
+
+       if (!obj_desc) {
+               return (AE_AML_NO_OPERAND);
+       }
+
+
+       /*
+        * Result of predicate evaluation currently must
+        * be a number
+        */
+
+       if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
+               status = AE_AML_OPERAND_TYPE;
+               goto cleanup;
+       }
+
+
+       /* Truncate the predicate to 32-bits if necessary */
+
+       acpi_aml_truncate_for32bit_table (obj_desc, walk_state);
+
+       /*
+        * Save the result of the predicate evaluation on
+        * the control stack
+        */
+
+       if (obj_desc->integer.value) {
+               walk_state->control_state->common.value = TRUE;
+       }
+
+       else {
+               /*
+                * Predicate is FALSE, we will just toss the
+                * rest of the package
+                */
+
+               walk_state->control_state->common.value = FALSE;
+               status = AE_CTRL_FALSE;
+       }
+
+
+cleanup:
+
+        /* Break to debugger to display result */
+
+       DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state));
+
+       /*
+        * Delete the predicate result object (we know that
+        * we don't need it anymore)
+        */
+
+       acpi_cm_remove_reference (obj_desc);
+
+       walk_state->control_state->common.state = CONTROL_NORMAL;
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_exec_begin_op
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *              Op              - Op that has been just been reached in the
+ *                                walk;  Arguments have not been evaluated yet.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Descending callback used during the execution of control
+ *              methods.  This is where most operators and operands are
+ *              dispatched to the interpreter.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_exec_begin_op (
+       u16                     opcode,
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       **out_op)
+{
+       ACPI_OPCODE_INFO        *op_info;
+       ACPI_STATUS             status = AE_OK;
+
+
+       if (!op) {
+               status = acpi_ds_load2_begin_op (opcode, NULL, walk_state, out_op);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               op = *out_op;
+       }
+
+       if (op == walk_state->origin) {
+               if (out_op) {
+                       *out_op = op;
+               }
+
+               return (AE_OK);
+       }
+
+       /*
+        * If the previous opcode was a conditional, this opcode
+        * must be the beginning of the associated predicate.
+        * Save this knowledge in the current scope descriptor
+        */
+
+       if ((walk_state->control_state) &&
+               (walk_state->control_state->common.state ==
+                       CONTROL_CONDITIONAL_EXECUTING)) {
+               walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING;
+
+               /* Save start of predicate */
+
+               walk_state->control_state->control.predicate_op = op;
+       }
+
+
+       op_info = acpi_ps_get_opcode_info (op->opcode);
+
+       /* We want to send namepaths to the load code */
+
+       if (op->opcode == AML_NAMEPATH_OP) {
+               op_info->flags = OPTYPE_NAMED_OBJECT;
+       }
+
+
+       /*
+        * Handle the opcode based upon the opcode type
+        */
+
+       switch (ACPI_GET_OP_CLASS (op_info)) {
+       case OPTYPE_CONTROL:
+
+               status = acpi_ds_result_stack_push (walk_state);
+               if (ACPI_FAILURE (status)) {
+                       return (status);
+               }
+
+               status = acpi_ds_exec_begin_control_op (walk_state, op);
+               break;
+
+
+       case OPTYPE_NAMED_OBJECT:
+
+               if (walk_state->walk_type == WALK_METHOD) {
+                       /*
+                        * Found a named object declaration during method
+                        * execution;  we must enter this object into the
+                        * namespace.  The created object is temporary and
+                        * will be deleted upon completion of the execution
+                        * of this method.
+                        */
+
+                       status = acpi_ds_load2_begin_op (op->opcode, op, walk_state, NULL);
+               }
+
+
+               if (op->opcode == AML_REGION_OP) {
+                       status = acpi_ds_result_stack_push (walk_state);
+               }
+
+               break;
+
+
+       /* most operators with arguments */
+
+       case OPTYPE_MONADIC1:
+       case OPTYPE_DYADIC1:
+       case OPTYPE_MONADIC2:
+       case OPTYPE_MONADIC2_r:
+       case OPTYPE_DYADIC2:
+       case OPTYPE_DYADIC2_r:
+       case OPTYPE_DYADIC2_s:
+       case OPTYPE_RECONFIGURATION:
+       case OPTYPE_INDEX:
+       case OPTYPE_MATCH:
+       case OPTYPE_FATAL:
+       case OPTYPE_CREATE_FIELD:
+
+               /* Start a new result/operand state */
+
+               status = acpi_ds_result_stack_push (walk_state);
+               break;
+
+
+       default:
+               break;
+       }
+
+       /* Nothing to do here during method execution */
+
+       return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_exec_end_op
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *              Op              - Op that has been just been completed in the
+ *                                walk;  Arguments have now been evaluated.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Ascending callback used during the execution of control
+ *              methods.  The only thing we really need to do here is to
+ *              notice the beginning of IF, ELSE, and WHILE blocks.
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_exec_end_op (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status = AE_OK;
+       u16                     opcode;
+       u8                      optype;
+       ACPI_PARSE_OBJECT       *next_op;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_PARSE_OBJECT       *first_arg;
+       ACPI_OPERAND_OBJECT     *result_obj = NULL;
+       ACPI_OPCODE_INFO        *op_info;
+       u32                     operand_index;
+
+
+       opcode = (u16) op->opcode;
+
+
+       op_info = acpi_ps_get_opcode_info (op->opcode);
+       if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
+               return (AE_NOT_IMPLEMENTED);
+       }
+
+       optype = (u8) ACPI_GET_OP_CLASS (op_info);
+       first_arg = op->value.arg;
+
+       /* Init the walk state */
+
+       walk_state->num_operands = 0;
+       walk_state->return_desc = NULL;
+       walk_state->op_info = op_info;
+       walk_state->opcode = opcode;
+
+
+       /* Call debugger for single step support (DEBUG build only) */
+
+       DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, optype));
+       DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return (status);});
+
+
+       /* Decode the opcode */
+
+       switch (optype) {
+       case OPTYPE_UNDEFINED:
+
+               return (AE_NOT_IMPLEMENTED);
+               break;
+
+
+       case OPTYPE_BOGUS:
+               break;
+
+       case OPTYPE_CONSTANT:           /* argument type only */
+       case OPTYPE_LITERAL:            /* argument type only */
+       case OPTYPE_DATA_TERM:          /* argument type only */
+       case OPTYPE_LOCAL_VARIABLE:     /* argument type only */
+       case OPTYPE_METHOD_ARGUMENT:    /* argument type only */
+               break;
+
+
+       /* most operators with arguments */
+
+       case OPTYPE_MONADIC1:
+       case OPTYPE_DYADIC1:
+       case OPTYPE_MONADIC2:
+       case OPTYPE_MONADIC2_r:
+       case OPTYPE_DYADIC2:
+       case OPTYPE_DYADIC2_r:
+       case OPTYPE_DYADIC2_s:
+       case OPTYPE_RECONFIGURATION:
+       case OPTYPE_INDEX:
+       case OPTYPE_MATCH:
+       case OPTYPE_FATAL:
+
+
+               /* Build resolved operand stack */
+
+               status = acpi_ds_create_operands (walk_state, first_arg);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               operand_index = walk_state->num_operands - 1;
+
+
+               /* Done with this result state (Now that operand stack is built) */
+
+               status = acpi_ds_result_stack_pop (walk_state);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               switch (optype) {
+               case OPTYPE_MONADIC1:
+
+                       /* 1 Operand, 0 External_result, 0 Internal_result */
+
+                       status = acpi_aml_exec_monadic1 (opcode, walk_state);
+                       break;
+
+
+               case OPTYPE_MONADIC2:
+
+                       /* 1 Operand, 0 External_result, 1 Internal_result */
+
+                       status = acpi_aml_exec_monadic2 (opcode, walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_MONADIC2_r:
+
+                       /* 1 Operand, 1 External_result, 1 Internal_result */
+
+                       status = acpi_aml_exec_monadic2_r (opcode, walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_DYADIC1:
+
+                       /* 2 Operands, 0 External_result, 0 Internal_result */
+
+                       status = acpi_aml_exec_dyadic1 (opcode, walk_state);
+                       break;
+
+
+               case OPTYPE_DYADIC2:
+
+                       /* 2 Operands, 0 External_result, 1 Internal_result */
+
+                       status = acpi_aml_exec_dyadic2 (opcode, walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_DYADIC2_r:
+
+                       /* 2 Operands, 1 or 2 External_results, 1 Internal_result */
+
+                       status = acpi_aml_exec_dyadic2_r (opcode, walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_DYADIC2_s:  /* Synchronization Operator */
+
+                       /* 2 Operands, 0 External_result, 1 Internal_result */
+
+                       status = acpi_aml_exec_dyadic2_s (opcode, walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_INDEX:  /* Type 2 opcode with 3 operands */
+
+                       /* 3 Operands, 1 External_result, 1 Internal_result */
+
+                       status = acpi_aml_exec_index (walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_MATCH:  /* Type 2 opcode with 6 operands */
+
+                       /* 6 Operands, 0 External_result, 1 Internal_result */
+
+                       status = acpi_aml_exec_match (walk_state, &result_obj);
+                       break;
+
+
+               case OPTYPE_RECONFIGURATION:
+
+                       /* 1 or 2 operands, 0 Internal Result */
+
+                       status = acpi_aml_exec_reconfiguration (opcode, walk_state);
+                       break;
+
+
+               case OPTYPE_FATAL:
+
+                       /* 3 Operands, 0 External_result, 0 Internal_result */
+
+                       status = acpi_aml_exec_fatal (walk_state);
+                       break;
+               }
+
+               /*
+                * If a result object was returned from above, push it on the
+                * current result stack
+                */
+               if (ACPI_SUCCESS (status) &&
+                       result_obj) {
+                       status = acpi_ds_result_push (result_obj, walk_state);
+               }
+
+               break;
+
+
+       case OPTYPE_CONTROL:    /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
+
+               /* 1 Operand, 0 External_result, 0 Internal_result */
+
+               status = acpi_ds_exec_end_control_op (walk_state, op);
+
+               acpi_ds_result_stack_pop (walk_state);
+               break;
+
+
+       case OPTYPE_METHOD_CALL:
+
+               /*
+                * (AML_METHODCALL) Op->Value->Arg->Node contains
+                * the method Node pointer
+                */
+               /* Next_op points to the op that holds the method name */
+
+               next_op = first_arg;
+               node = next_op->node;
+
+               /* Next_op points to first argument op */
+
+               next_op = next_op->next;
+
+               /*
+                * Get the method's arguments and put them on the operand stack
+                */
+               status = acpi_ds_create_operands (walk_state, next_op);
+               if (ACPI_FAILURE (status)) {
+                       break;
+               }
+
+               /*
+                * Since the operands will be passed to another
+                * control method, we must resolve all local
+                * references here (Local variables, arguments
+                * to *this* method, etc.)
+                */
+
+               status = acpi_ds_resolve_operands (walk_state);
+               if (ACPI_FAILURE (status)) {
+                       break;
+               }
+
+               /*
+                * Tell the walk loop to preempt this running method and
+                * execute the new method
+                */
+               status = AE_CTRL_TRANSFER;
+
+               /*
+                * Return now; we don't want to disturb anything,
+                * especially the operand count!
+                */
+               return (status);
+               break;
+
+
+       case OPTYPE_CREATE_FIELD:
+
+               status = acpi_ds_load2_end_op (walk_state, op);
+               if (ACPI_FAILURE (status)) {
+                       break;
+               }
+
+               status = acpi_ds_eval_field_unit_operands (walk_state, op);
+               break;
+
+
+       case OPTYPE_NAMED_OBJECT:
+
+               status = acpi_ds_load2_end_op (walk_state, op);
+               if (ACPI_FAILURE (status)) {
+                       break;
+               }
+
+               switch (op->opcode) {
+               case AML_REGION_OP:
+
+                       status = acpi_ds_eval_region_operands (walk_state, op);
+                       if (ACPI_FAILURE (status)) {
+                               break;
+                       }
+
+                       status = acpi_ds_result_stack_pop (walk_state);
+                       break;
+
+
+               case AML_METHOD_OP:
+                       break;
+
+
+               case AML_ALIAS_OP:
+
+                       /* Alias creation was already handled by call
+                       to psxload above */
+                       break;
+
+
+               default:
+                       /* Nothing needs to be done */
+
+                       status = AE_OK;
+                       break;
+               }
+
+               break;
+
+       default:
+
+               status = AE_NOT_IMPLEMENTED;
+               break;
+       }
+
+
+       /*
+        * ACPI 2.0 support for 64-bit integers:
+        * Truncate numeric result value if we are executing from a 32-bit ACPI table
+        */
+       acpi_aml_truncate_for32bit_table (result_obj, walk_state);
+
+       /*
+        * Check if we just completed the evaluation of a
+        * conditional predicate
+        */
+
+       if ((walk_state->control_state) &&
+               (walk_state->control_state->common.state ==
+                       CONTROL_PREDICATE_EXECUTING) &&
+               (walk_state->control_state->control.predicate_op == op)) {
+               status = acpi_ds_get_predicate_value (walk_state, op, (u32) result_obj);
+               result_obj = NULL;
+       }
+
+
+cleanup:
+       if (result_obj) {
+               /* Break to debugger to display result */
+
+               DEBUGGER_EXEC (acpi_db_display_result_object (result_obj, walk_state));
+
+               /*
+                * Delete the result op if and only if:
+                * Parent will not use the result -- such as any
+                * non-nested type2 op in a method (parent will be method)
+                */
+               acpi_ds_delete_result_if_not_used (op, result_obj, walk_state);
+       }
+
+       /* Always clear the object stack */
+
+       /* TBD: [Investigate] Clear stack of return value,
+       but don't delete it */
+       walk_state->num_operands = 0;
+
+       return (status);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dswload.c b/reactos/drivers/bus/acpi/dispatcher/dswload.c
new file mode 100644 (file)
index 0000000..4c072ed
--- /dev/null
@@ -0,0 +1,679 @@
+/******************************************************************************
+ *
+ * Module Name: dswload - Dispatcher namespace load callbacks
+ *              $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"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acevents.h"
+
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dswload")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_load1_begin_op
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *              Op              - Op that has been just been reached in the
+ *                                walk;  Arguments have not been evaluated yet.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Descending callback used during the loading of ACPI tables.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_load1_begin_op (
+       u16                     opcode,
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       **out_op)
+{
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_STATUS             status;
+       OBJECT_TYPE_INTERNAL    data_type;
+       NATIVE_CHAR             *path;
+
+
+       /* We are only interested in opcodes that have an associated name */
+
+       if (!acpi_ps_is_named_op (opcode)) {
+               *out_op = op;
+               return (AE_OK);
+       }
+
+
+       /* Check if this object has already been installed in the namespace */
+
+       if (op && op->node) {
+               *out_op = op;
+               return (AE_OK);
+       }
+
+       path = acpi_ps_get_next_namestring (walk_state->parser_state);
+
+       /* Map the raw opcode into an internal object type */
+
+       data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
+
+
+
+       /*
+        * Enter the named type into the internal namespace.  We enter the name
+        * as we go downward in the parse tree.  Any necessary subobjects that involve
+        * arguments to the opcode must be created as we go back up the parse tree later.
+        */
+       status = acpi_ns_lookup (walk_state->scope_info, path,
+                        data_type, IMODE_LOAD_PASS1,
+                        NS_NO_UPSEARCH, walk_state, &(node));
+
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       if (!op) {
+               /* Create a new op */
+
+               op = acpi_ps_alloc_op (opcode);
+               if (!op) {
+                       return (AE_NO_MEMORY);
+               }
+       }
+
+       /* Initialize */
+
+       ((ACPI_PARSE2_OBJECT *)op)->name = node->name;
+
+       /*
+        * Put the Node in the "op" object that the parser uses, so we
+        * can get it again quickly when this scope is closed
+        */
+       op->node = node;
+
+
+       acpi_ps_append_arg (acpi_ps_get_parent_scope (walk_state->parser_state), op);
+
+       *out_op = op;
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_load1_end_op
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *              Op              - Op that has been just been completed in the
+ *                                walk;  Arguments have now been evaluated.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Ascending callback used during the loading of the namespace,
+ *              both control methods and everything else.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_load1_end_op (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       OBJECT_TYPE_INTERNAL    data_type;
+
+
+       /* We are only interested in opcodes that have an associated name */
+
+       if (!acpi_ps_is_named_op (op->opcode)) {
+               return (AE_OK);
+       }
+
+
+       /* Get the type to determine if we should pop the scope */
+
+       data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
+
+       if (op->opcode == AML_NAME_OP) {
+               /* For Name opcode, check the argument */
+
+               if (op->value.arg) {
+                       data_type = acpi_ds_map_opcode_to_data_type (
+                                         (op->value.arg)->opcode, NULL);
+                       ((ACPI_NAMESPACE_NODE *)op->node)->type =
+                                         (u8) data_type;
+               }
+       }
+
+
+       /* Pop the scope stack */
+
+       if (acpi_ns_opens_scope (data_type)) {
+
+               acpi_ds_scope_stack_pop (walk_state);
+       }
+
+       return (AE_OK);
+
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_load2_begin_op
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *              Op              - Op that has been just been reached in the
+ *                                walk;  Arguments have not been evaluated yet.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Descending callback used during the loading of ACPI tables.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_load2_begin_op (
+       u16                     opcode,
+       ACPI_PARSE_OBJECT       *op,
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       **out_op)
+{
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_STATUS             status;
+       OBJECT_TYPE_INTERNAL    data_type;
+       NATIVE_CHAR             *buffer_ptr;
+       void                    *original = NULL;
+
+
+       /* We only care about Namespace opcodes here */
+
+       if (!acpi_ps_is_namespace_op (opcode) &&
+               opcode != AML_NAMEPATH_OP) {
+               return (AE_OK);
+       }
+
+
+       /* Temp! same code as in psparse */
+
+       if (!acpi_ps_is_named_op (opcode)) {
+               return (AE_OK);
+       }
+
+       if (op) {
+               /*
+                * Get the name we are going to enter or lookup in the namespace
+                */
+               if (opcode == AML_NAMEPATH_OP) {
+                       /* For Namepath op, get the path string */
+
+                       buffer_ptr = op->value.string;
+                       if (!buffer_ptr) {
+                               /* No name, just exit */
+
+                               return (AE_OK);
+                       }
+               }
+
+               else {
+                       /* Get name from the op */
+
+                       buffer_ptr = (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)op)->name;
+               }
+       }
+
+       else {
+               buffer_ptr = acpi_ps_get_next_namestring (walk_state->parser_state);
+       }
+
+
+       /* Map the raw opcode into an internal object type */
+
+       data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
+
+
+       if (opcode == AML_DEF_FIELD_OP      ||
+               opcode == AML_BANK_FIELD_OP     ||
+               opcode == AML_INDEX_FIELD_OP) {
+               node = NULL;
+               status = AE_OK;
+       }
+
+       else if (opcode == AML_NAMEPATH_OP) {
+               /*
+                * The Name_path is an object reference to an existing object. Don't enter the
+                * name into the namespace, but look it up for use later
+                */
+               status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr,
+                                data_type, IMODE_EXECUTE,
+                                NS_SEARCH_PARENT, walk_state,
+                                &(node));
+       }
+
+       else {
+               if (op && op->node) {
+                       original = op->node;
+                       node = op->node;
+
+                       if (acpi_ns_opens_scope (data_type)) {
+                               status = acpi_ds_scope_stack_push (node,
+                                                  data_type,
+                                                  walk_state);
+                               if (ACPI_FAILURE (status)) {
+                                       return (status);
+                               }
+
+                       }
+                       return (AE_OK);
+               }
+
+               /*
+                * Enter the named type into the internal namespace.  We enter the name
+                * as we go downward in the parse tree.  Any necessary subobjects that involve
+                * arguments to the opcode must be created as we go back up the parse tree later.
+                */
+               status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr,
+                                data_type, IMODE_EXECUTE,
+                                NS_NO_UPSEARCH, walk_state,
+                                &(node));
+       }
+
+       if (ACPI_SUCCESS (status)) {
+               if (!op) {
+                       /* Create a new op */
+
+                       op = acpi_ps_alloc_op (opcode);
+                       if (!op) {
+                               return (AE_NO_MEMORY);
+                       }
+
+                       /* Initialize */
+
+                       ((ACPI_PARSE2_OBJECT *)op)->name = node->name;
+                       *out_op = op;
+               }
+
+
+               /*
+                * Put the Node in the "op" object that the parser uses, so we
+                * can get it again quickly when this scope is closed
+                */
+               op->node = node;
+
+       }
+
+
+       return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_load2_end_op
+ *
+ * PARAMETERS:  Walk_state      - Current state of the parse tree walk
+ *              Op              - Op that has been just been completed in the
+ *                                walk;  Arguments have now been evaluated.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Ascending callback used during the loading of the namespace,
+ *              both control methods and everything else.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_load2_end_op (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_PARSE_OBJECT       *op)
+{
+       ACPI_STATUS             status = AE_OK;
+       OBJECT_TYPE_INTERNAL    data_type;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_PARSE_OBJECT       *arg;
+       ACPI_NAMESPACE_NODE     *new_node;
+
+
+       if (!acpi_ps_is_namespace_object_op (op->opcode)) {
+               return (AE_OK);
+       }
+
+       if (op->opcode == AML_SCOPE_OP) {
+               if (((ACPI_PARSE2_OBJECT *)op)->name == -1) {
+                       return (AE_OK);
+               }
+       }
+
+
+       data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
+
+       /*
+        * Get the Node/name from the earlier lookup
+        * (It was saved in the *op structure)
+        */
+       node = op->node;
+
+       /*
+        * Put the Node on the object stack (Contains the ACPI Name of
+        * this object)
+        */
+
+       walk_state->operands[0] = (void *) node;
+       walk_state->num_operands = 1;
+
+       /* Pop the scope stack */
+
+       if (acpi_ns_opens_scope (data_type)) {
+
+               acpi_ds_scope_stack_pop (walk_state);
+       }
+
+
+       /*
+        * Named operations are as follows:
+        *
+        * AML_SCOPE
+        * AML_DEVICE
+        * AML_THERMALZONE
+        * AML_METHOD
+        * AML_POWERRES
+        * AML_PROCESSOR
+        * AML_FIELD
+        * AML_INDEXFIELD
+        * AML_BANKFIELD
+        * AML_NAMEDFIELD
+        * AML_NAME
+        * AML_ALIAS
+        * AML_MUTEX
+        * AML_EVENT
+        * AML_OPREGION
+        * AML_CREATEFIELD
+        * AML_CREATEBITFIELD
+        * AML_CREATEBYTEFIELD
+        * AML_CREATEWORDFIELD
+        * AML_CREATEDWORDFIELD
+        * AML_METHODCALL
+        */
+
+
+       /* Decode the opcode */
+
+       arg = op->value.arg;
+
+       switch (op->opcode) {
+
+       case AML_CREATE_FIELD_OP:
+       case AML_BIT_FIELD_OP:
+       case AML_BYTE_FIELD_OP:
+       case AML_WORD_FIELD_OP:
+       case AML_DWORD_FIELD_OP:
+
+               /*
+                * Create the field object, but the field buffer and index must
+                * be evaluated later during the execution phase
+                */
+
+               /* Get the Name_string argument */
+
+               if (op->opcode == AML_CREATE_FIELD_OP) {
+                       arg = acpi_ps_get_arg (op, 3);
+               }
+               else {
+                       /* Create Bit/Byte/Word/Dword field */
+
+                       arg = acpi_ps_get_arg (op, 2);
+               }
+
+               /*
+                * Enter the Name_string into the namespace
+                */
+
+               status = acpi_ns_lookup (walk_state->scope_info,
+                                arg->value.string,
+                                INTERNAL_TYPE_DEF_ANY,
+                                IMODE_LOAD_PASS1,
+                                NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+                                walk_state, &(new_node));
+
+               if (ACPI_SUCCESS (status)) {
+                       /* We could put the returned object (Node) on the object stack for later, but
+                        * for now, we will put it in the "op" object that the parser uses, so we
+                        * can get it again at the end of this scope
+                        */
+                       op->node = new_node;
+
+                       /*
+                        * If there is no object attached to the node, this node was just created and
+                        * we need to create the field object.  Otherwise, this was a lookup of an
+                        * existing node and we don't want to create the field object again.
+                        */
+                       if (!new_node->object) {
+                               /*
+                                * The Field definition is not fully parsed at this time.
+                                * (We must save the address of the AML for the buffer and index operands)
+                                */
+                               status = acpi_aml_exec_create_field (((ACPI_PARSE2_OBJECT *) op)->data,
+                                                  ((ACPI_PARSE2_OBJECT *) op)->length,
+                                                  new_node, walk_state);
+                       }
+               }
+
+
+               break;
+
+
+       case AML_METHODCALL_OP:
+
+               /*
+                * Lookup the method name and save the Node
+                */
+
+               status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
+                                ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
+                                NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
+                                walk_state, &(new_node));
+
+               if (ACPI_SUCCESS (status)) {
+
+/* has name already been resolved by here ??*/
+
+                       /* TBD: [Restructure] Make sure that what we found is indeed a method! */
+                       /* We didn't search for a method on purpose, to see if the name would resolve! */
+
+                       /* We could put the returned object (Node) on the object stack for later, but
+                        * for now, we will put it in the "op" object that the parser uses, so we
+                        * can get it again at the end of this scope
+                        */
+                       op->node = new_node;
+               }
+
+
+                break;
+
+
+       case AML_PROCESSOR_OP:
+
+               /* Nothing to do other than enter object into namespace */
+
+               status = acpi_aml_exec_create_processor (op, (ACPI_HANDLE) node);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               break;
+
+
+       case AML_POWER_RES_OP:
+
+               /* Nothing to do other than enter object into namespace */
+
+               status = acpi_aml_exec_create_power_resource (op, (ACPI_HANDLE) node);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               break;
+
+
+       case AML_THERMAL_ZONE_OP:
+
+               /* Nothing to do other than enter object into namespace */
+
+               break;
+
+
+       case AML_DEF_FIELD_OP:
+
+               arg = op->value.arg;
+
+               status = acpi_ds_create_field (op, arg->node, walk_state);
+               break;
+
+
+       case AML_INDEX_FIELD_OP:
+
+               arg = op->value.arg;
+
+               status = acpi_ds_create_index_field (op, (ACPI_HANDLE) arg->node,
+                                  walk_state);
+               break;
+
+
+       case AML_BANK_FIELD_OP:
+
+               arg = op->value.arg;
+               status = acpi_ds_create_bank_field (op, arg->node, walk_state);
+               break;
+
+
+       /*
+        * Method_op Pkg_length Names_string Method_flags Term_list
+        */
+       case AML_METHOD_OP:
+
+               if (!node->object) {
+                       status = acpi_aml_exec_create_method (((ACPI_PARSE2_OBJECT *) op)->data,
+                                          ((ACPI_PARSE2_OBJECT *) op)->length,
+                                          arg->value.integer, (ACPI_HANDLE) node);
+               }
+
+               break;
+
+
+       case AML_MUTEX_OP:
+
+               status = acpi_ds_create_operands (walk_state, arg);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               status = acpi_aml_exec_create_mutex (walk_state);
+               break;
+
+
+       case AML_EVENT_OP:
+
+               status = acpi_ds_create_operands (walk_state, arg);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               status = acpi_aml_exec_create_event (walk_state);
+               break;
+
+
+       case AML_REGION_OP:
+
+               if (node->object) {
+                       break;
+               }
+
+
+               /*
+                * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
+                * (We must save the address of the AML of the address and length operands)
+                */
+
+               status = acpi_aml_exec_create_region (((ACPI_PARSE2_OBJECT *) op)->data,
+                                  ((ACPI_PARSE2_OBJECT *) op)->length,
+                                  (ACPI_ADDRESS_SPACE_TYPE) arg->value.integer,
+                                  walk_state);
+
+               break;
+
+
+       /* Namespace Modifier Opcodes */
+
+       case AML_ALIAS_OP:
+
+               status = acpi_ds_create_operands (walk_state, arg);
+               if (ACPI_FAILURE (status)) {
+                       goto cleanup;
+               }
+
+               status = acpi_aml_exec_create_alias (walk_state);
+               break;
+
+
+       case AML_NAME_OP:
+
+               /*
+                * Because of the execution pass through the non-control-method
+                * parts of the table, we can arrive here twice.  Only init
+                * the named object node the first time through
+                */
+
+               if (!node->object) {
+                       status = acpi_ds_create_node (walk_state, node, op);
+               }
+
+               break;
+
+
+       case AML_NAMEPATH_OP:
+
+               break;
+
+
+       default:
+               break;
+       }
+
+
+cleanup:
+
+       /* Remove the Node pushed at the very beginning */
+
+       acpi_ds_obj_stack_pop (1, walk_state);
+       return (status);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dswscope.c b/reactos/drivers/bus/acpi/dispatcher/dswscope.c
new file mode 100644 (file)
index 0000000..9813df5
--- /dev/null
@@ -0,0 +1,161 @@
+/******************************************************************************
+ *
+ * Module Name: dswscope - Scope stack manipulation
+ *              $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"
+#include "acinterp.h"
+#include "acdispat.h"
+
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dswscope")
+
+
+#define STACK_POP(head) head
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_scope_stack_clear
+ *
+ * PARAMETERS:  None
+ *
+ * DESCRIPTION: Pop (and free) everything on the scope stack except the
+ *              root scope object (which remains at the stack top.)
+ *
+ ***************************************************************************/
+
+void
+acpi_ds_scope_stack_clear (
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *scope_info;
+
+
+       while (walk_state->scope_info) {
+               /* Pop a scope off the stack */
+
+               scope_info = walk_state->scope_info;
+               walk_state->scope_info = scope_info->scope.next;
+
+               acpi_cm_delete_generic_state (scope_info);
+       }
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_scope_stack_push
+ *
+ * PARAMETERS:  *Node,              - Name to be made current
+ *              Type,               - Type of frame being pushed
+ *
+ * DESCRIPTION: Push the current scope on the scope stack, and make the
+ *              passed Node current.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ds_scope_stack_push (
+       ACPI_NAMESPACE_NODE     *node,
+       OBJECT_TYPE_INTERNAL    type,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *scope_info;
+
+
+       if (!node) {
+               /*  invalid scope   */
+
+               REPORT_ERROR (("Ds_scope_stack_push: null scope passed\n"));
+               return (AE_BAD_PARAMETER);
+       }
+
+       /* Make sure object type is valid */
+
+       if (!acpi_aml_validate_object_type (type)) {
+               REPORT_WARNING (("Ds_scope_stack_push: type code out of range\n"));
+       }
+
+
+       /* Allocate a new scope object */
+
+       scope_info = acpi_cm_create_generic_state ();
+       if (!scope_info) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* Init new scope object */
+
+       scope_info->scope.node = node;
+       scope_info->common.value = (u16) type;
+
+       /* Push new scope object onto stack */
+
+       acpi_cm_push_generic_state (&walk_state->scope_info, scope_info);
+
+       return (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_scope_stack_pop
+ *
+ * PARAMETERS:  Type                - The type of frame to be found
+ *
+ * DESCRIPTION: Pop the scope stack until a frame of the requested type
+ *              is found.
+ *
+ * RETURN:      Count of frames popped.  If no frame of the requested type
+ *              was found, the count is returned as a negative number and
+ *              the scope stack is emptied (which sets the current scope
+ *              to the root).  If the scope stack was empty at entry, the
+ *              function is a no-op and returns 0.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ds_scope_stack_pop (
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *scope_info;
+
+
+       /*
+        * Pop scope info object off the stack.
+        */
+
+       scope_info = acpi_cm_pop_generic_state (&walk_state->scope_info);
+       if (!scope_info) {
+               return (AE_STACK_UNDERFLOW);
+       }
+
+       acpi_cm_delete_generic_state (scope_info);
+
+       return (AE_OK);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/dispatcher/dswstate.c b/reactos/drivers/bus/acpi/dispatcher/dswstate.c
new file mode 100644 (file)
index 0000000..99632f0
--- /dev/null
@@ -0,0 +1,877 @@
+/******************************************************************************
+ *
+ * Module Name: dswstate - Dispatcher parse tree walk management routines
+ *              $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"
+#include "amlcode.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+        MODULE_NAME         ("dswstate")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_insert
+ *
+ * PARAMETERS:  Object              - Object to push
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Push an object onto this walk's result stack
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_insert (
+       void                    *object,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *state;
+
+
+       state = walk_state->results;
+       if (!state) {
+               return (AE_NOT_EXIST);
+       }
+
+       if (index >= OBJ_NUM_OPERANDS) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       if (!object) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       state->results.obj_desc [index] = object;
+       state->results.num_results++;
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_remove
+ *
+ * PARAMETERS:  Object              - Where to return the popped object
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
+ *              other words, this is a FIFO.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_remove (
+       ACPI_OPERAND_OBJECT     **object,
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *state;
+
+
+       state = walk_state->results;
+       if (!state) {
+               return (AE_NOT_EXIST);
+       }
+
+
+
+       /* Check for a valid result object */
+
+       if (!state->results.obj_desc [index]) {
+               return (AE_AML_NO_RETURN_VALUE);
+       }
+
+       /* Remove the object */
+
+       state->results.num_results--;
+
+       *object = state->results.obj_desc [index];
+       state->results.obj_desc [index] = NULL;
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_pop
+ *
+ * PARAMETERS:  Object              - Where to return the popped object
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
+ *              other words, this is a FIFO.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_pop (
+       ACPI_OPERAND_OBJECT     **object,
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     index;
+       ACPI_GENERIC_STATE      *state;
+
+
+       state = walk_state->results;
+       if (!state) {
+               return (AE_OK);
+       }
+
+
+       if (!state->results.num_results) {
+               return (AE_AML_NO_RETURN_VALUE);
+       }
+
+       /* Remove top element */
+
+       state->results.num_results--;
+
+       for (index = OBJ_NUM_OPERANDS; index; index--) {
+               /* Check for a valid result object */
+
+               if (state->results.obj_desc [index -1]) {
+                       *object = state->results.obj_desc [index -1];
+                       state->results.obj_desc [index -1] = NULL;
+
+                       return (AE_OK);
+               }
+       }
+
+
+       return (AE_AML_NO_RETURN_VALUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_pop_from_bottom
+ *
+ * PARAMETERS:  Object              - Where to return the popped object
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Pop an object off the bottom of this walk's result stack.  In
+ *              other words, this is a FIFO.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_pop_from_bottom (
+       ACPI_OPERAND_OBJECT     **object,
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     index;
+       ACPI_GENERIC_STATE      *state;
+
+
+       state = walk_state->results;
+       if (!state) {
+               return (AE_NOT_EXIST);
+       }
+
+
+       if (!state->results.num_results) {
+               return (AE_AML_NO_RETURN_VALUE);
+       }
+
+       /* Remove Bottom element */
+
+       *object = state->results.obj_desc [0];
+
+
+       /* Push entire stack down one element */
+
+       for (index = 0; index < state->results.num_results; index++) {
+               state->results.obj_desc [index] = state->results.obj_desc [index + 1];
+       }
+
+       state->results.num_results--;
+
+       /* Check for a valid result object */
+
+       if (!*object) {
+               return (AE_AML_NO_RETURN_VALUE);
+       }
+
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_push
+ *
+ * PARAMETERS:  Object              - Where to return the popped object
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Push an object onto the current result stack
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_push (
+       ACPI_OPERAND_OBJECT     *object,
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *state;
+
+
+       state = walk_state->results;
+       if (!state) {
+               return (AE_AML_INTERNAL);
+       }
+
+       if (state->results.num_results == OBJ_NUM_OPERANDS) {
+               return (AE_STACK_OVERFLOW);
+       }
+
+       if (!object) {
+               return (AE_BAD_PARAMETER);
+       }
+
+
+       state->results.obj_desc [state->results.num_results] = object;
+       state->results.num_results++;
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_stack_push
+ *
+ * PARAMETERS:  Object              - Object to push
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_stack_push (
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *state;
+
+
+       state = acpi_cm_create_generic_state ();
+       if (!state) {
+               return (AE_NO_MEMORY);
+       }
+
+       acpi_cm_push_generic_state (&walk_state->results, state);
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_result_stack_pop
+ *
+ * PARAMETERS:  Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_result_stack_pop (
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *state;
+
+
+       /* Check for stack underflow */
+
+       if (walk_state->results == NULL) {
+               return (AE_AML_NO_OPERAND);
+       }
+
+
+       state = acpi_cm_pop_generic_state (&walk_state->results);
+
+       acpi_cm_delete_generic_state (state);
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_obj_stack_delete_all
+ *
+ * PARAMETERS:  Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
+ *              Should be used with great care, if at all!
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_obj_stack_delete_all (
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     i;
+
+
+       /* The stack size is configurable, but fixed */
+
+       for (i = 0; i < OBJ_NUM_OPERANDS; i++) {
+               if (walk_state->operands[i]) {
+                       acpi_cm_remove_reference (walk_state->operands[i]);
+                       walk_state->operands[i] = NULL;
+               }
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_obj_stack_push
+ *
+ * PARAMETERS:  Object              - Object to push
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Push an object onto this walk's object/operand stack
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_obj_stack_push (
+       void                    *object,
+       ACPI_WALK_STATE         *walk_state)
+{
+
+
+       /* Check for stack overflow */
+
+       if (walk_state->num_operands >= OBJ_NUM_OPERANDS) {
+               return (AE_STACK_OVERFLOW);
+       }
+
+       /* Put the object onto the stack */
+
+       walk_state->operands [walk_state->num_operands] = object;
+       walk_state->num_operands++;
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_obj_stack_pop_object
+ *
+ * PARAMETERS:  Pop_count           - Number of objects/entries to pop
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
+ *              deleted by this routine.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_obj_stack_pop_object (
+       ACPI_OPERAND_OBJECT     **object,
+       ACPI_WALK_STATE         *walk_state)
+{
+
+
+       /* Check for stack underflow */
+
+       if (walk_state->num_operands == 0) {
+               return (AE_AML_NO_OPERAND);
+       }
+
+
+       /* Pop the stack */
+
+       walk_state->num_operands--;
+
+       /* Check for a valid operand */
+
+       if (!walk_state->operands [walk_state->num_operands]) {
+               return (AE_AML_NO_OPERAND);
+       }
+
+       /* Get operand and set stack entry to null */
+
+       *object = walk_state->operands [walk_state->num_operands];
+       walk_state->operands [walk_state->num_operands] = NULL;
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_obj_stack_pop
+ *
+ * PARAMETERS:  Pop_count           - Number of objects/entries to pop
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
+ *              deleted by this routine.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_obj_stack_pop (
+       u32                     pop_count,
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     i;
+
+
+       for (i = 0; i < pop_count; i++) {
+               /* Check for stack underflow */
+
+               if (walk_state->num_operands == 0) {
+                       return (AE_STACK_UNDERFLOW);
+               }
+
+               /* Just set the stack entry to null */
+
+               walk_state->num_operands--;
+               walk_state->operands [walk_state->num_operands] = NULL;
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_obj_stack_pop_and_delete
+ *
+ * PARAMETERS:  Pop_count           - Number of objects/entries to pop
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Pop this walk's object stack and delete each object that is
+ *              popped off.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_obj_stack_pop_and_delete (
+       u32                     pop_count,
+       ACPI_WALK_STATE         *walk_state)
+{
+       u32                     i;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+
+
+       for (i = 0; i < pop_count; i++) {
+               /* Check for stack underflow */
+
+               if (walk_state->num_operands == 0) {
+                       return (AE_STACK_UNDERFLOW);
+               }
+
+               /* Pop the stack and delete an object if present in this stack entry */
+
+               walk_state->num_operands--;
+               obj_desc = walk_state->operands [walk_state->num_operands];
+               if (obj_desc) {
+                       acpi_cm_remove_reference (walk_state->operands [walk_state->num_operands]);
+                       walk_state->operands [walk_state->num_operands] = NULL;
+               }
+       }
+
+       return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_obj_stack_get_value
+ *
+ * PARAMETERS:  Index               - Stack index whose value is desired.  Based
+ *                                    on the top of the stack (index=0 == top)
+ *              Walk_state          - Current Walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Retrieve an object from this walk's object stack.  Index must
+ *              be within the range of the current stack pointer.
+ *
+ ******************************************************************************/
+
+void *
+acpi_ds_obj_stack_get_value (
+       u32                     index,
+       ACPI_WALK_STATE         *walk_state)
+{
+
+
+       /* Can't do it if the stack is empty */
+
+       if (walk_state->num_operands == 0) {
+               return (NULL);
+       }
+
+       /* or if the index is past the top of the stack */
+
+       if (index > (walk_state->num_operands - (u32) 1)) {
+               return (NULL);
+       }
+
+
+       return (walk_state->operands[(NATIVE_UINT)(walk_state->num_operands - 1) -
+                         index]);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_get_current_walk_state
+ *
+ * PARAMETERS:  Walk_list       - Get current active state for this walk list
+ *
+ * RETURN:      Pointer to the current walk state
+ *
+ * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
+ *              walk state.
+ *
+ ******************************************************************************/
+
+ACPI_WALK_STATE *
+acpi_ds_get_current_walk_state (
+       ACPI_WALK_LIST          *walk_list)
+
+{
+
+       if (!walk_list) {
+               return (NULL);
+       }
+
+       return (walk_list->walk_state);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_push_walk_state
+ *
+ * PARAMETERS:  Walk_state      - State to push
+ *              Walk_list       - The list that owns the walk stack
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Place the Walk_state at the head of the state list.
+ *
+ ******************************************************************************/
+
+static void
+acpi_ds_push_walk_state (
+       ACPI_WALK_STATE         *walk_state,
+       ACPI_WALK_LIST          *walk_list)
+{
+
+
+       walk_state->next    = walk_list->walk_state;
+       walk_list->walk_state = walk_state;
+
+       return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_pop_walk_state
+ *
+ * PARAMETERS:  Walk_list       - The list that owns the walk stack
+ *
+ * RETURN:      A Walk_state object popped from the stack
+ *
+ * DESCRIPTION: Remove and return the walkstate object that is at the head of
+ *              the walk stack for the given walk list.  NULL indicates that
+ *              the list is empty.
+ *
+ ******************************************************************************/
+
+ACPI_WALK_STATE *
+acpi_ds_pop_walk_state (
+       ACPI_WALK_LIST          *walk_list)
+{
+       ACPI_WALK_STATE         *walk_state;
+
+
+       walk_state = walk_list->walk_state;
+
+       if (walk_state) {
+               /* Next walk state becomes the current walk state */
+
+               walk_list->walk_state = walk_state->next;
+
+               /*
+                * Don't clear the NEXT field, this serves as an indicator
+                * that there is a parent WALK STATE
+                *     Walk_state->Next = NULL;
+                */
+       }
+
+       return (walk_state);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_walk_state
+ *
+ * PARAMETERS:  Origin          - Starting point for this walk
+ *              Walk_list       - Owning walk list
+ *
+ * RETURN:      Pointer to the new walk state.
+ *
+ * DESCRIPTION: Allocate and initialize a new walk state.  The current walk state
+ *              is set to this new state.
+ *
+ ******************************************************************************/
+
+ACPI_WALK_STATE *
+acpi_ds_create_walk_state (
+       ACPI_OWNER_ID           owner_id,
+       ACPI_PARSE_OBJECT       *origin,
+       ACPI_OPERAND_OBJECT     *mth_desc,
+       ACPI_WALK_LIST          *walk_list)
+{
+       ACPI_WALK_STATE         *walk_state;
+       ACPI_STATUS             status;
+
+
+       acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
+       acpi_gbl_walk_state_cache_requests++;
+
+       /* Check the cache first */
+
+       if (acpi_gbl_walk_state_cache) {
+               /* There is an object available, use it */
+
+               walk_state = acpi_gbl_walk_state_cache;
+               acpi_gbl_walk_state_cache = walk_state->next;
+
+               acpi_gbl_walk_state_cache_hits++;
+               acpi_gbl_walk_state_cache_depth--;
+
+               acpi_cm_release_mutex (ACPI_MTX_CACHES);
+       }
+
+       else {
+               /* The cache is empty, create a new object */
+
+               /* Avoid deadlock with Acpi_cm_callocate */
+
+               acpi_cm_release_mutex (ACPI_MTX_CACHES);
+
+               walk_state = acpi_cm_callocate (sizeof (ACPI_WALK_STATE));
+               if (!walk_state) {
+                       return (NULL);
+               }
+       }
+
+       walk_state->data_type       = ACPI_DESC_TYPE_WALK;
+       walk_state->owner_id        = owner_id;
+       walk_state->origin          = origin;
+       walk_state->method_desc     = mth_desc;
+       walk_state->walk_list       = walk_list;
+
+       /* Init the method args/local */
+
+#ifndef _ACPI_ASL_COMPILER
+       acpi_ds_method_data_init (walk_state);
+#endif
+
+       /* Create an initial result stack entry */
+
+       status = acpi_ds_result_stack_push (walk_state);
+       if (ACPI_FAILURE (status)) {
+               return (NULL);
+       }
+
+
+       /* Put the new state at the head of the walk list */
+
+       acpi_ds_push_walk_state (walk_state, walk_list);
+
+       return (walk_state);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_delete_walk_state
+ *
+ * PARAMETERS:  Walk_state      - State to delete
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Delete a walk state including all internal data structures
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_delete_walk_state (
+       ACPI_WALK_STATE         *walk_state)
+{
+       ACPI_GENERIC_STATE      *state;
+
+
+       if (!walk_state) {
+               return;
+       }
+
+       if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
+               return;
+       }
+
+
+       /* Always must free any linked control states */
+
+       while (walk_state->control_state) {
+               state = walk_state->control_state;
+               walk_state->control_state = state->common.next;
+
+               acpi_cm_delete_generic_state (state);
+       }
+
+       /* Always must free any linked parse states */
+
+       while (walk_state->scope_info) {
+               state = walk_state->scope_info;
+               walk_state->scope_info = state->common.next;
+
+               acpi_cm_delete_generic_state (state);
+       }
+
+       /* Always must free any stacked result states */
+
+       while (walk_state->results) {
+               state = walk_state->results;
+               walk_state->results = state->common.next;
+
+               acpi_cm_delete_generic_state (state);
+       }
+
+
+       /* If walk cache is full, just free this wallkstate object */
+
+       if (acpi_gbl_walk_state_cache_depth >= MAX_WALK_CACHE_DEPTH) {
+               acpi_cm_free (walk_state);
+       }
+
+       /* Otherwise put this object back into the cache */
+
+       else {
+               acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
+
+               /* Clear the state */
+
+               MEMSET (walk_state, 0, sizeof (ACPI_WALK_STATE));
+               walk_state->data_type = ACPI_DESC_TYPE_WALK;
+
+               /* Put the object at the head of the global cache list */
+
+               walk_state->next = acpi_gbl_walk_state_cache;
+               acpi_gbl_walk_state_cache = walk_state;
+               acpi_gbl_walk_state_cache_depth++;
+
+
+               acpi_cm_release_mutex (ACPI_MTX_CACHES);
+       }
+
+       return;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_delete_walk_state_cache
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Purge the global state object cache.  Used during subsystem
+ *              termination.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_delete_walk_state_cache (
+       void)
+{
+       ACPI_WALK_STATE         *next;
+
+
+       /* Traverse the global cache list */
+
+       while (acpi_gbl_walk_state_cache) {
+               /* Delete one cached state object */
+
+               next = acpi_gbl_walk_state_cache->next;
+               acpi_cm_free (acpi_gbl_walk_state_cache);
+               acpi_gbl_walk_state_cache = next;
+               acpi_gbl_walk_state_cache_depth--;
+       }
+
+       return;
+}
+
+
diff --git a/reactos/drivers/bus/acpi/events/evevent.c b/reactos/drivers/bus/acpi/events/evevent.c
new file mode 100644 (file)
index 0000000..319a2d3
--- /dev/null
@@ -0,0 +1,769 @@
+/******************************************************************************
+ *
+ * Module Name: evevent - Fixed and General Purpose Acpi_event
+ *                          handling and dispatch
+ *              $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"
+#include "achware.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_EVENTS
+        MODULE_NAME         ("evevent")
+
+
+/**************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_initialize
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly
+ *              configured, disables SCI event sources, installs the SCI
+ *              handler
+ *
+ *************************************************************************/
+
+ACPI_STATUS
+acpi_ev_initialize (
+       void)
+{
+       ACPI_STATUS             status;
+
+
+       /* Make sure we have ACPI tables */
+
+       if (!acpi_gbl_DSDT) {
+               return (AE_NO_ACPI_TABLES);
+       }
+
+
+       /* Make sure the BIOS supports ACPI mode */
+
+       if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) {
+               return (AE_ERROR);
+       }
+
+
+       acpi_gbl_original_mode = acpi_hw_get_mode();
+
+       /*
+        * Initialize the Fixed and General Purpose Acpi_events prior. This is
+        * done prior to enabling SCIs to prevent interrupts from occuring
+        * before handers are installed.
+        */
+
+       status = acpi_ev_fixed_event_initialize ();
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       status = acpi_ev_gpe_initialize ();
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Install the SCI handler */
+
+       status = acpi_ev_install_sci_handler ();
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+
+       /* Install handlers for control method GPE handlers (_Lxx, _Exx) */
+
+       status = acpi_ev_init_gpe_control_methods ();
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Install the handler for the Global Lock */
+
+       status = acpi_ev_init_global_lock_handler ();
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+
+       return (status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_fixed_event_initialize
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize the Fixed Acpi_event data structures
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ev_fixed_event_initialize(void)
+{
+       int                     i = 0;
+
+       /* Initialize the structure that keeps track of fixed event handlers */
+
+       for (i = 0; i < NUM_FIXED_EVENTS; i++) {
+               acpi_gbl_fixed_event_handlers[i].handler = NULL;
+               acpi_gbl_fixed_event_handlers[i].context = NULL;
+       }
+
+       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0);
+       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0);
+       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0);
+       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0);
+       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0);
+
+       return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_fixed_event_detect
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
+ *
+ * DESCRIPTION: Checks the PM status register for fixed events
+ *
+ ******************************************************************************/
+
+u32
+acpi_ev_fixed_event_detect(void)
+{
+       u32                     int_status = INTERRUPT_NOT_HANDLED;
+       u32                     status_register;
+       u32                     enable_register;
+
+       /*
+        * Read the fixed feature status and enable registers, as all the cases
+        * depend on their values.
+        */
+
+       status_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
+       enable_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
+
+
+       /* power management timer roll over */
+
+       if ((status_register & ACPI_STATUS_PMTIMER) &&
+               (enable_register & ACPI_ENABLE_PMTIMER)) {
+               int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER);
+       }
+
+       /* global event (BIOS want's the global lock) */
+
+       if ((status_register & ACPI_STATUS_GLOBAL) &&
+               (enable_register & ACPI_ENABLE_GLOBAL)) {
+               int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL);
+       }
+
+       /* power button event */
+
+       if ((status_register & ACPI_STATUS_POWER_BUTTON) &&
+               (enable_register & ACPI_ENABLE_POWER_BUTTON)) {
+               int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON);
+       }
+
+       /* sleep button event */
+
+       if ((status_register & ACPI_STATUS_SLEEP_BUTTON) &&
+               (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) {
+               int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON);
+       }
+
+       return (int_status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_fixed_event_dispatch
+ *
+ * PARAMETERS:  Event               - Event type
+ *
+ * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
+ *
+ * DESCRIPTION: Clears the status bit for the requested event, calls the
+ *              handler that previously registered for the event.
+ *
+ ******************************************************************************/
+
+u32
+acpi_ev_fixed_event_dispatch (
+       u32                     event)
+{
+       u32 register_id;
+
+       /* Clear the status bit */
+
+       switch (event) {
+       case ACPI_EVENT_PMTIMER:
+               register_id = TMR_STS;
+               break;
+
+       case ACPI_EVENT_GLOBAL:
+               register_id = GBL_STS;
+               break;
+
+       case ACPI_EVENT_POWER_BUTTON:
+               register_id = PWRBTN_STS;
+               break;
+
+       case ACPI_EVENT_SLEEP_BUTTON:
+               register_id = SLPBTN_STS;
+               break;
+
+       case ACPI_EVENT_RTC:
+               register_id = RTC_STS;
+               break;
+
+       default:
+               return 0;
+               break;
+       }
+
+       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 1);
+
+       /*
+        * Make sure we've got a handler.  If not, report an error.
+        * The event is disabled to prevent further interrupts.
+        */
+       if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
+               register_id = (PM1_EN | REGISTER_BIT_ID(register_id));
+
+               acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,
+                                register_id, 0);
+
+               REPORT_ERROR (
+                       ("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n",
+                       event));
+
+               return (INTERRUPT_NOT_HANDLED);
+       }
+
+       /* Invoke the handler */
+
+       return ((acpi_gbl_fixed_event_handlers[event].handler)(
+                         acpi_gbl_fixed_event_handlers[event].context));
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_gpe_initialize
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize the GPE data structures
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ev_gpe_initialize (void)
+{
+       u32                     i;
+       u32                     j;
+       u32                     register_index;
+       u32                     gpe_number;
+       u16                     gpe0register_count;
+       u16                     gpe1_register_count;
+
+
+       /*
+        * Set up various GPE counts
+        *
+        * You may ask,why are the GPE register block lengths divided by 2?
+        * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event
+        * Registers, we have,
+        *
+        * "Each register block contains two registers of equal length
+        * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
+        * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
+        * The length of the GPE1_STS and GPE1_EN registers is equal to
+        * half the GPE1_LEN. If a generic register block is not supported
+        * then its respective block pointer and block length values in the
+        * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
+        * to be the same size."
+        */
+
+       gpe0register_count          = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len);
+       gpe1_register_count         = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
+       acpi_gbl_gpe_register_count = gpe0register_count + gpe1_register_count;
+
+       if (!acpi_gbl_gpe_register_count) {
+               REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
+               return (AE_OK);
+       }
+
+       /*
+        * Allocate the Gpe information block
+        */
+
+       acpi_gbl_gpe_registers = acpi_cm_callocate (acpi_gbl_gpe_register_count *
+                        sizeof (ACPI_GPE_REGISTERS));
+       if (!acpi_gbl_gpe_registers) {
+               return (AE_NO_MEMORY);
+       }
+
+       /*
+        * Allocate the Gpe dispatch handler block
+        * There are eight distinct GP events per register.
+        * Initialization to zeros is sufficient
+        */
+
+       acpi_gbl_gpe_info = acpi_cm_callocate (MUL_8 (acpi_gbl_gpe_register_count) *
+                        sizeof (ACPI_GPE_LEVEL_INFO));
+       if (!acpi_gbl_gpe_info) {
+               acpi_cm_free (acpi_gbl_gpe_registers);
+               return (AE_NO_MEMORY);
+       }
+
+       /* Set the Gpe validation table to GPE_INVALID */
+
+       MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, NUM_GPE);
+
+       /*
+        * Initialize the Gpe information and validation blocks.  A goal of these
+        * blocks is to hide the fact that there are two separate GPE register sets
+        * In a given block, the status registers occupy the first half, and
+        * the enable registers occupy the second half.
+        */
+
+       /* GPE Block 0 */
+
+       register_index = 0;
+
+       for (i = 0; i < gpe0register_count; i++) {
+               acpi_gbl_gpe_registers[register_index].status_addr =
+                                (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i);
+
+               acpi_gbl_gpe_registers[register_index].enable_addr =
+                                (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i + gpe0register_count);
+
+               acpi_gbl_gpe_registers[register_index].gpe_base = (u8) MUL_8 (i);
+
+               for (j = 0; j < 8; j++) {
+                       gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j;
+                       acpi_gbl_gpe_valid[gpe_number] = (u8) register_index;
+               }
+
+               /*
+                * Clear the status/enable registers.  Note that status registers
+                * are cleared by writing a '1', while enable registers are cleared
+                * by writing a '0'.
+                */
+               acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00);
+               acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF);
+
+               register_index++;
+       }
+
+       /* GPE Block 1 */
+
+       for (i = 0; i < gpe1_register_count; i++) {
+               acpi_gbl_gpe_registers[register_index].status_addr =
+                                (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i);
+
+               acpi_gbl_gpe_registers[register_index].enable_addr =
+                                (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i + gpe1_register_count);
+
+               acpi_gbl_gpe_registers[register_index].gpe_base =
+                                (u8) (acpi_gbl_FADT->gpe1_base + MUL_8 (i));
+
+               for (j = 0; j < 8; j++) {
+                       gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j;
+                       acpi_gbl_gpe_valid[gpe_number] = (u8) register_index;
+               }
+
+               /*
+                * Clear the status/enable registers.  Note that status registers
+                * are cleared by writing a '1', while enable registers are cleared
+                * by writing a '0'.
+                */
+               acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00);
+               acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF);
+
+               register_index++;
+       }
+
+       return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_save_method_info
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Called from Acpi_walk_namespace. Expects each object to be a
+ *              control method under the _GPE portion of the namespace.
+ *              Extract the name and GPE type from the object, saving this
+ *              information for quick lookup during GPE dispatch
+ *
+ *              The name of each GPE control method is of the form:
+ *                  "_Lnn" or "_Enn"
+ *              Where:
+ *                  L      - means that the GPE is level triggered
+ *                  E      - means that the GPE is edge triggered
+ *                  nn     - is the GPE number
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+acpi_ev_save_method_info (
+       ACPI_HANDLE             obj_handle,
+       u32                     level,
+       void                    *obj_desc,
+       void                    **return_value)
+{
+       u32                     gpe_number;
+       NATIVE_CHAR             name[ACPI_NAME_SIZE + 1];
+       u8                      type;
+
+
+       /* Extract the name from the object and convert to a string */
+
+       MOVE_UNALIGNED32_TO_32 (name, &((ACPI_NAMESPACE_NODE *) obj_handle)->name);
+       name[ACPI_NAME_SIZE] = 0;
+
+       /*
+        * Edge/Level determination is based on the 2nd s8 of the method name
+        */
+       if (name[1] == 'L') {
+               type = ACPI_EVENT_LEVEL_TRIGGERED;
+       }
+       else if (name[1] == 'E') {
+               type = ACPI_EVENT_EDGE_TRIGGERED;
+       }
+       else {
+               /* Unknown method type, just ignore it! */
+
+               return (AE_OK);
+       }
+
+       /* Convert the last two characters of the name to the Gpe Number */
+
+       gpe_number = STRTOUL (&name[2], NULL, 16);
+       if (gpe_number == ACPI_UINT32_MAX) {
+               /* Conversion failed; invalid method, just ignore it */
+
+               return (AE_OK);
+       }
+
+       /* Ensure that we have a valid GPE number */
+
+       if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
+               /* Not valid, all we can do here is ignore it */
+
+               return (AE_OK);
+       }
+
+       /*
+        * Now we can add this information to the Gpe_info block
+        * for use during dispatch of this GPE.
+        */
+
+       acpi_gbl_gpe_info [gpe_number].type         = type;
+       acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle;
+
+
+       /*
+        * Enable the GPE (SCIs should be disabled at this point)
+        */
+
+       acpi_hw_enable_gpe (gpe_number);
+
+       return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_init_gpe_control_methods
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Obtain the control methods associated with the GPEs.
+ *
+ *              NOTE: Must be called AFTER namespace initialization!
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ev_init_gpe_control_methods (void)
+{
+       ACPI_STATUS             status;
+
+
+       /* Get a permanent handle to the _GPE object */
+
+       status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle);
+       if (ACPI_FAILURE (status)) {
+               return (status);
+       }
+
+       /* Traverse the namespace under \_GPE to find all methods there */
+
+       status = acpi_walk_namespace (ACPI_TYPE_METHOD, acpi_gbl_gpe_obj_handle,
+                         ACPI_UINT32_MAX, acpi_ev_save_method_info,
+                         NULL, NULL);
+
+       return (status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_gpe_detect
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
+ *
+ * DESCRIPTION: Detect if any GP events have occurred
+ *
+ ******************************************************************************/
+
+u32
+acpi_ev_gpe_detect (void)
+{
+       u32                     int_status = INTERRUPT_NOT_HANDLED;
+       u32                     i;
+       u32                     j;
+       u8                      enabled_status_byte;
+       u8                      bit_mask;
+
+
+       /*
+        * Read all of the 8-bit GPE status and enable registers
+        * in both of the register blocks, saving all of it.
+        * Find all currently active GP events.
+        */
+
+       for (i = 0; i < acpi_gbl_gpe_register_count; i++) {
+               acpi_gbl_gpe_registers[i].status =
+                                  acpi_os_in8 (acpi_gbl_gpe_registers[i].status_addr);
+
+               acpi_gbl_gpe_registers[i].enable =
+                                  acpi_os_in8 (acpi_gbl_gpe_registers[i].enable_addr);
+
+               /* First check if there is anything active at all in this register */
+
+               enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status &
+                                 acpi_gbl_gpe_registers[i].enable);
+
+               if (!enabled_status_byte) {
+                       /* No active GPEs in this register, move on */
+
+                       continue;
+               }
+
+               /* Now look at the individual GPEs in this byte register */
+
+               for (j = 0, bit_mask = 1; j < 8; j++, bit_mask <<= 1) {
+                       /* Examine one GPE bit */
+
+                       if (enabled_status_byte & bit_mask) {
+                               /*
+                                * Found an active GPE.  Dispatch the event to a handler
+                                * or method.
+                                */
+                               int_status |=
+                                       acpi_ev_gpe_dispatch (acpi_gbl_gpe_registers[i].gpe_base + j);
+                       }
+               }
+       }
+
+       return (int_status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_asynch_execute_gpe_method
+ *
+ * PARAMETERS:  Gpe_number      - The 0-based Gpe number
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Perform the actual execution of a GPE control method.  This
+ *              function is called from an invocation of Acpi_os_queue_for_execution
+ *              (and therefore does NOT execute at interrupt level) so that
+ *              the control method itself is not executed in the context of
+ *              the SCI interrupt handler.
+ *
+ ******************************************************************************/
+
+static void
+acpi_ev_asynch_execute_gpe_method (
+       void                    *context)
+{
+       u32                     gpe_number = (u32) context;
+       ACPI_GPE_LEVEL_INFO     gpe_info;
+
+
+       /*
+        * Take a snapshot of the GPE info for this level
+        */
+       acpi_cm_acquire_mutex (ACPI_MTX_EVENTS);
+       gpe_info = acpi_gbl_gpe_info [gpe_number];
+       acpi_cm_release_mutex (ACPI_MTX_EVENTS);
+
+       /*
+        * Method Handler (_Lxx, _Exx):
+        * ----------------------------
+        * Evaluate the _Lxx/_Exx control method that corresponds to this GPE.
+        */
+       if (gpe_info.method_handle) {
+               acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL);
+       }
+
+       /*
+        * Level-Triggered?
+        * ----------------
+        * If level-triggered we clear the GPE status bit after handling the event.
+        */
+       if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
+               acpi_hw_clear_gpe (gpe_number);
+       }
+
+       /*
+        * Enable the GPE.
+        */
+       acpi_hw_enable_gpe (gpe_number);
+
+       return;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_gpe_dispatch
+ *
+ * PARAMETERS:  Gpe_number      - The 0-based Gpe number
+ *
+ * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
+ *
+ * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event.
+ *              Clears the status bit for the requested event.
+ *
+ * TBD: [Investigate] is this still valid or necessary:
+ * The Gpe handler differs from the fixed events in that it clears the enable
+ * bit rather than the status bit to clear the interrupt.  This allows
+ * software outside of interrupt context to determine what caused the SCI and
+ * dispatch the correct AML.
+ *
+ ******************************************************************************/
+
+u32
+acpi_ev_gpe_dispatch (
+       u32                     gpe_number)
+{
+       ACPI_GPE_LEVEL_INFO     gpe_info;
+
+       /*
+        * Valid GPE number?
+        */
+       if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
+               return (INTERRUPT_NOT_HANDLED);
+       }
+
+       /*
+        * Disable the GPE.
+        */
+       acpi_hw_disable_gpe (gpe_number);
+
+       gpe_info = acpi_gbl_gpe_info [gpe_number];
+
+       /*
+        * Edge-Triggered?
+        * ---------------
+        * If edge-triggered, clear the GPE status bit now.  Note that
+        * level-triggered events are cleared after the GPE is serviced.
+        */
+       if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) {
+               acpi_hw_clear_gpe (gpe_number);
+       }
+               /*
+                * Function Handler (e.g. EC)?
+                */
+       if (gpe_info.handler) {
+               /* Invoke function handler (at interrupt level). */
+               gpe_info.handler (gpe_info.context);
+
+               /* Level-Triggered? */
+               if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
+                       acpi_hw_clear_gpe (gpe_number);
+               }
+
+               /* Enable GPE */
+               acpi_hw_enable_gpe (gpe_number);
+       }
+       /*
+        * Method Handler (e.g. _Exx/_Lxx)?
+        */
+       else if (gpe_info.method_handle) {
+               if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
+                       acpi_ev_asynch_execute_gpe_method, (void*)(NATIVE_UINT)gpe_number))) {
+                       /*
+                        * Shoudn't occur, but if it does report an error. Note that
+                        * the GPE will remain disabled until the ACPI Core Subsystem
+                        * is restarted, or the handler is removed/reinstalled.
+                        */
+                       REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number));
+               }
+       }
+       /*
+        * No Handler? Report an error and leave the GPE disabled.
+        */
+       else {
+               REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number));
+
+               /* Level-Triggered? */
+               if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
+                       acpi_hw_clear_gpe (gpe_number);
+               }
+       }
+
+       return (INTERRUPT_HANDLED);
+}
diff --git a/reactos/drivers/bus/acpi/events/evmisc.c b/reactos/drivers/bus/acpi/events/evmisc.c
new file mode 100644 (file)
index 0000000..16f0d47
--- /dev/null
@@ -0,0 +1,443 @@
+/******************************************************************************
+ *
+ * Module Name: evmisc - ACPI device notification handler dispatch
+ *                       and ACPI Global Lock support
+ *              $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"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "achware.h"
+
+#define _COMPONENT          ACPI_EVENTS
+        MODULE_NAME         ("evmisc")
+
+
+/**************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_queue_notify_request
+ *
+ * PARAMETERS:
+ *
+ * RETURN:      None.
+ *
+ * DESCRIPTION: Dispatch a device notification event to a previously
+ *              installed handler.
+ *
+ *************************************************************************/
+
+ACPI_STATUS
+acpi_ev_queue_notify_request (
+       ACPI_NAMESPACE_NODE     *node,
+       u32                     notify_value)
+{
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_OPERAND_OBJECT     *handler_obj = NULL;
+       ACPI_GENERIC_STATE      *notify_info;
+       ACPI_STATUS             status = AE_OK;
+
+
+       /*
+        * For value 1 (Ejection Request), some device method may need to be run.
+        * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
+        * For value 0x80 (Status Change) on the power button or sleep button,
+        * initiate soft-off or sleep operation?
+        */
+
+       switch (notify_value) {
+       case 0:
+               break;
+
+       case 1:
+               break;
+
+       case 2:
+               break;
+
+       case 0x80:
+               break;
+
+       default:
+               break;
+       }
+
+
+       /*
+        * Get the notify object attached to the device Node
+        */
+
+       obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
+       if (obj_desc) {
+
+               /* We have the notify object, Get the right handler */
+
+               switch (node->type) {
+               case ACPI_TYPE_DEVICE:
+                       if (notify_value <= MAX_SYS_NOTIFY) {
+                               handler_obj = obj_desc->device.sys_handler;
+                       }
+                       else {
+                               handler_obj = obj_desc->device.drv_handler;
+                       }
+                       break;
+
+               case ACPI_TYPE_THERMAL:
+                       if (notify_value <= MAX_SYS_NOTIFY) {
+                               handler_obj = obj_desc->thermal_zone.sys_handler;
+                       }
+                       else {
+                               handler_obj = obj_desc->thermal_zone.drv_handler;
+                       }
+                       break;
+               }
+       }
+
+
+       /* If there is any handler to run, schedule the dispatcher */
+
+       if ((acpi_gbl_sys_notify.handler && (notify_value <= MAX_SYS_NOTIFY)) ||
+               (acpi_gbl_drv_notify.handler && (notify_value > MAX_SYS_NOTIFY)) ||
+               handler_obj) {
+
+               notify_info = acpi_cm_create_generic_state ();
+               if (!notify_info) {
+                       return (AE_NO_MEMORY);
+               }
+
+               notify_info->notify.node      = node;
+               notify_info->notify.value     = (u16) notify_value;
+               notify_info->notify.handler_obj = handler_obj;
+
+               status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
+                                 acpi_ev_notify_dispatch, notify_info);
+               if (ACPI_FAILURE (status)) {
+                       acpi_cm_delete_generic_state (notify_info);
+               }
+       }
+
+       if (!handler_obj) {
+               /* There is no per-device notify handler for this device */
+
+       }
+
+
+       return (status);
+}
+
+
+/**************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_notify_dispatch
+ *
+ * PARAMETERS:
+ *
+ * RETURN:      None.
+ *
+ * DESCRIPTION: Dispatch a device notification event to a previously
+ *              installed handler.
+ *
+ *************************************************************************/
+
+void
+acpi_ev_notify_dispatch (
+       void                    *context)
+{
+       ACPI_GENERIC_STATE      *notify_info = (ACPI_GENERIC_STATE *) context;
+       NOTIFY_HANDLER          global_handler = NULL;
+       void                    *global_context = NULL;
+       ACPI_OPERAND_OBJECT     *handler_obj;
+
+
+       /*
+        * We will invoke a global notify handler if installed.
+        * This is done _before_ we invoke the per-device handler attached to the device.
+        */
+
+       if (notify_info->notify.value <= MAX_SYS_NOTIFY) {
+               /* Global system notification handler */
+
+               if (acpi_gbl_sys_notify.handler) {
+                       global_handler = acpi_gbl_sys_notify.handler;
+                       global_context = acpi_gbl_sys_notify.context;
+               }
+       }
+
+       else {
+               /* Global driver notification handler */
+
+               if (acpi_gbl_drv_notify.handler) {
+                       global_handler = acpi_gbl_drv_notify.handler;
+                       global_context = acpi_gbl_drv_notify.context;
+               }
+       }
+
+
+       /* Invoke the system handler first, if present */
+
+       if (global_handler) {
+               global_handler (notify_info->notify.node, notify_info->notify.value, global_context);
+       }
+
+       /* Now invoke the per-device handler, if present */
+
+       handler_obj = notify_info->notify.handler_obj;
+       if (handler_obj) {
+               handler_obj->notify_handler.handler (notify_info->notify.node, notify_info->notify.value,
+                                 handler_obj->notify_handler.context);
+       }
+
+
+       /* All done with the info object */
+
+       acpi_cm_delete_generic_state (notify_info);
+}
+
+
+/***************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_global_lock_thread
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
+ *              Global Lock.  Simply signal all threads that are waiting
+ *              for the lock.
+ *
+ **************************************************************************/
+
+static void
+acpi_ev_global_lock_thread (
+       void                    *context)
+{
+
+       /* Signal threads that are waiting for the lock */
+
+       if (acpi_gbl_global_lock_thread_count) {
+               /* Send sufficient units to the semaphore */
+
+               acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore,
+                                acpi_gbl_global_lock_thread_count);
+       }
+}
+
+
+/***************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_global_lock_handler
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Invoked directly from the SCI handler when a global lock
+ *              release interrupt occurs.  Grab the global lock and queue
+ *              the global lock thread for execution
+ *
+ **************************************************************************/
+
+static u32
+acpi_ev_global_lock_handler (
+       void                    *context)
+{
+       u8                      acquired = FALSE;
+       void                    *global_lock;
+
+
+       /*
+        * Attempt to get the lock
+        * If we don't get it now, it will be marked pending and we will
+        * take another interrupt when it becomes free.
+        */
+
+       global_lock = acpi_gbl_FACS->global_lock;
+       ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired);
+       if (acquired) {
+               /* Got the lock, now wake all threads waiting for it */
+
+               acpi_gbl_global_lock_acquired = TRUE;
+
+               /* Run the Global Lock thread which will signal all waiting threads */
+
+               acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_global_lock_thread,
+                                 context);
+       }
+
+       return (INTERRUPT_HANDLED);
+}
+
+
+/***************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_init_global_lock_handler
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for the global lock release event
+ *
+ **************************************************************************/
+
+ACPI_STATUS
+acpi_ev_init_global_lock_handler (void)
+{
+       ACPI_STATUS             status;
+
+
+       acpi_gbl_global_lock_present = TRUE;
+       status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL,
+                         acpi_ev_global_lock_handler, NULL);
+
+       /*
+        * If the global lock does not exist on this platform, the attempt
+        * to enable GBL_STS will fail (the GBL_EN bit will not stick)
+        * Map to AE_OK, but mark global lock as not present.
+        * Any attempt to actually use the global lock will be flagged
+        * with an error.
+        */
+       if (status == AE_NO_HARDWARE_RESPONSE) {
+               acpi_gbl_global_lock_present = FALSE;
+               status = AE_OK;
+       }
+
+       return (status);
+}
+
+
+/***************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_acquire_global_lock
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Attempt to gain ownership of the Global Lock.
+ *
+ **************************************************************************/
+
+ACPI_STATUS
+acpi_ev_acquire_global_lock(void)
+{
+       ACPI_STATUS             status = AE_OK;
+       u8                      acquired = FALSE;
+       void                    *global_lock;
+
+
+       /* Make sure that we actually have a global lock */
+
+       if (!acpi_gbl_global_lock_present) {
+               return (AE_NO_GLOBAL_LOCK);
+       }
+
+       /* One more thread wants the global lock */
+
+       acpi_gbl_global_lock_thread_count++;
+
+
+       /* If we (OS side) have the hardware lock already, we are done */
+
+       if (acpi_gbl_global_lock_acquired) {
+               return (AE_OK);
+       }
+
+       /* Only if the FACS is valid */
+
+       if (!acpi_gbl_FACS) {
+               return (AE_OK);
+       }
+
+
+       /* We must acquire the actual hardware lock */
+
+       global_lock = acpi_gbl_FACS->global_lock;
+       ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired);
+       if (acquired) {
+          /* We got the lock */
+
+               acpi_gbl_global_lock_acquired = TRUE;
+
+               return (AE_OK);
+       }
+
+
+       /*
+        * Did not get the lock.  The pending bit was set above, and we must now
+        * wait until we get the global lock released interrupt.
+        */
+
+        /*
+         * Acquire the global lock semaphore first.
+         * Since this wait will block, we must release the interpreter
+         */
+
+       status = acpi_aml_system_wait_semaphore (acpi_gbl_global_lock_semaphore,
+                         ACPI_UINT32_MAX);
+
+       return (status);
+}
+
+
+/***************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_release_global_lock
+ *
+ * DESCRIPTION: Releases ownership of the Global Lock.
+ *
+ **************************************************************************/
+
+void
+acpi_ev_release_global_lock (void)
+{
+       u8                      pending = FALSE;
+       void                    *global_lock;
+
+
+       if (!acpi_gbl_global_lock_thread_count) {
+               REPORT_WARNING(("Global Lock has not be acquired, cannot release\n"));
+               return;
+       }
+
+   /* One fewer thread has the global lock */
+
+       acpi_gbl_global_lock_thread_count--;
+
+       /* Have all threads released the lock? */
+
+       if (!acpi_gbl_global_lock_thread_count) {
+               /*
+                * No more threads holding lock, we can do the actual hardware
+                * release
+                */
+
+               global_lock = acpi_gbl_FACS->global_lock;
+               ACPI_RELEASE_GLOBAL_LOCK (global_lock, pending);
+               acpi_gbl_global_lock_acquired = FALSE;
+
+               /*
+                * If the pending bit was set, we must write GBL_RLS to the control
+                * register
+                */
+               if (pending) {
+                       acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK,
+                                        GBL_RLS, 1);
+               }
+       }
+
+       return;
+}
diff --git a/reactos/drivers/bus/acpi/events/evregion.c b/reactos/drivers/bus/acpi/events/evregion.c
new file mode 100644 (file)
index 0000000..b94806d
--- /dev/null
@@ -0,0 +1,606 @@
+/******************************************************************************
+ *
+ * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch
+ *              $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"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "amlcode.h"
+
+#define _COMPONENT          ACPI_EVENTS
+        MODULE_NAME         ("evregion")
+
+
+/**************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_install_default_address_space_handlers
+ *
+ * PARAMETERS:
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Installs the core subsystem address space handlers.
+ *
+ *************************************************************************/
+
+ACPI_STATUS
+acpi_ev_install_default_address_space_handlers (
+       void)
+{
+       ACPI_STATUS             status;
+
+
+       /*
+        * All address spaces (PCI Config, EC, SMBus) are scope dependent
+        * and registration must occur for a specific device.  In the case
+        * system memory and IO address spaces there is currently no device
+        * associated with the address space.  For these we use the root.
+        * We install the default PCI config space handler at the root so
+        * that this space is immediately available even though the we have
+        * not enumerated all the PCI Root Buses yet.  This is to conform
+        * to the ACPI specification which states that the PCI config
+        * space must be always available -- even though we are nowhere
+        * near ready to find the PCI root buses at this point.
+        *
+        * NOTE: We ignore AE_EXIST because this means that a handler has
+        * already been installed (via Acpi_install_address_space_handler)
+        */
+
+       status = acpi_install_address_space_handler (acpi_gbl_root_node,
+                          ADDRESS_SPACE_SYSTEM_MEMORY,
+                          ACPI_DEFAULT_HANDLER, NULL, NULL);
+       if ((ACPI_FAILURE (status)) &&
+               (status != AE_EXIST)) {
+               return (status);
+       }
+
+       status = acpi_install_address_space_handler (acpi_gbl_root_node,
+                          ADDRESS_SPACE_SYSTEM_IO,
+                          ACPI_DEFAULT_HANDLER, NULL, NULL);
+       if ((ACPI_FAILURE (status)) &&
+               (status != AE_EXIST)) {
+               return (status);
+       }
+
+       status = acpi_install_address_space_handler (acpi_gbl_root_node,
+                          ADDRESS_SPACE_PCI_CONFIG,
+                          ACPI_DEFAULT_HANDLER, NULL, NULL);
+       if ((ACPI_FAILURE (status)) &&
+               (status != AE_EXIST)) {
+               return (status);
+       }
+
+
+       return (AE_OK);
+}
+
+
+/* TBD: [Restructure] Move elsewhere */
+
+/**************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_execute_reg_method
+ *
+ * PARAMETERS:  Region_obj          - Object structure
+ *              Function            - On (1) or Off (0)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute _REG method for a region
+ *
+ *************************************************************************/
+
+static ACPI_STATUS
+acpi_ev_execute_reg_method (
+       ACPI_OPERAND_OBJECT    *region_obj,
+       u32                     function)
+{
+       ACPI_OPERAND_OBJECT    *params[3];
+       ACPI_OPERAND_OBJECT     space_id_desc;
+       ACPI_OPERAND_OBJECT     function_desc;
+       ACPI_STATUS             status;
+
+
+       if (region_obj->region.extra->extra.method_REG == NULL) {
+               return (AE_OK);
+       }
+
+       /*
+        *  _REG method has two arguments
+        *  Arg0:   Integer: Operation region space ID
+        *          Same value as Region_obj->Region.Space_id
+        *  Arg1:   Integer: connection status
+        *          1 for connecting the handler,
+        *          0 for disconnecting the handler
+        *          Passed as a parameter
+        */
+
+       acpi_cm_init_static_object (&space_id_desc);
+       acpi_cm_init_static_object (&function_desc);
+
+       /*
+        *  Method requires two parameters.
+        */
+       params [0] = &space_id_desc;
+       params [1] = &function_desc;
+       params [2] = NULL;
+
+       /*
+        *  Set up the parameter objects
+        */
+       space_id_desc.common.type  = ACPI_TYPE_INTEGER;
+       space_id_desc.integer.value = region_obj->region.space_id;
+
+       function_desc.common.type  = ACPI_TYPE_INTEGER;
+       function_desc.integer.value = function;
+
+       /*
+        *  Execute the method, no return value
+        */
+       status = acpi_ns_evaluate_by_handle (region_obj->region.extra->extra.method_REG, params, NULL);
+       return (status);
+}
+
+
+/**************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_address_space_dispatch
+ *
+ * PARAMETERS:  Region_obj          - internal region object
+ *              Space_id            - ID of the address space (0-255)
+ *              Function            - Read or Write operation
+ *              Address             - Where in the space to read or write
+ *              Bit_width           - Field width in bits (8, 16, or 32)
+ *              Value               - Pointer to in or out value
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Dispatch an address space or operation region access to
+ *              a previously installed handler.
+ *
+ *************************************************************************/
+
+ACPI_STATUS
+acpi_ev_address_space_dispatch (
+       ACPI_OPERAND_OBJECT     *region_obj,
+       u32                     function,
+       ACPI_PHYSICAL_ADDRESS   address,
+       u32                     bit_width,
+       u32                     *value)
+{
+       ACPI_STATUS             status;
+       ADDRESS_SPACE_HANDLER   handler;
+       ADDRESS_SPACE_SETUP     region_setup;
+       ACPI_OPERAND_OBJECT     *handler_desc;
+       void                    *region_context = NULL;
+
+
+       /*
+        * Ensure that there is a handler associated with this region
+        */
+       handler_desc = region_obj->region.addr_handler;
+       if (!handler_desc) {
+               return(AE_NOT_EXIST);
+       }
+
+       /*
+        * It may be the case that the region has never been initialized
+        * Some types of regions require special init code
+        */
+       if (!(region_obj->region.flags & AOPOBJ_INITIALIZED)) {
+               /*
+                * This region has not been initialized yet, do it
+                */
+               region_setup = handler_desc->addr_handler.setup;
+               if (!region_setup) {
+                       /*
+                        *  Bad news, no init routine and not init'd
+                        */
+                       return (AE_UNKNOWN_STATUS);
+               }
+
+               /*
+                * We must exit the interpreter because the region setup will potentially
+                * execute control methods
+                */
+               acpi_aml_exit_interpreter ();
+
+               status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
+                                 handler_desc->addr_handler.context,
+                                 &region_context);
+
+               /* Re-enter the interpreter */
+
+               acpi_aml_enter_interpreter ();
+
+               /*
+                *  Init routine may fail
+                */
+               if (ACPI_FAILURE (status)) {
+                       return(status);
+               }
+
+               region_obj->region.flags |= AOPOBJ_INITIALIZED;
+
+               /*
+                *  Save the returned context for use in all accesses to
+                *  this particular region.
+                */
+               region_obj->region.extra->extra.region_context = region_context;
+       }
+
+       /*
+        *  We have everything we need, begin the process
+        */
+       handler = handler_desc->addr_handler.handler;
+
+       if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) {
+               /*
+                *  For handlers other than the default (supplied) handlers, we must
+                *  exit the interpreter because the handler *might* block -- we don't
+                *  know what it will do, so we can't hold the lock on the intepreter.
+                */
+               acpi_aml_exit_interpreter();
+       }
+
+       /*
+        *  Invoke the handler.
+        */
+       status = handler (function, address, bit_width, value,
+                        handler_desc->addr_handler.context,
+                        region_obj->region.extra->extra.region_context);
+
+
+       if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) {
+               /* We just returned from a non-default handler, we must re-enter the
+               interpreter */
+
+               acpi_aml_enter_interpreter ();
+       }
+
+       return (status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_disassociate_region_from_handler
+ *
+ * PARAMETERS:  Region_obj      - Region Object
+ *              Acpi_ns_is_locked - Namespace Region Already Locked?
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Break the association between the handler and the region
+ *              this is a two way association.
+ *
+ ******************************************************************************/
+
+void
+acpi_ev_disassociate_region_from_handler(
+       ACPI_OPERAND_OBJECT     *region_obj,
+       u8                      acpi_ns_is_locked)
+{
+       ACPI_OPERAND_OBJECT     *handler_obj;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_OPERAND_OBJECT     **last_obj_ptr;
+       ADDRESS_SPACE_SETUP     region_setup;
+       void                    *region_context;
+       ACPI_STATUS             status;
+
+
+       region_context = region_obj->region.extra->extra.region_context;
+
+       /*
+        *  Get the address handler from the region object
+        */
+
+       handler_obj = region_obj->region.addr_handler;
+       if (!handler_obj) {
+               /*
+                *  This region has no handler, all done
+                */
+               return;
+       }
+
+
+       /*
+        *  Find this region in the handler's list
+        */
+
+       obj_desc = handler_obj->addr_handler.region_list;
+       last_obj_ptr = &handler_obj->addr_handler.region_list;
+
+       while (obj_desc) {
+               /*
+                *  See if this is the one
+                */
+               if (obj_desc == region_obj) {
+                       /*
+                        *  This is it, remove it from the handler's list
+                        */
+                       *last_obj_ptr = obj_desc->region.next;
+                       obj_desc->region.next = NULL;           /* Must clear field */
+
+                       if (acpi_ns_is_locked) {
+                               acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+                       }
+
+                       /*
+                        *  Now stop region accesses by executing the _REG method
+                        */
+                       acpi_ev_execute_reg_method (region_obj, 0);
+
+                       if (acpi_ns_is_locked) {
+                               acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+                       }
+
+                       /*
+                        *  Call the setup handler with the deactivate notification
+                        */
+                       region_setup = handler_obj->addr_handler.setup;
+                       status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
+                                         handler_obj->addr_handler.context,
+                                         &region_context);
+
+                       /*
+                        *  Init routine may fail, Just ignore errors
+                        */
+
+                       region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);
+
+                       /*
+                        *  Remove handler reference in the region
+                        *
+                        *  NOTE: this doesn't mean that the region goes away
+                        *  The region is just inaccessible as indicated to
+                        *  the _REG method
+                        *
+                        *  If the region is on the handler's list
+                        *  this better be the region's handler
+                        */
+                       ACPI_ASSERT (region_obj->region.addr_handler == handler_obj);
+
+                       region_obj->region.addr_handler = NULL;
+
+                       return;
+
+               } /* found the right handler */
+
+               /*
+                *  Move through the linked list of handlers
+                */
+               last_obj_ptr = &obj_desc->region.next;
+               obj_desc = obj_desc->region.next;
+       }
+
+       /*
+        *  If we get here, the region was not in the handler's region list
+        */
+       return;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_associate_region_and_handler
+ *
+ * PARAMETERS:  Handler_obj     - Handler Object
+ *              Region_obj      - Region Object
+ *              Acpi_ns_is_locked - Namespace Region Already Locked?
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Create the association between the handler and the region
+ *              this is a two way association.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ev_associate_region_and_handler (
+       ACPI_OPERAND_OBJECT     *handler_obj,
+       ACPI_OPERAND_OBJECT     *region_obj,
+       u8                      acpi_ns_is_locked)
+{
+       ACPI_STATUS     status;
+
+
+       ACPI_ASSERT (region_obj->region.space_id == handler_obj->addr_handler.space_id);
+       ACPI_ASSERT (region_obj->region.addr_handler == 0);
+
+       /*
+        *  Link this region to the front of the handler's list
+        */
+
+       region_obj->region.next = handler_obj->addr_handler.region_list;
+       handler_obj->addr_handler.region_list = region_obj;
+
+       /*
+        *  set the region's handler
+        */
+
+/*
+       Handler_obj->Common.Reference_count =
+                         (u16) (Handler_obj->Common.Reference_count +
+                         Region_obj->Common.Reference_count - 1);
+*/
+       region_obj->region.addr_handler = handler_obj;
+
+       /*
+        *  Last thing, tell all users that this region is usable
+        */
+       if (acpi_ns_is_locked) {
+               acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+       }
+
+       status = acpi_ev_execute_reg_method (region_obj, 1);
+
+       if (acpi_ns_is_locked) {
+               acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+       }
+
+       return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_addr_handler_helper
+ *
+ * PARAMETERS:  Handle              - Node to be dumped
+ *              Level               - Nesting level of the handle
+ *              Context             - Passed into Acpi_ns_walk_namespace
+ *
+ * DESCRIPTION: This routine checks to see if the object is a Region if it
+ *              is then the address handler is installed in it.
+ *
+ *              If the Object is a Device, and the device has a handler of
+ *              the same type then the search is terminated in that branch.
+ *
+ *              This is because the existing handler is closer in proximity
+ *              to any more regions than the one we are trying to install.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ev_addr_handler_helper (
+       ACPI_HANDLE             obj_handle,
+       u32                     level,
+       void                    *context,
+       void                    **return_value)
+{
+       ACPI_OPERAND_OBJECT     *handler_obj;
+       ACPI_OPERAND_OBJECT     *tmp_obj;
+       ACPI_OPERAND_OBJECT     *obj_desc;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_STATUS             status;
+
+
+       handler_obj = (ACPI_OPERAND_OBJECT *) context;
+
+       /* Parameter validation */
+
+       if (!handler_obj) {
+               return (AE_OK);
+       }
+
+       /* Convert and validate the device handle */
+
+       node = acpi_ns_convert_handle_to_entry (obj_handle);
+       if (!node) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       /*
+        *  We only care about regions.and objects
+        *  that can have address handlers
+        */
+
+       if ((node->type != ACPI_TYPE_DEVICE) &&
+               (node->type != ACPI_TYPE_REGION) &&
+               (node != acpi_gbl_root_node)) {
+               return (AE_OK);
+       }
+
+       /* Check for an existing internal object */
+
+       obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
+       if (!obj_desc) {
+               /*
+                *  The object DNE, we don't care about it
+                */
+               return (AE_OK);
+       }
+
+       /*
+        *  Devices are handled different than regions
+        */
+       if (IS_THIS_OBJECT_TYPE (obj_desc, ACPI_TYPE_DEVICE)) {
+               /*
+                *  See if this guy has any handlers
+                */
+               tmp_obj = obj_desc->device.addr_handler;
+               while (tmp_obj) {
+                       /*
+                        *  Now let's see if it's for the same address space.
+                        */
+                       if (tmp_obj->addr_handler.space_id == handler_obj->addr_handler.space_id) {
+                               /*
+                                *  It's for the same address space
+                                */
+                               /*
+                                *  Since the object we found it on was a device, then it
+                                *  means that someone has already installed a handler for
+                                *  the branch of the namespace from this device on.  Just
+                                *  bail out telling the walk routine to not traverse this
+                                *  branch.  This preserves the scoping rule for handlers.
+                                */
+                               return (AE_CTRL_DEPTH);
+                       }
+
+                       /*
+                        *  Move through the linked list of handlers
+                        */
+                       tmp_obj = tmp_obj->addr_handler.next;
+               }
+
+               /*
+                *  As long as the device didn't have a handler for this
+                *  space we don't care about it.  We just ignore it and
+                *  proceed.
+                */
+               return (AE_OK);
+       }
+
+       /*
+        *  Only here if it was a region
+        */
+       ACPI_ASSERT (obj_desc->common.type == ACPI_TYPE_REGION);
+
+       if (obj_desc->region.space_id != handler_obj->addr_handler.space_id) {
+               /*
+                *  This region is for a different address space
+                *  ignore it
+                */
+               return (AE_OK);
+       }
+
+       /*
+        *  Now we have a region and it is for the handler's address
+        *  space type.
+        *
+        *  First disconnect region for any previous handler (if any)
+        */
+       acpi_ev_disassociate_region_from_handler (obj_desc, FALSE);
+
+       /*
+        *  Then connect the region to the new handler
+        */
+       status = acpi_ev_associate_region_and_handler (handler_obj, obj_desc, FALSE);
+
+       return (status);
+}
+
+
diff --git a/reactos/drivers/bus/acpi/events/evrgnini.c b/reactos/drivers/bus/acpi/events/evrgnini.c
new file mode 100644 (file)
index 0000000..72e9a30
--- /dev/null
@@ -0,0 +1,417 @@
+/******************************************************************************
+ *
+ * Module Name: evrgnini- ACPI Address_space (Op_region) init
+ *              $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"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "amlcode.h"
+
+#define _COMPONENT          ACPI_EVENTS
+        MODULE_NAME         ("evrgnini")
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_system_memory_region_setup
+ *
+ * PARAMETERS:  Region_obj          - region we are interested in
+ *              Function            - start or stop
+ *              Handler_context     - Address space handler context
+ *              Region_context      - Region specific context
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Do any prep work for region handling, a nop for now
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ev_system_memory_region_setup (
+       ACPI_HANDLE             handle,
+       u32                     function,
+       void                    *handler_context,
+       void                    **region_context)
+{
+
+       if (function == ACPI_REGION_DEACTIVATE) {
+               if (*region_context) {
+                       acpi_cm_free (*region_context);
+                       *region_context = NULL;
+               }
+               return (AE_OK);
+       }
+
+
+       /* Activate.  Create a new context */
+
+       *region_context = acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT));
+       if (!(*region_context)) {
+               return (AE_NO_MEMORY);
+       }
+
+       return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_io_space_region_setup
+ *
+ * PARAMETERS:  Region_obj          - region we are interested in
+ *              Function            - start or stop
+ *              Handler_context     - Address space handler context
+ *              Region_context      - Region specific context
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Do any prep work for region handling
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ev_io_space_region_setup (
+       ACPI_HANDLE             handle,
+       u32                     function,
+       void                    *handler_context,
+       void                    **region_context)
+{
+       if (function == ACPI_REGION_DEACTIVATE) {
+               *region_context = NULL;
+       }
+       else {
+               *region_context = handler_context;
+       }
+
+       return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_pci_config_region_setup
+ *
+ * PARAMETERS:  Region_obj          - region we are interested in
+ *              Function            - start or stop
+ *              Handler_context     - Address space handler context
+ *              Region_context      - Region specific context
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Do any prep work for region handling
+ *
+ * MUTEX:       Assumes namespace is not locked
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ev_pci_config_region_setup (
+       ACPI_HANDLE             handle,
+       u32                     function,
+       void                    *handler_context,
+       void                    **region_context)
+{
+       ACPI_STATUS             status = AE_OK;
+       ACPI_INTEGER            temp;
+       PCI_HANDLER_CONTEXT     *pci_context = *region_context;
+       ACPI_OPERAND_OBJECT     *handler_obj;
+       ACPI_NAMESPACE_NODE     *node;
+       ACPI_OPERAND_OBJECT     *region_obj = (ACPI_OPERAND_OBJECT *) handle;
+       DEVICE_ID               object_hID;
+
+       handler_obj = region_obj->region.addr_handler;
+
+       if (!handler_obj) {
+               /*
+                *  No installed handler. This shouldn't happen because the dispatch
+                *  routine checks before we get here, but we check again just in case.
+                */
+               return(AE_NOT_EXIST);
+       }
+
+       if (function == ACPI_REGION_DEACTIVATE) {
+               if (pci_context) {
+                       acpi_cm_free (pci_context);
+                       *region_context = NULL;
+               }
+
+               return (status);
+       }
+
+
+       /* Create a new context */
+
+       pci_context = acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT));
+       if (!pci_context) {
+               return (AE_NO_MEMORY);
+       }
+
+       /*
+        *  For PCI Config space access, we have to pass the segment, bus,
+        *  device and function numbers.  This routine must acquire those.
+        */
+
+       /*
+        *  First get device and function numbers from the _ADR object
+        *  in the parent's scope.
+        */
+       ACPI_ASSERT(region_obj->region.node);
+
+       node = acpi_ns_get_parent_object (region_obj->region.node);
+
+
+       /* Acpi_evaluate the _ADR object */
+
+       status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp);
+       /*
+        *  The default is zero, since the allocation above zeroed the data, just
+        *  do nothing on failures.
+        */
+       if (ACPI_SUCCESS (status)) {
+               /*
+                *  Got it..
+                */
+               pci_context->dev_func = (u32) temp;
+       }
+
+       /*
+        *  Get the _SEG and _BBN values from the device upon which the handler
+        *  is installed.
+        *
+        *  We need to get the _SEG and _BBN objects relative to the PCI BUS device.
+        *  This is the device the handler has been registered to handle.
+        */
+
+       /*
+        *  If the Addr_handler.Node is still pointing to the root, we need
+        *  to scan upward for a PCI Root bridge and re-associate the Op_region
+        *  handlers with that device.
+        */
+       if (handler_obj->addr_handler.node == acpi_gbl_root_node) {
+               /*
+                * Node is currently the parent object
+                */
+               while (node != acpi_gbl_root_node) {
+                       status = acpi_cm_execute_HID(node, &object_hID);
+
+                       if (ACPI_SUCCESS (status)) {
+                               if (!(STRNCMP(object_hID.buffer, PCI_ROOT_HID_STRING,
+                                                  sizeof (PCI_ROOT_HID_STRING)))) {
+                                       acpi_install_address_space_handler(node,
+                                                          ADDRESS_SPACE_PCI_CONFIG,
+                                                          ACPI_DEFAULT_HANDLER, NULL, NULL);
+
+                                       break;
+                               }
+                       }
+
+                       node = acpi_ns_get_parent_object(node);
+               }
+       }
+       else {
+               node = handler_obj->addr_handler.node;
+       }
+
+       status = acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp);
+       if (ACPI_SUCCESS (status)) {
+               /*
+                *  Got it..
+                */
+               pci_context->seg = (u32) temp;
+       }
+
+       status = acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp);
+       if (ACPI_SUCCESS (status)) {
+               /*
+                *  Got it..
+                */
+               pci_context->bus = (u32) temp;
+       }
+
+       *region_context = pci_context;
+
+       return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_default_region_setup
+ *
+ * PARAMETERS:  Region_obj          - region we are interested in
+ *              Function            - start or stop
+ *              Handler_context     - Address space handler context
+ *              Region_context      - Region specific context
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Do any prep work for region handling
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ev_default_region_setup (
+       ACPI_HANDLE             handle,
+       u32                     function,
+       void                    *handler_context,
+       void                    **region_context)
+{
+       if (function == ACPI_REGION_DEACTIVATE) {
+               *region_context = NULL;
+       }
+       else {
+               *region_context = handler_context;
+       }
+
+       return (AE_OK);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_initialize_region
+ *
+ * PARAMETERS:  Region_obj - Region we are initializing
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
+ *              for execution at a later time
+ *
+ *              Get the appropriate address space handler for a newly
+ *              created region.
+ *
+ *              This also performs address space specific intialization.  For
+ *              example, PCI regions must have an _ADR object that contains
+ *              a PCI address in the scope of the defintion.  This address is
+ *              required to perform an access to PCI config space.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ev_initialize_region (
+       ACPI_OPERAND_OBJECT     *region_obj,
+       u8                      acpi_ns_locked)
+{
+       ACPI_OPERAND_OBJECT    *handler_obj;
+       ACPI_OPERAND_OBJECT    *obj_desc;
+       ACPI_ADDRESS_SPACE_TYPE space_id;
+       ACPI_NAMESPACE_NODE    *node;
+       ACPI_STATUS             status;
+       ACPI_NAMESPACE_NODE    *method_node;
+       ACPI_NAME              *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG;
+
+
+       if (!region_obj) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       ACPI_ASSERT(region_obj->region.node);
+
+       node = acpi_ns_get_parent_object (region_obj->region.node);
+       space_id = region_obj->region.space_id;
+
+       region_obj->region.addr_handler = NULL;
+       region_obj->region.extra->extra.method_REG = NULL;
+       region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);
+
+       /*
+        *  Find any "_REG" associated with this region definition