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