minor corrections by M.Taguchi
[reactos.git] / reactos / drivers / bus / acpi / events / evrgnini.c
1 /******************************************************************************
2 *
3 * Module Name: evrgnini- ACPI Address_space (Op_region) init
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 "acevents.h"
29 #include "acnamesp.h"
30 #include "acinterp.h"
31 #include "amlcode.h"
32
33 #define _COMPONENT ACPI_EVENTS
34 MODULE_NAME ("evrgnini")
35
36
37 /*****************************************************************************
38 *
39 * FUNCTION: Acpi_ev_system_memory_region_setup
40 *
41 * PARAMETERS: Region_obj - region we are interested in
42 * Function - start or stop
43 * Handler_context - Address space handler context
44 * Region_context - Region specific context
45 *
46 * RETURN: Status
47 *
48 * DESCRIPTION: Do any prep work for region handling, a nop for now
49 *
50 ****************************************************************************/
51
52 ACPI_STATUS
53 acpi_ev_system_memory_region_setup (
54 ACPI_HANDLE handle,
55 u32 function,
56 void *handler_context,
57 void **region_context)
58 {
59
60 if (function == ACPI_REGION_DEACTIVATE) {
61 if (*region_context) {
62 acpi_cm_free (*region_context);
63 *region_context = NULL;
64 }
65 return (AE_OK);
66 }
67
68
69 /* Activate. Create a new context */
70
71 *region_context = acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT));
72 if (!(*region_context)) {
73 return (AE_NO_MEMORY);
74 }
75
76 return (AE_OK);
77 }
78
79
80 /*****************************************************************************
81 *
82 * FUNCTION: Acpi_ev_io_space_region_setup
83 *
84 * PARAMETERS: Region_obj - region we are interested in
85 * Function - start or stop
86 * Handler_context - Address space handler context
87 * Region_context - Region specific context
88 *
89 * RETURN: Status
90 *
91 * DESCRIPTION: Do any prep work for region handling
92 *
93 ****************************************************************************/
94
95 ACPI_STATUS
96 acpi_ev_io_space_region_setup (
97 ACPI_HANDLE handle,
98 u32 function,
99 void *handler_context,
100 void **region_context)
101 {
102 if (function == ACPI_REGION_DEACTIVATE) {
103 *region_context = NULL;
104 }
105 else {
106 *region_context = handler_context;
107 }
108
109 return (AE_OK);
110 }
111
112
113 /*****************************************************************************
114 *
115 * FUNCTION: Acpi_ev_pci_config_region_setup
116 *
117 * PARAMETERS: Region_obj - region we are interested in
118 * Function - start or stop
119 * Handler_context - Address space handler context
120 * Region_context - Region specific context
121 *
122 * RETURN: Status
123 *
124 * DESCRIPTION: Do any prep work for region handling
125 *
126 * MUTEX: Assumes namespace is not locked
127 *
128 ****************************************************************************/
129
130 ACPI_STATUS
131 acpi_ev_pci_config_region_setup (
132 ACPI_HANDLE handle,
133 u32 function,
134 void *handler_context,
135 void **region_context)
136 {
137 ACPI_STATUS status = AE_OK;
138 ACPI_INTEGER temp;
139 PCI_HANDLER_CONTEXT *pci_context = *region_context;
140 ACPI_OPERAND_OBJECT *handler_obj;
141 ACPI_NAMESPACE_NODE *node;
142 ACPI_OPERAND_OBJECT *region_obj = (ACPI_OPERAND_OBJECT *) handle;
143 DEVICE_ID object_hID;
144
145 handler_obj = region_obj->region.addr_handler;
146
147 if (!handler_obj) {
148 /*
149 * No installed handler. This shouldn't happen because the dispatch
150 * routine checks before we get here, but we check again just in case.
151 */
152 return(AE_NOT_EXIST);
153 }
154
155 if (function == ACPI_REGION_DEACTIVATE) {
156 if (pci_context) {
157 acpi_cm_free (pci_context);
158 *region_context = NULL;
159 }
160
161 return (status);
162 }
163
164
165 /* Create a new context */
166
167 pci_context = acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT));
168 if (!pci_context) {
169 return (AE_NO_MEMORY);
170 }
171
172 /*
173 * For PCI Config space access, we have to pass the segment, bus,
174 * device and function numbers. This routine must acquire those.
175 */
176
177 /*
178 * First get device and function numbers from the _ADR object
179 * in the parent's scope.
180 */
181 ACPI_ASSERT(region_obj->region.node);
182
183 node = acpi_ns_get_parent_object (region_obj->region.node);
184
185
186 /* Acpi_evaluate the _ADR object */
187
188 status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp);
189 /*
190 * The default is zero, since the allocation above zeroed the data, just
191 * do nothing on failures.
192 */
193 if (ACPI_SUCCESS (status)) {
194 /*
195 * Got it..
196 */
197 pci_context->dev_func = (u32) temp;
198 }
199
200 /*
201 * Get the _SEG and _BBN values from the device upon which the handler
202 * is installed.
203 *
204 * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
205 * This is the device the handler has been registered to handle.
206 */
207
208 /*
209 * If the Addr_handler.Node is still pointing to the root, we need
210 * to scan upward for a PCI Root bridge and re-associate the Op_region
211 * handlers with that device.
212 */
213 if (handler_obj->addr_handler.node == acpi_gbl_root_node) {
214 /*
215 * Node is currently the parent object
216 */
217 while (node != acpi_gbl_root_node) {
218 status = acpi_cm_execute_HID(node, &object_hID);
219
220 if (ACPI_SUCCESS (status)) {
221 if (!(STRNCMP(object_hID.buffer, PCI_ROOT_HID_STRING,
222 sizeof (PCI_ROOT_HID_STRING)))) {
223 acpi_install_address_space_handler(node,
224 ADDRESS_SPACE_PCI_CONFIG,
225 ACPI_DEFAULT_HANDLER, NULL, NULL);
226
227 break;
228 }
229 }
230
231 node = acpi_ns_get_parent_object(node);
232 }
233 }
234 else {
235 node = handler_obj->addr_handler.node;
236 }
237
238 status = acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp);
239 if (ACPI_SUCCESS (status)) {
240 /*
241 * Got it..
242 */
243 pci_context->seg = (u32) temp;
244 }
245
246 status = acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp);
247 if (ACPI_SUCCESS (status)) {
248 /*
249 * Got it..
250 */
251 pci_context->bus = (u32) temp;
252 }
253
254 *region_context = pci_context;
255
256 return (AE_OK);
257 }
258
259
260 /*****************************************************************************
261 *
262 * FUNCTION: Acpi_ev_default_region_setup
263 *
264 * PARAMETERS: Region_obj - region we are interested in
265 * Function - start or stop
266 * Handler_context - Address space handler context
267 * Region_context - Region specific context
268 *
269 * RETURN: Status
270 *
271 * DESCRIPTION: Do any prep work for region handling
272 *
273 ****************************************************************************/
274
275 ACPI_STATUS
276 acpi_ev_default_region_setup (
277 ACPI_HANDLE handle,
278 u32 function,
279 void *handler_context,
280 void **region_context)
281 {
282 if (function == ACPI_REGION_DEACTIVATE) {
283 *region_context = NULL;
284 }
285 else {
286 *region_context = handler_context;
287 }
288
289 return (AE_OK);
290 }
291
292
293 /******************************************************************************
294 *
295 * FUNCTION: Acpi_ev_initialize_region
296 *
297 * PARAMETERS: Region_obj - Region we are initializing
298 *
299 * RETURN: Status
300 *
301 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
302 * for execution at a later time
303 *
304 * Get the appropriate address space handler for a newly
305 * created region.
306 *
307 * This also performs address space specific intialization. For
308 * example, PCI regions must have an _ADR object that contains
309 * a PCI address in the scope of the defintion. This address is
310 * required to perform an access to PCI config space.
311 *
312 ******************************************************************************/
313
314 ACPI_STATUS
315 acpi_ev_initialize_region (
316 ACPI_OPERAND_OBJECT *region_obj,
317 u8 acpi_ns_locked)
318 {
319 ACPI_OPERAND_OBJECT *handler_obj;
320 ACPI_OPERAND_OBJECT *obj_desc;
321 ACPI_ADDRESS_SPACE_TYPE space_id;
322 ACPI_NAMESPACE_NODE *node;
323 ACPI_STATUS status;
324 ACPI_NAMESPACE_NODE *method_node;
325 ACPI_NAME *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG;
326
327
328 if (!region_obj) {
329 return (AE_BAD_PARAMETER);
330 }
331
332 ACPI_ASSERT(region_obj->region.node);
333
334 node = acpi_ns_get_parent_object (region_obj->region.node);
335 space_id = region_obj->region.space_id;
336
337 region_obj->region.addr_handler = NULL;
338 region_obj->region.extra->extra.method_REG = NULL;
339 region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);
340
341 /*
342 * Find any "_REG" associated with this region definition
343 */
344 status = acpi_ns_search_node (*reg_name_ptr, node,
345 ACPI_TYPE_METHOD, &method_node);
346 if (ACPI_SUCCESS (status)) {
347 /*
348 * The _REG method is optional and there can be only one per region
349 * definition. This will be executed when the handler is attached
350 * or removed
351 */
352 region_obj->region.extra->extra.method_REG = method_node;
353 }
354
355 /*
356 * The following loop depends upon the root Node having no parent
357 * ie: Acpi_gbl_Root_node->Parent_entry being set to NULL
358 */
359 while (node) {
360 /*
361 * Check to see if a handler exists
362 */
363 handler_obj = NULL;
364 obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
365 if (obj_desc) {
366 /*
367 * can only be a handler if the object exists
368 */
369 switch (node->type) {
370 case ACPI_TYPE_DEVICE:
371
372 handler_obj = obj_desc->device.addr_handler;
373 break;
374
375 case ACPI_TYPE_PROCESSOR:
376
377 handler_obj = obj_desc->processor.addr_handler;
378 break;
379
380 case ACPI_TYPE_THERMAL:
381
382 handler_obj = obj_desc->thermal_zone.addr_handler;
383 break;
384 }
385
386 while (handler_obj) {
387 /*
388 * This guy has at least one address handler
389 * see if it has the type we want
390 */
391 if (handler_obj->addr_handler.space_id == space_id) {
392 /*
393 * Found it! Now update the region and the handler
394 */
395 acpi_ev_associate_region_and_handler (handler_obj, region_obj, acpi_ns_locked);
396 return (AE_OK);
397 }
398
399 handler_obj = handler_obj->addr_handler.next;
400
401 } /* while handlerobj */
402 }
403
404 /*
405 * This one does not have the handler we need
406 * Pop up one level
407 */
408 node = acpi_ns_get_parent_object (node);
409
410 } /* while Node != ROOT */
411
412 /*
413 * If we get here, there is no handler for this region
414 */
415 return (AE_NOT_EXIST);
416 }
417