1 /******************************************************************************
3 * Module Name: evrgnini- ACPI Address_space (Op_region) init
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
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.
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.
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
33 #define _COMPONENT ACPI_EVENTS
34 MODULE_NAME ("evrgnini")
37 /*****************************************************************************
39 * FUNCTION: Acpi_ev_system_memory_region_setup
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
48 * DESCRIPTION: Do any prep work for region handling, a nop for now
50 ****************************************************************************/
53 acpi_ev_system_memory_region_setup (
56 void *handler_context
,
57 void **region_context
)
60 if (function
== ACPI_REGION_DEACTIVATE
) {
61 if (*region_context
) {
62 acpi_cm_free (*region_context
);
63 *region_context
= NULL
;
69 /* Activate. Create a new context */
71 *region_context
= acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT
));
72 if (!(*region_context
)) {
73 return (AE_NO_MEMORY
);
80 /*****************************************************************************
82 * FUNCTION: Acpi_ev_io_space_region_setup
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
91 * DESCRIPTION: Do any prep work for region handling
93 ****************************************************************************/
96 acpi_ev_io_space_region_setup (
99 void *handler_context
,
100 void **region_context
)
102 if (function
== ACPI_REGION_DEACTIVATE
) {
103 *region_context
= NULL
;
106 *region_context
= handler_context
;
113 /*****************************************************************************
115 * FUNCTION: Acpi_ev_pci_config_region_setup
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
124 * DESCRIPTION: Do any prep work for region handling
126 * MUTEX: Assumes namespace is not locked
128 ****************************************************************************/
131 acpi_ev_pci_config_region_setup (
134 void *handler_context
,
135 void **region_context
)
137 ACPI_STATUS status
= AE_OK
;
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
;
145 handler_obj
= region_obj
->region
.addr_handler
;
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.
152 return(AE_NOT_EXIST
);
155 if (function
== ACPI_REGION_DEACTIVATE
) {
157 acpi_cm_free (pci_context
);
158 *region_context
= NULL
;
165 /* Create a new context */
167 pci_context
= acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT
));
169 return (AE_NO_MEMORY
);
173 * For PCI Config space access, we have to pass the segment, bus,
174 * device and function numbers. This routine must acquire those.
178 * First get device and function numbers from the _ADR object
179 * in the parent's scope.
181 ACPI_ASSERT(region_obj
->region
.node
);
183 node
= acpi_ns_get_parent_object (region_obj
->region
.node
);
186 /* Acpi_evaluate the _ADR object */
188 status
= acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR
, node
, &temp
);
190 * The default is zero, since the allocation above zeroed the data, just
191 * do nothing on failures.
193 if (ACPI_SUCCESS (status
)) {
197 pci_context
->dev_func
= (u32
) temp
;
201 * Get the _SEG and _BBN values from the device upon which the handler
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.
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.
213 if (handler_obj
->addr_handler
.node
== acpi_gbl_root_node
) {
215 * Node is currently the parent object
217 while (node
!= acpi_gbl_root_node
) {
218 status
= acpi_cm_execute_HID(node
, &object_hID
);
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
);
231 node
= acpi_ns_get_parent_object(node
);
235 node
= handler_obj
->addr_handler
.node
;
238 status
= acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG
, node
, &temp
);
239 if (ACPI_SUCCESS (status
)) {
243 pci_context
->seg
= (u32
) temp
;
246 status
= acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN
, node
, &temp
);
247 if (ACPI_SUCCESS (status
)) {
251 pci_context
->bus
= (u32
) temp
;
254 *region_context
= pci_context
;
260 /*****************************************************************************
262 * FUNCTION: Acpi_ev_default_region_setup
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
271 * DESCRIPTION: Do any prep work for region handling
273 ****************************************************************************/
276 acpi_ev_default_region_setup (
279 void *handler_context
,
280 void **region_context
)
282 if (function
== ACPI_REGION_DEACTIVATE
) {
283 *region_context
= NULL
;
286 *region_context
= handler_context
;
293 /******************************************************************************
295 * FUNCTION: Acpi_ev_initialize_region
297 * PARAMETERS: Region_obj - Region we are initializing
301 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
302 * for execution at a later time
304 * Get the appropriate address space handler for a newly
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.
312 ******************************************************************************/
315 acpi_ev_initialize_region (
316 ACPI_OPERAND_OBJECT
*region_obj
,
319 ACPI_OPERAND_OBJECT
*handler_obj
;
320 ACPI_OPERAND_OBJECT
*obj_desc
;
321 ACPI_ADDRESS_SPACE_TYPE space_id
;
322 ACPI_NAMESPACE_NODE
*node
;
324 ACPI_NAMESPACE_NODE
*method_node
;
325 ACPI_NAME
*reg_name_ptr
= (ACPI_NAME
*) METHOD_NAME__REG
;
329 return (AE_BAD_PARAMETER
);
332 ACPI_ASSERT(region_obj
->region
.node
);
334 node
= acpi_ns_get_parent_object (region_obj
->region
.node
);
335 space_id
= region_obj
->region
.space_id
;
337 region_obj
->region
.addr_handler
= NULL
;
338 region_obj
->region
.extra
->extra
.method_REG
= NULL
;
339 region_obj
->region
.flags
&= ~(AOPOBJ_INITIALIZED
);
342 * Find any "_REG" associated with this region definition
344 status
= acpi_ns_search_node (*reg_name_ptr
, node
,
345 ACPI_TYPE_METHOD
, &method_node
);
346 if (ACPI_SUCCESS (status
)) {
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
352 region_obj
->region
.extra
->extra
.method_REG
= method_node
;
356 * The following loop depends upon the root Node having no parent
357 * ie: Acpi_gbl_Root_node->Parent_entry being set to NULL
361 * Check to see if a handler exists
364 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
367 * can only be a handler if the object exists
369 switch (node
->type
) {
370 case ACPI_TYPE_DEVICE
:
372 handler_obj
= obj_desc
->device
.addr_handler
;
375 case ACPI_TYPE_PROCESSOR
:
377 handler_obj
= obj_desc
->processor
.addr_handler
;
380 case ACPI_TYPE_THERMAL
:
382 handler_obj
= obj_desc
->thermal_zone
.addr_handler
;
386 while (handler_obj
) {
388 * This guy has at least one address handler
389 * see if it has the type we want
391 if (handler_obj
->addr_handler
.space_id
== space_id
) {
393 * Found it! Now update the region and the handler
395 acpi_ev_associate_region_and_handler (handler_obj
, region_obj
, acpi_ns_locked
);
399 handler_obj
= handler_obj
->addr_handler
.next
;
401 } /* while handlerobj */
405 * This one does not have the handler we need
408 node
= acpi_ns_get_parent_object (node
);
410 } /* while Node != ROOT */
413 * If we get here, there is no handler for this region
415 return (AE_NOT_EXIST
);