1/******************************************************************************
2 *
3 * Module Name: nsinit - namespace initialization
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 "acnamesp.h"
29#include "acdispat.h"
30#include "acinterp.h"
31
32#define _COMPONENT          ACPI_NAMESPACE
33	 MODULE_NAME         ("nsinit")
34
35
36/*******************************************************************************
37 *
38 * FUNCTION:    Acpi_ns_initialize_objects
39 *
40 * PARAMETERS:  None
41 *
42 * RETURN:      Status
43 *
44 * DESCRIPTION: Walk the entire namespace and perform any necessary
45 *              initialization on the objects found therein
46 *
47 ******************************************************************************/
48
49acpi_status
50acpi_ns_initialize_objects (
51	void)
52{
53	acpi_status             status;
54	acpi_init_walk_info     info;
55
56
57	FUNCTION_TRACE ("Ns_initialize_objects");
58
59
60	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
61		"**** Starting initialization of namespace objects ****\n"));
62	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Completing Region and Field initialization:"));
63
64
65	info.field_count = 0;
66	info.field_init = 0;
67	info.op_region_count = 0;
68	info.op_region_init = 0;
69	info.object_count = 0;
70
71
72	/* Walk entire namespace from the supplied root */
73
74	status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
75			  ACPI_UINT32_MAX, acpi_ns_init_one_object,
76			  &info, NULL);
77	if (ACPI_FAILURE (status)) {
78		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status));
79	}
80
81	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
82		"\n%d/%d Regions, %d/%d Fields initialized (%d nodes total)\n",
83		info.op_region_init, info.op_region_count, info.field_init,
84		info.field_count, info.object_count));
85	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
86		"%d Control Methods found\n", info.method_count));
87	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
88		"%d Op Regions found\n", info.op_region_count));
89
90	return_ACPI_STATUS (AE_OK);
91}
92
93
94/*******************************************************************************
95 *
96 * FUNCTION:    Acpi_ns_initialize_devices
97 *
98 * PARAMETERS:  None
99 *
100 * RETURN:      acpi_status
101 *
102 * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
103 *              This means running _INI on all present devices.
104 *
105 *              Note: We install PCI config space handler on region access,
106 *              not here.
107 *
108 ******************************************************************************/
109
110acpi_status
111acpi_ns_initialize_devices (
112	void)
113{
114	acpi_status             status;
115	acpi_device_walk_info   info;
116
117
118	FUNCTION_TRACE ("Ns_initialize_devices");
119
120
121	info.device_count = 0;
122	info.num_STA = 0;
123	info.num_INI = 0;
124
125
126	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Executing device _INI methods:"));
127
128	status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
129			  ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL);
130
131	if (ACPI_FAILURE (status)) {
132		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status));
133	}
134
135
136	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
137		"\n%d Devices found: %d _STA, %d _INI\n",
138		info.device_count, info.num_STA, info.num_INI));
139
140	return_ACPI_STATUS (status);
141}
142
143
144/*******************************************************************************
145 *
146 * FUNCTION:    Acpi_ns_init_one_object
147 *
148 * PARAMETERS:  Obj_handle      - Node
149 *              Level           - Current nesting level
150 *              Context         - Points to a init info struct
151 *              Return_value    - Not used
152 *
153 * RETURN:      Status
154 *
155 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
156 *              within the  namespace.
157 *
158 *              Currently, the only objects that require initialization are:
159 *              1) Methods
160 *              2) Op Regions
161 *
162 ******************************************************************************/
163
164acpi_status
165acpi_ns_init_one_object (
166	acpi_handle             obj_handle,
167	u32                     level,
168	void                    *context,
169	void                    **return_value)
170{
171	acpi_object_type8       type;
172	acpi_status             status;
173	acpi_init_walk_info     *info = (acpi_init_walk_info *) context;
174	acpi_namespace_node     *node = (acpi_namespace_node *) obj_handle;
175	acpi_operand_object     *obj_desc;
176
177
178	PROC_NAME ("Ns_init_one_object");
179
180
181	info->object_count++;
182
183
184	/* And even then, we are only interested in a few object types */
185
186	type = acpi_ns_get_type (obj_handle);
187	obj_desc = node->object;
188	if (!obj_desc) {
189		return (AE_OK);
190	}
191
192	if ((type != ACPI_TYPE_REGION) &&
193		(type != ACPI_TYPE_BUFFER_FIELD)) {
194		return (AE_OK);
195	}
196
197
198	/*
199	 * Must lock the interpreter before executing AML code
200	 */
201	status = acpi_ex_enter_interpreter ();
202	if (ACPI_FAILURE (status)) {
203		return (status);
204	}
205
206	switch (type) {
207
208	case ACPI_TYPE_REGION:
209
210		info->op_region_count++;
211		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
212			break;
213		}
214
215		info->op_region_init++;
216		status = acpi_ds_get_region_arguments (obj_desc);
217		if (ACPI_FAILURE (status)) {
218			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
219			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
220					"%s while getting region arguments [%4.4s]\n",
221					acpi_format_exception (status), (char*)&node->name));
222		}
223
224		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
225			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
226		}
227
228		break;
229
230
231	case ACPI_TYPE_BUFFER_FIELD:
232
233		info->field_count++;
234		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
235			break;
236		}
237
238		info->field_init++;
239		status = acpi_ds_get_buffer_field_arguments (obj_desc);
240		if (ACPI_FAILURE (status)) {
241			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
242			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
243					"%s while getting buffer field arguments [%4.4s]\n",
244					acpi_format_exception (status), (char*)&node->name));
245		}
246		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
247			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
248		}
249
250
251		break;
252
253	default:
254		break;
255	}
256
257
258	/*
259	 * We ignore errors from above, and always return OK, since
260	 * we don't want to abort the walk on a single error.
261	 */
262	acpi_ex_exit_interpreter ();
263	return (AE_OK);
264}
265
266
267/*******************************************************************************
268 *
269 * FUNCTION:    Acpi_ns_init_one_device
270 *
271 * PARAMETERS:  acpi_walk_callback
272 *
273 * RETURN:      acpi_status
274 *
275 * DESCRIPTION: This is called once per device soon after ACPI is enabled
276 *              to initialize each device. It determines if the device is
277 *              present, and if so, calls _INI.
278 *
279 ******************************************************************************/
280
281acpi_status
282acpi_ns_init_one_device (
283	acpi_handle             obj_handle,
284	u32                     nesting_level,
285	void                    *context,
286	void                    **return_value)
287{
288	acpi_status             status;
289	acpi_namespace_node    *node;
290	u32                     flags;
291	acpi_device_walk_info  *info = (acpi_device_walk_info *) context;
292
293
294	FUNCTION_TRACE ("Ns_init_one_device");
295
296
297	if (!(acpi_dbg_level & ACPI_LV_INIT)) {
298		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
299	}
300
301	info->device_count++;
302
303	acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
304
305	node = acpi_ns_map_handle_to_node (obj_handle);
306	if (!node) {
307		acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
308		return (AE_BAD_PARAMETER);
309	}
310
311	acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
312
313	/*
314	 * Run _STA to determine if we can run _INI on the device.
315	 */
316	DEBUG_EXEC (acpi_ut_display_init_pathname (node, "_STA [Method]"));
317	status = acpi_ut_execute_STA (node, &flags);
318	if (ACPI_FAILURE (status)) {
319		/* Ignore error and move on to next device */
320
321		return_ACPI_STATUS (AE_OK);
322	}
323
324	info->num_STA++;
325
326	if (!(flags & 0x01)) {
327		/* don't look at children of a not present device */
328
329		return_ACPI_STATUS(AE_CTRL_DEPTH);
330	}
331
332
333	/*
334	 * The device is present. Run _INI.
335	 */
336	DEBUG_EXEC (acpi_ut_display_init_pathname (obj_handle, "_INI [Method]"));
337	status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
338	if (AE_NOT_FOUND == status) {
339		/* No _INI means device requires no initialization */
340
341		status = AE_OK;
342	}
343
344	else if (ACPI_FAILURE (status)) {
345		/* Ignore error and move on to next device */
346
347#ifdef ACPI_DEBUG
348		NATIVE_CHAR *scope_name = acpi_ns_get_table_pathname (obj_handle);
349
350		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
351				scope_name, acpi_format_exception (status)));
352
353		ACPI_MEM_FREE (scope_name);
354#endif
355	}
356
357	else {
358		/* Count of successful INIs */
359
360		info->num_INI++;
361	}
362
363	return_ACPI_STATUS (AE_OK);
364}
365