508528f8c126c82d5e4e78ae905623e1d0bc16f7
[reactos.git] / reactos / drivers / bus / acpi / namespace / nsinit.c
1 /******************************************************************************
2 *
3 * Module Name: nsinit - namespace initialization
4 * $Revision: 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
31 #define _COMPONENT ACPI_NAMESPACE
32 MODULE_NAME ("nsinit")
33
34
35 /*******************************************************************************
36 *
37 * FUNCTION: Acpi_ns_initialize_objects
38 *
39 * PARAMETERS: None
40 *
41 * RETURN: Status
42 *
43 * DESCRIPTION: Walk the entire namespace and perform any necessary
44 * initialization on the objects found therein
45 *
46 ******************************************************************************/
47
48 ACPI_STATUS
49 acpi_ns_initialize_objects (
50 void)
51 {
52 ACPI_STATUS status;
53 ACPI_INIT_WALK_INFO info;
54
55
56 info.field_count = 0;
57 info.field_init = 0;
58 info.op_region_count = 0;
59 info.op_region_init = 0;
60 info.object_count = 0;
61
62
63 /* Walk entire namespace from the supplied root */
64
65 status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
66 ACPI_UINT32_MAX, acpi_ns_init_one_object,
67 &info, NULL);
68
69 return (AE_OK);
70 }
71
72
73 /*******************************************************************************
74 *
75 * FUNCTION: Acpi_ns_initialize_devices
76 *
77 * PARAMETERS: None
78 *
79 * RETURN: ACPI_STATUS
80 *
81 * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
82 * This means running _INI on all present devices.
83 *
84 * Note: We install PCI config space handler on region access,
85 * not here.
86 *
87 ******************************************************************************/
88
89 ACPI_STATUS
90 acpi_ns_initialize_devices (
91 void)
92 {
93 ACPI_STATUS status;
94 ACPI_DEVICE_WALK_INFO info;
95
96
97 info.device_count = 0;
98 info.num_STA = 0;
99 info.num_INI = 0;
100
101
102 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
103 ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL);
104
105
106
107 return (status);
108 }
109
110
111 /*******************************************************************************
112 *
113 * FUNCTION: Acpi_ns_init_one_object
114 *
115 * PARAMETERS: Obj_handle - Node
116 * Level - Current nesting level
117 * Context - Points to a init info struct
118 * Return_value - Not used
119 *
120 * RETURN: Status
121 *
122 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
123 * within the namespace.
124 *
125 * Currently, the only objects that require initialization are:
126 * 1) Methods
127 * 2) Op Regions
128 *
129 ******************************************************************************/
130
131 ACPI_STATUS
132 acpi_ns_init_one_object (
133 ACPI_HANDLE obj_handle,
134 u32 level,
135 void *context,
136 void **return_value)
137 {
138 OBJECT_TYPE_INTERNAL type;
139 ACPI_STATUS status;
140 ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context;
141 ACPI_NAMESPACE_NODE *node = (ACPI_NAMESPACE_NODE *) obj_handle;
142 ACPI_OPERAND_OBJECT *obj_desc;
143
144
145 info->object_count++;
146
147
148 /* And even then, we are only interested in a few object types */
149
150 type = acpi_ns_get_type (obj_handle);
151 obj_desc = node->object;
152 if (!obj_desc) {
153 return (AE_OK);
154 }
155
156 switch (type) {
157
158 case ACPI_TYPE_REGION:
159
160 info->op_region_count++;
161 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
162 break;
163 }
164
165 info->op_region_init++;
166 status = acpi_ds_get_region_arguments (obj_desc);
167
168
169 break;
170
171
172 case ACPI_TYPE_FIELD_UNIT:
173
174 info->field_count++;
175 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
176 break;
177 }
178
179 info->field_init++;
180 status = acpi_ds_get_field_unit_arguments (obj_desc);
181
182
183 break;
184
185 default:
186 break;
187 }
188
189 /*
190 * We ignore errors from above, and always return OK, since
191 * we don't want to abort the walk on a single error.
192 */
193 return (AE_OK);
194 }
195
196
197 /*******************************************************************************
198 *
199 * FUNCTION: Acpi_ns_init_one_device
200 *
201 * PARAMETERS: WALK_CALLBACK
202 *
203 * RETURN: ACPI_STATUS
204 *
205 * DESCRIPTION: This is called once per device soon after ACPI is enabled
206 * to initialize each device. It determines if the device is
207 * present, and if so, calls _INI.
208 *
209 ******************************************************************************/
210
211 ACPI_STATUS
212 acpi_ns_init_one_device (
213 ACPI_HANDLE obj_handle,
214 u32 nesting_level,
215 void *context,
216 void **return_value)
217 {
218 ACPI_STATUS status;
219 ACPI_NAMESPACE_NODE *node;
220 u32 flags;
221 ACPI_DEVICE_WALK_INFO *info = (ACPI_DEVICE_WALK_INFO *) context;
222
223
224
225 info->device_count++;
226
227 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
228
229 node = acpi_ns_convert_handle_to_entry (obj_handle);
230 if (!node) {
231 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
232 return (AE_BAD_PARAMETER);
233 }
234
235 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
236
237 /*
238 * Run _STA to determine if we can run _INI on the device.
239 */
240
241 status = acpi_cm_execute_STA (node, &flags);
242 if (ACPI_FAILURE (status)) {
243 /* Ignore error and move on to next device */
244
245 return (AE_OK);
246 }
247
248 info->num_STA++;
249
250 if (!(flags & 0x01)) {
251 /* don't look at children of a not present device */
252 return(AE_CTRL_DEPTH);
253 }
254
255
256 /*
257 * The device is present. Run _INI.
258 */
259
260 status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
261 if (AE_NOT_FOUND == status) {
262 /* No _INI means device requires no initialization */
263 status = AE_OK;
264 }
265
266 else if (ACPI_FAILURE (status)) {
267 /* Ignore error and move on to next device */
268
269 }
270
271 else {
272 /* Count of successful INIs */
273
274 info->num_INI++;
275 }
276
277 return (AE_OK);
278 }