1/******************************************************************************
2 *
3 * Module Name: psxface - Parser external interfaces
4 *              $Revision: 1.1.1.1 $
5 *
6 *****************************************************************************/
7
8/*
9 *  Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; either version 2 of the License, or
14 *  (at your option) any later version.
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *  GNU General Public License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License
22 *  along with this program; if not, write to the Free Software
23 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26
27#include "acpi.h"
28#include "acparser.h"
29#include "acdispat.h"
30#include "acinterp.h"
31#include "amlcode.h"
32#include "acnamesp.h"
33
34
35#define _COMPONENT          ACPI_PARSER
36	 MODULE_NAME         ("psxface")
37
38
39/*******************************************************************************
40 *
41 * FUNCTION:    Acpi_psx_execute
42 *
43 * PARAMETERS:  Method_node         - A method object containing both the AML
44 *                                    address and length.
45 *              **Params            - List of parameters to pass to method,
46 *                                    terminated by NULL. Params itself may be
47 *                                    NULL if no parameters are being passed.
48 *              **Return_obj_desc   - Return object from execution of the
49 *                                    method.
50 *
51 * RETURN:      Status
52 *
53 * DESCRIPTION: Execute a control method
54 *
55 ******************************************************************************/
56
57acpi_status
58acpi_psx_execute (
59	acpi_namespace_node     *method_node,
60	acpi_operand_object     **params,
61	acpi_operand_object     **return_obj_desc)
62{
63	acpi_status             status;
64	acpi_operand_object     *obj_desc;
65	u32                     i;
66	acpi_parse_object       *op;
67	acpi_walk_state         *walk_state;
68
69
70	FUNCTION_TRACE ("Psx_execute");
71
72
73	/* Validate the Node and get the attached object */
74
75	if (!method_node) {
76		return_ACPI_STATUS (AE_NULL_ENTRY);
77	}
78
79	obj_desc = acpi_ns_get_attached_object (method_node);
80	if (!obj_desc) {
81		return_ACPI_STATUS (AE_NULL_OBJECT);
82	}
83
84	/* Init for new method, wait on concurrency semaphore */
85
86	status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
87	if (ACPI_FAILURE (status)) {
88		return_ACPI_STATUS (status);
89	}
90
91	if (params) {
92		/*
93		 * The caller "owns" the parameters, so give each one an extra
94		 * reference
95		 */
96		for (i = 0; params[i]; i++) {
97			acpi_ut_add_reference (params[i]);
98		}
99	}
100
101	/*
102	 * 1) Perform the first pass parse of the method to enter any
103	 * named objects that it creates into the namespace
104	 */
105	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
106		"**** Begin Method Parse **** Entry=%p obj=%p\n",
107		method_node, obj_desc));
108
109	/* Create and init a Root Node */
110
111	op = acpi_ps_alloc_op (AML_SCOPE_OP);
112	if (!op) {
113		return_ACPI_STATUS (AE_NO_MEMORY);
114	}
115
116	/* Create and initialize a new walk state */
117
118	walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
119			   NULL, NULL, NULL);
120	if (!walk_state) {
121		return_ACPI_STATUS (AE_NO_MEMORY);
122	}
123
124	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
125			  obj_desc->method.aml_length, NULL, NULL, 1);
126	if (ACPI_FAILURE (status)) {
127		/* TBD: delete walk state */
128		return_ACPI_STATUS (status);
129	}
130
131	/* Parse the AML */
132
133	status = acpi_ps_parse_aml (walk_state);
134	acpi_ps_delete_parse_tree (op);
135
136
137	/*
138	 * 2) Execute the method.  Performs second pass parse simultaneously
139	 */
140	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
141		"**** Begin Method Execution **** Entry=%p obj=%p\n",
142		method_node, obj_desc));
143
144	/* Create and init a Root Node */
145
146	op = acpi_ps_alloc_op (AML_SCOPE_OP);
147	if (!op) {
148		return_ACPI_STATUS (AE_NO_MEMORY);
149	}
150
151	/* Init new op with the method name and pointer back to the NS node */
152
153	acpi_ps_set_name (op, method_node->name);
154	op->node = method_node;
155
156	/* Create and initialize a new walk state */
157
158	walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
159			   NULL, NULL, NULL);
160	if (!walk_state) {
161		return_ACPI_STATUS (AE_NO_MEMORY);
162	}
163
164	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
165			  obj_desc->method.aml_length, params, return_obj_desc, 3);
166	if (ACPI_FAILURE (status)) {
167		/* TBD: delete walk state */
168		return_ACPI_STATUS (status);
169	}
170
171	/*
172	 * The walk of the parse tree is where we actually execute the method
173	 */
174	status = acpi_ps_parse_aml (walk_state);
175	acpi_ps_delete_parse_tree (op);
176
177	if (params) {
178		/* Take away the extra reference that we gave the parameters above */
179
180		for (i = 0; params[i]; i++) {
181			acpi_ut_update_object_reference (params[i], REF_DECREMENT);
182		}
183	}
184
185
186	if (ACPI_FAILURE (status)) {
187		DUMP_PATHNAME (method_node, "Ps_execute: method failed -",
188			ACPI_LV_ERROR, _COMPONENT);
189	}
190
191
192	/*
193	 * If the method has returned an object, signal this to the caller with
194	 * a control exception code
195	 */
196	if (*return_obj_desc) {
197		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Method returned Obj_desc=%p\n",
198			*return_obj_desc));
199		DUMP_STACK_ENTRY (*return_obj_desc);
200
201		status = AE_CTRL_RETURN_VALUE;
202	}
203
204
205	return_ACPI_STATUS (status);
206}
207
208
209