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
29 #define _COMPONENT ACPI_EVENTS
30 MODULE_NAME ("evrgnini")
33 /*****************************************************************************
35 * FUNCTION: Acpi_ev_system_memory_region_setup
37 * PARAMETERS: Region_obj - region we are interested in
38 * Function - start or stop
39 * Handler_context - Address space handler context
40 * Region_context - Region specific context
44 * DESCRIPTION: Do any prep work for region handling, a nop for now
46 ****************************************************************************/
49 acpi_ev_system_memory_region_setup (
52 void *handler_context
,
53 void **region_context
)
56 if (function
== ACPI_REGION_DEACTIVATE
) {
57 if (*region_context
) {
58 acpi_cm_free (*region_context
);
59 *region_context
= NULL
;
65 /* Activate. Create a new context */
67 *region_context
= acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT
));
68 if (!(*region_context
)) {
69 return (AE_NO_MEMORY
);
76 /*****************************************************************************
78 * FUNCTION: Acpi_ev_io_space_region_setup
80 * PARAMETERS: Region_obj - region we are interested in
81 * Function - start or stop
82 * Handler_context - Address space handler context
83 * Region_context - Region specific context
87 * DESCRIPTION: Do any prep work for region handling
89 ****************************************************************************/
92 acpi_ev_io_space_region_setup (
95 void *handler_context
,
96 void **region_context
)
98 if (function
== ACPI_REGION_DEACTIVATE
) {
99 *region_context
= NULL
;
102 *region_context
= handler_context
;
109 /*****************************************************************************
111 * FUNCTION: Acpi_ev_pci_config_region_setup
113 * PARAMETERS: Region_obj - region we are interested in
114 * Function - start or stop
115 * Handler_context - Address space handler context
116 * Region_context - Region specific context
120 * DESCRIPTION: Do any prep work for region handling
122 * MUTEX: Assumes namespace is not locked
124 ****************************************************************************/
127 acpi_ev_pci_config_region_setup (
130 void *handler_context
,
131 void **region_context
)
133 ACPI_STATUS status
= AE_OK
;
135 PCI_HANDLER_CONTEXT
*pci_context
= *region_context
;
136 ACPI_OPERAND_OBJECT
*handler_obj
;
137 ACPI_NAMESPACE_NODE
*node
;
138 ACPI_OPERAND_OBJECT
*region_obj
= (ACPI_OPERAND_OBJECT
*) handle
;
139 DEVICE_ID object_hID
;
141 handler_obj
= region_obj
->region
.addr_handler
;
145 * No installed handler. This shouldn't happen because the dispatch
146 * routine checks before we get here, but we check again just in case.
148 return(AE_NOT_EXIST
);
151 if (function
== ACPI_REGION_DEACTIVATE
) {
153 acpi_cm_free (pci_context
);
154 *region_context
= NULL
;
161 /* Create a new context */
163 pci_context
= acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT
));
165 return (AE_NO_MEMORY
);
169 * For PCI Config space access, we have to pass the segment, bus,
170 * device and function numbers. This routine must acquire those.
174 * First get device and function numbers from the _ADR object
175 * in the parent's scope.
177 ACPI_ASSERT(region_obj
->region
.node
);
179 node
= acpi_ns_get_parent_object (region_obj
->region
.node
);
182 /* Acpi_evaluate the _ADR object */
184 status
= acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR
, node
, &temp
);
186 * The default is zero, since the allocation above zeroed the data, just
187 * do nothing on failures.
189 if (ACPI_SUCCESS (status
)) {
193 pci_context
->dev_func
= (u32
) temp
;
197 * Get the _SEG and _BBN values from the device upon which the handler
200 * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
201 * This is the device the handler has been registered to handle.
205 * If the Addr_handler.Node is still pointing to the root, we need
206 * to scan upward for a PCI Root bridge and re-associate the Op_region
207 * handlers with that device.
209 if (handler_obj
->addr_handler
.node
== acpi_gbl_root_node
) {
211 * Node is currently the parent object
213 while (node
!= acpi_gbl_root_node
) {
214 status
= acpi_cm_execute_HID(node
, &object_hID
);
216 if (ACPI_SUCCESS (status
)) {
217 if (!(STRNCMP(object_hID
.buffer
, PCI_ROOT_HID_STRING
,
218 sizeof (PCI_ROOT_HID_STRING
)))) {
219 acpi_install_address_space_handler(node
,
220 ADDRESS_SPACE_PCI_CONFIG
,
221 ACPI_DEFAULT_HANDLER
, NULL
, NULL
);
227 node
= acpi_ns_get_parent_object(node
);
231 node
= handler_obj
->addr_handler
.node
;
234 status
= acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG
, node
, &temp
);
235 if (ACPI_SUCCESS (status
)) {
239 pci_context
->seg
= (u32
) temp
;
242 status
= acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN
, node
, &temp
);
243 if (ACPI_SUCCESS (status
)) {
247 pci_context
->bus
= (u32
) temp
;
250 *region_context
= pci_context
;
256 /*****************************************************************************
258 * FUNCTION: Acpi_ev_default_region_setup
260 * PARAMETERS: Region_obj - region we are interested in
261 * Function - start or stop
262 * Handler_context - Address space handler context
263 * Region_context - Region specific context
267 * DESCRIPTION: Do any prep work for region handling
269 ****************************************************************************/
272 acpi_ev_default_region_setup (
275 void *handler_context
,
276 void **region_context
)
278 if (function
== ACPI_REGION_DEACTIVATE
) {
279 *region_context
= NULL
;
282 *region_context
= handler_context
;
289 /******************************************************************************
291 * FUNCTION: Acpi_ev_initialize_region
293 * PARAMETERS: Region_obj - Region we are initializing
297 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
298 * for execution at a later time
300 * Get the appropriate address space handler for a newly
303 * This also performs address space specific intialization. For
304 * example, PCI regions must have an _ADR object that contains
305 * a PCI address in the scope of the defintion. This address is
306 * required to perform an access to PCI config space.
308 ******************************************************************************/
311 acpi_ev_initialize_region (
312 ACPI_OPERAND_OBJECT
*region_obj
,
315 ACPI_OPERAND_OBJECT
*handler_obj
;
316 ACPI_OPERAND_OBJECT
*obj_desc
;
317 ACPI_ADDRESS_SPACE_TYPE space_id
;
318 ACPI_NAMESPACE_NODE
*node
;
320 ACPI_NAMESPACE_NODE
*method_node
;
321 ACPI_NAME
*reg_name_ptr
= (ACPI_NAME
*) METHOD_NAME__REG
;
325 return (AE_BAD_PARAMETER
);
328 ACPI_ASSERT(region_obj
->region
.node
);
330 node
= acpi_ns_get_parent_object (region_obj
->region
.node
);
331 space_id
= region_obj
->region
.space_id
;
333 region_obj
->region
.addr_handler
= NULL
;
334 region_obj
->region
.extra
->extra
.method_REG
= NULL
;
335 region_obj
->region
.flags
&= ~(AOPOBJ_INITIALIZED
);
338 * Find any "_REG" associated with this region definition
340 status
= acpi_ns_search_node (*reg_name_ptr
, node
,
341 ACPI_TYPE_METHOD
, &method_node
);
342 if (ACPI_SUCCESS (status
)) {
344 * The _REG method is optional and there can be only one per region
345 * definition. This will be executed when the handler is attached
348 region_obj
->region
.extra
->extra
.method_REG
= method_node
;
352 * The following loop depends upon the root Node having no parent
353 * ie: Acpi_gbl_Root_node->Parent_entry being set to NULL
357 * Check to see if a handler exists
360 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
363 * can only be a handler if the object exists
365 switch (node
->type
) {
366 case ACPI_TYPE_DEVICE
:
368 handler_obj
= obj_desc
->device
.addr_handler
;
371 case ACPI_TYPE_PROCESSOR
:
373 handler_obj
= obj_desc
->processor
.addr_handler
;
376 case ACPI_TYPE_THERMAL
:
378 handler_obj
= obj_desc
->thermal_zone
.addr_handler
;
382 while (handler_obj
) {
384 * This guy has at least one address handler
385 * see if it has the type we want
387 if (handler_obj
->addr_handler
.space_id
== space_id
) {
389 * Found it! Now update the region and the handler
391 acpi_ev_associate_region_and_handler (handler_obj
, region_obj
, acpi_ns_locked
);
395 handler_obj
= handler_obj
->addr_handler
.next
;
397 } /* while handlerobj */
401 * This one does not have the handler we need
404 node
= acpi_ns_get_parent_object (node
);
406 } /* while Node != ROOT */
409 * If we get here, there is no handler for this region
411 return (AE_NOT_EXIST
);