:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / namespace / nsinit.c
1 /******************************************************************************
2  *
3  * Module Name: nsinit - namespace initialization
4  *              $Revision$
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 }