1*95857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 295b482a8SLen Brown /****************************************************************************** 395b482a8SLen Brown * 495b482a8SLen Brown * Module Name: evrgnini- ACPI address_space (op_region) init 595b482a8SLen Brown * 6da6f8320SBob Moore * Copyright (C) 2000 - 2018, Intel Corp. 795b482a8SLen Brown * 8*95857638SErik Schmauss *****************************************************************************/ 995b482a8SLen Brown 1095b482a8SLen Brown #include <acpi/acpi.h> 11e2f7a777SLen Brown #include "accommon.h" 12e2f7a777SLen Brown #include "acevents.h" 13e2f7a777SLen Brown #include "acnamesp.h" 148633db6bSLv Zheng #include "acinterp.h" 1595b482a8SLen Brown 1695b482a8SLen Brown #define _COMPONENT ACPI_EVENTS 1795b482a8SLen Brown ACPI_MODULE_NAME("evrgnini") 1895b482a8SLen Brown 1995b482a8SLen Brown /* Local prototypes */ 2095b482a8SLen Brown static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); 2195b482a8SLen Brown 2295b482a8SLen Brown /******************************************************************************* 2395b482a8SLen Brown * 2495b482a8SLen Brown * FUNCTION: acpi_ev_system_memory_region_setup 2595b482a8SLen Brown * 26ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 27ba494beeSBob Moore * function - Start or stop 2895b482a8SLen Brown * handler_context - Address space handler context 2995b482a8SLen Brown * region_context - Region specific context 3095b482a8SLen Brown * 3195b482a8SLen Brown * RETURN: Status 3295b482a8SLen Brown * 3395b482a8SLen Brown * DESCRIPTION: Setup a system_memory operation region 3495b482a8SLen Brown * 3595b482a8SLen Brown ******************************************************************************/ 3695b482a8SLen Brown 3795b482a8SLen Brown acpi_status 3895b482a8SLen Brown acpi_ev_system_memory_region_setup(acpi_handle handle, 3995b482a8SLen Brown u32 function, 4095b482a8SLen Brown void *handler_context, void **region_context) 4195b482a8SLen Brown { 4295b482a8SLen Brown union acpi_operand_object *region_desc = 4395b482a8SLen Brown (union acpi_operand_object *)handle; 4495b482a8SLen Brown struct acpi_mem_space_context *local_region_context; 4595b482a8SLen Brown 4695b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); 4795b482a8SLen Brown 4895b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 4995b482a8SLen Brown if (*region_context) { 5095b482a8SLen Brown local_region_context = 5195b482a8SLen Brown (struct acpi_mem_space_context *)*region_context; 5295b482a8SLen Brown 5395b482a8SLen Brown /* Delete a cached mapping if present */ 5495b482a8SLen Brown 5595b482a8SLen Brown if (local_region_context->mapped_length) { 5695b482a8SLen Brown acpi_os_unmap_memory(local_region_context-> 5795b482a8SLen Brown mapped_logical_address, 5895b482a8SLen Brown local_region_context-> 5995b482a8SLen Brown mapped_length); 6095b482a8SLen Brown } 6195b482a8SLen Brown ACPI_FREE(local_region_context); 6295b482a8SLen Brown *region_context = NULL; 6395b482a8SLen Brown } 6495b482a8SLen Brown return_ACPI_STATUS(AE_OK); 6595b482a8SLen Brown } 6695b482a8SLen Brown 6795b482a8SLen Brown /* Create a new context */ 6895b482a8SLen Brown 6995b482a8SLen Brown local_region_context = 7095b482a8SLen Brown ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); 7195b482a8SLen Brown if (!(local_region_context)) { 7295b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 7395b482a8SLen Brown } 7495b482a8SLen Brown 7595b482a8SLen Brown /* Save the region length and address for use in the handler */ 7695b482a8SLen Brown 7795b482a8SLen Brown local_region_context->length = region_desc->region.length; 7895b482a8SLen Brown local_region_context->address = region_desc->region.address; 7995b482a8SLen Brown 8095b482a8SLen Brown *region_context = local_region_context; 8195b482a8SLen Brown return_ACPI_STATUS(AE_OK); 8295b482a8SLen Brown } 8395b482a8SLen Brown 8495b482a8SLen Brown /******************************************************************************* 8595b482a8SLen Brown * 8695b482a8SLen Brown * FUNCTION: acpi_ev_io_space_region_setup 8795b482a8SLen Brown * 88ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 89ba494beeSBob Moore * function - Start or stop 9095b482a8SLen Brown * handler_context - Address space handler context 9195b482a8SLen Brown * region_context - Region specific context 9295b482a8SLen Brown * 9395b482a8SLen Brown * RETURN: Status 9495b482a8SLen Brown * 9595b482a8SLen Brown * DESCRIPTION: Setup a IO operation region 9695b482a8SLen Brown * 9795b482a8SLen Brown ******************************************************************************/ 9895b482a8SLen Brown 9995b482a8SLen Brown acpi_status 10095b482a8SLen Brown acpi_ev_io_space_region_setup(acpi_handle handle, 10195b482a8SLen Brown u32 function, 10295b482a8SLen Brown void *handler_context, void **region_context) 10395b482a8SLen Brown { 10495b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_io_space_region_setup); 10595b482a8SLen Brown 10695b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 10795b482a8SLen Brown *region_context = NULL; 10895b482a8SLen Brown } else { 10995b482a8SLen Brown *region_context = handler_context; 11095b482a8SLen Brown } 11195b482a8SLen Brown 11295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 11395b482a8SLen Brown } 11495b482a8SLen Brown 11595b482a8SLen Brown /******************************************************************************* 11695b482a8SLen Brown * 11795b482a8SLen Brown * FUNCTION: acpi_ev_pci_config_region_setup 11895b482a8SLen Brown * 119ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 120ba494beeSBob Moore * function - Start or stop 12195b482a8SLen Brown * handler_context - Address space handler context 12295b482a8SLen Brown * region_context - Region specific context 12395b482a8SLen Brown * 12495b482a8SLen Brown * RETURN: Status 12595b482a8SLen Brown * 12695b482a8SLen Brown * DESCRIPTION: Setup a PCI_Config operation region 12795b482a8SLen Brown * 12895b482a8SLen Brown * MUTEX: Assumes namespace is not locked 12995b482a8SLen Brown * 13095b482a8SLen Brown ******************************************************************************/ 13195b482a8SLen Brown 13295b482a8SLen Brown acpi_status 13395b482a8SLen Brown acpi_ev_pci_config_region_setup(acpi_handle handle, 13495b482a8SLen Brown u32 function, 13595b482a8SLen Brown void *handler_context, void **region_context) 13695b482a8SLen Brown { 13795b482a8SLen Brown acpi_status status = AE_OK; 1385df7e6cbSBob Moore u64 pci_value; 13995b482a8SLen Brown struct acpi_pci_id *pci_id = *region_context; 14095b482a8SLen Brown union acpi_operand_object *handler_obj; 14195b482a8SLen Brown struct acpi_namespace_node *parent_node; 14295b482a8SLen Brown struct acpi_namespace_node *pci_root_node; 14395b482a8SLen Brown struct acpi_namespace_node *pci_device_node; 14495b482a8SLen Brown union acpi_operand_object *region_obj = 14595b482a8SLen Brown (union acpi_operand_object *)handle; 14695b482a8SLen Brown 14795b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); 14895b482a8SLen Brown 14995b482a8SLen Brown handler_obj = region_obj->region.handler; 15095b482a8SLen Brown if (!handler_obj) { 15195b482a8SLen Brown /* 15295b482a8SLen Brown * No installed handler. This shouldn't happen because the dispatch 15395b482a8SLen Brown * routine checks before we get here, but we check again just in case. 15495b482a8SLen Brown */ 15595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 15695b482a8SLen Brown "Attempting to init a region %p, with no handler\n", 15795b482a8SLen Brown region_obj)); 15895b482a8SLen Brown return_ACPI_STATUS(AE_NOT_EXIST); 15995b482a8SLen Brown } 16095b482a8SLen Brown 16195b482a8SLen Brown *region_context = NULL; 16295b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 16395b482a8SLen Brown if (pci_id) { 16495b482a8SLen Brown ACPI_FREE(pci_id); 16595b482a8SLen Brown } 16695b482a8SLen Brown return_ACPI_STATUS(status); 16795b482a8SLen Brown } 16895b482a8SLen Brown 169c45b5c09SAlexey Starikovskiy parent_node = region_obj->region.node->parent; 17095b482a8SLen Brown 17195b482a8SLen Brown /* 17295b482a8SLen Brown * Get the _SEG and _BBN values from the device upon which the handler 17395b482a8SLen Brown * is installed. 17495b482a8SLen Brown * 17595b482a8SLen Brown * We need to get the _SEG and _BBN objects relative to the PCI BUS device. 17695b482a8SLen Brown * This is the device the handler has been registered to handle. 17795b482a8SLen Brown */ 17895b482a8SLen Brown 17995b482a8SLen Brown /* 18095b482a8SLen Brown * If the address_space.Node is still pointing to the root, we need 18195b482a8SLen Brown * to scan upward for a PCI Root bridge and re-associate the op_region 18295b482a8SLen Brown * handlers with that device. 18395b482a8SLen Brown */ 18495b482a8SLen Brown if (handler_obj->address_space.node == acpi_gbl_root_node) { 18595b482a8SLen Brown 18695b482a8SLen Brown /* Start search from the parent object */ 18795b482a8SLen Brown 18895b482a8SLen Brown pci_root_node = parent_node; 18995b482a8SLen Brown while (pci_root_node != acpi_gbl_root_node) { 19095b482a8SLen Brown 19195b482a8SLen Brown /* Get the _HID/_CID in order to detect a root_bridge */ 19295b482a8SLen Brown 19395b482a8SLen Brown if (acpi_ev_is_pci_root_bridge(pci_root_node)) { 19495b482a8SLen Brown 19595b482a8SLen Brown /* Install a handler for this PCI root bridge */ 19695b482a8SLen Brown 1971f86e8c1SLv Zheng status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); 19895b482a8SLen Brown if (ACPI_FAILURE(status)) { 19995b482a8SLen Brown if (status == AE_SAME_HANDLER) { 20095b482a8SLen Brown /* 20195b482a8SLen Brown * It is OK if the handler is already installed on the 20295b482a8SLen Brown * root bridge. Still need to return a context object 20395b482a8SLen Brown * for the new PCI_Config operation region, however. 20495b482a8SLen Brown */ 20595b482a8SLen Brown status = AE_OK; 20695b482a8SLen Brown } else { 20795b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 208d4913dc6SBob Moore "Could not install PciConfig handler " 209d4913dc6SBob Moore "for Root Bridge %4.4s", 21095b482a8SLen Brown acpi_ut_get_node_name 21195b482a8SLen Brown (pci_root_node))); 21295b482a8SLen Brown } 21395b482a8SLen Brown } 21495b482a8SLen Brown break; 21595b482a8SLen Brown } 21695b482a8SLen Brown 217c45b5c09SAlexey Starikovskiy pci_root_node = pci_root_node->parent; 21895b482a8SLen Brown } 21995b482a8SLen Brown 22095b482a8SLen Brown /* PCI root bridge not found, use namespace root node */ 22195b482a8SLen Brown } else { 22295b482a8SLen Brown pci_root_node = handler_obj->address_space.node; 22395b482a8SLen Brown } 22495b482a8SLen Brown 22595b482a8SLen Brown /* 22695b482a8SLen Brown * If this region is now initialized, we are done. 22795b482a8SLen Brown * (install_address_space_handler could have initialized it) 22895b482a8SLen Brown */ 22995b482a8SLen Brown if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { 23095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 23195b482a8SLen Brown } 23295b482a8SLen Brown 23395b482a8SLen Brown /* Region is still not initialized. Create a new context */ 23495b482a8SLen Brown 23595b482a8SLen Brown pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); 23695b482a8SLen Brown if (!pci_id) { 23795b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 23895b482a8SLen Brown } 23995b482a8SLen Brown 24095b482a8SLen Brown /* 24195b482a8SLen Brown * For PCI_Config space access, we need the segment, bus, device and 24295b482a8SLen Brown * function numbers. Acquire them here. 24395b482a8SLen Brown * 24495b482a8SLen Brown * Find the parent device object. (This allows the operation region to be 24595b482a8SLen Brown * within a subscope under the device, such as a control method.) 24695b482a8SLen Brown */ 24795b482a8SLen Brown pci_device_node = region_obj->region.node; 24895b482a8SLen Brown while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { 249c45b5c09SAlexey Starikovskiy pci_device_node = pci_device_node->parent; 25095b482a8SLen Brown } 25195b482a8SLen Brown 25295b482a8SLen Brown if (!pci_device_node) { 25395b482a8SLen Brown ACPI_FREE(pci_id); 25495b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 25595b482a8SLen Brown } 25695b482a8SLen Brown 25795b482a8SLen Brown /* 25895abccb5SBob Moore * Get the PCI device and function numbers from the _ADR object 25995abccb5SBob Moore * contained in the parent's scope. 26095b482a8SLen Brown */ 261d4913dc6SBob Moore status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, 262d4913dc6SBob Moore pci_device_node, &pci_value); 26395b482a8SLen Brown 26495b482a8SLen Brown /* 26595b482a8SLen Brown * The default is zero, and since the allocation above zeroed the data, 26695b482a8SLen Brown * just do nothing on failure. 26795b482a8SLen Brown */ 26895b482a8SLen Brown if (ACPI_SUCCESS(status)) { 26995b482a8SLen Brown pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); 27095b482a8SLen Brown pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); 27195b482a8SLen Brown } 27295b482a8SLen Brown 27395b482a8SLen Brown /* The PCI segment number comes from the _SEG method */ 27495b482a8SLen Brown 275d4913dc6SBob Moore status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, 276d4913dc6SBob Moore pci_root_node, &pci_value); 27795b482a8SLen Brown if (ACPI_SUCCESS(status)) { 27895b482a8SLen Brown pci_id->segment = ACPI_LOWORD(pci_value); 27995b482a8SLen Brown } 28095b482a8SLen Brown 28195b482a8SLen Brown /* The PCI bus number comes from the _BBN method */ 28295b482a8SLen Brown 283d4913dc6SBob Moore status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, 284d4913dc6SBob Moore pci_root_node, &pci_value); 28595b482a8SLen Brown if (ACPI_SUCCESS(status)) { 28695b482a8SLen Brown pci_id->bus = ACPI_LOWORD(pci_value); 28795b482a8SLen Brown } 28895b482a8SLen Brown 28995abccb5SBob Moore /* Complete/update the PCI ID for this device */ 29095b482a8SLen Brown 29195abccb5SBob Moore status = 29295abccb5SBob Moore acpi_hw_derive_pci_id(pci_id, pci_root_node, 29395abccb5SBob Moore region_obj->region.node); 29495abccb5SBob Moore if (ACPI_FAILURE(status)) { 29595abccb5SBob Moore ACPI_FREE(pci_id); 29695abccb5SBob Moore return_ACPI_STATUS(status); 29795abccb5SBob Moore } 29895b482a8SLen Brown 29995b482a8SLen Brown *region_context = pci_id; 30095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 30195b482a8SLen Brown } 30295b482a8SLen Brown 30395b482a8SLen Brown /******************************************************************************* 30495b482a8SLen Brown * 30595b482a8SLen Brown * FUNCTION: acpi_ev_is_pci_root_bridge 30695b482a8SLen Brown * 307ba494beeSBob Moore * PARAMETERS: node - Device node being examined 30895b482a8SLen Brown * 30995b482a8SLen Brown * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge 31095b482a8SLen Brown * 31195b482a8SLen Brown * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by 31295b482a8SLen Brown * examining the _HID and _CID for the device. 31395b482a8SLen Brown * 31495b482a8SLen Brown ******************************************************************************/ 31595b482a8SLen Brown 31695b482a8SLen Brown static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) 31795b482a8SLen Brown { 31895b482a8SLen Brown acpi_status status; 31978e25fefSLv Zheng struct acpi_pnp_device_id *hid; 32078e25fefSLv Zheng struct acpi_pnp_device_id_list *cid; 32195b482a8SLen Brown u32 i; 32215b8dd53SBob Moore u8 match; 32395b482a8SLen Brown 32495b482a8SLen Brown /* Get the _HID and check for a PCI Root Bridge */ 32595b482a8SLen Brown 32695b482a8SLen Brown status = acpi_ut_execute_HID(node, &hid); 32795b482a8SLen Brown if (ACPI_FAILURE(status)) { 32895b482a8SLen Brown return (FALSE); 32995b482a8SLen Brown } 33095b482a8SLen Brown 33115b8dd53SBob Moore match = acpi_ut_is_pci_root_bridge(hid->string); 33215b8dd53SBob Moore ACPI_FREE(hid); 33315b8dd53SBob Moore 33415b8dd53SBob Moore if (match) { 33595b482a8SLen Brown return (TRUE); 33695b482a8SLen Brown } 33795b482a8SLen Brown 33895b482a8SLen Brown /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ 33995b482a8SLen Brown 34095b482a8SLen Brown status = acpi_ut_execute_CID(node, &cid); 34195b482a8SLen Brown if (ACPI_FAILURE(status)) { 34295b482a8SLen Brown return (FALSE); 34395b482a8SLen Brown } 34495b482a8SLen Brown 34595b482a8SLen Brown /* Check all _CIDs in the returned list */ 34695b482a8SLen Brown 34795b482a8SLen Brown for (i = 0; i < cid->count; i++) { 34815b8dd53SBob Moore if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) { 34995b482a8SLen Brown ACPI_FREE(cid); 35095b482a8SLen Brown return (TRUE); 35195b482a8SLen Brown } 35295b482a8SLen Brown } 35395b482a8SLen Brown 35495b482a8SLen Brown ACPI_FREE(cid); 35595b482a8SLen Brown return (FALSE); 35695b482a8SLen Brown } 35795b482a8SLen Brown 35895b482a8SLen Brown /******************************************************************************* 35995b482a8SLen Brown * 36095b482a8SLen Brown * FUNCTION: acpi_ev_pci_bar_region_setup 36195b482a8SLen Brown * 362ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 363ba494beeSBob Moore * function - Start or stop 36495b482a8SLen Brown * handler_context - Address space handler context 36595b482a8SLen Brown * region_context - Region specific context 36695b482a8SLen Brown * 36795b482a8SLen Brown * RETURN: Status 36895b482a8SLen Brown * 369ba494beeSBob Moore * DESCRIPTION: Setup a pci_BAR operation region 37095b482a8SLen Brown * 37195b482a8SLen Brown * MUTEX: Assumes namespace is not locked 37295b482a8SLen Brown * 37395b482a8SLen Brown ******************************************************************************/ 37495b482a8SLen Brown 37595b482a8SLen Brown acpi_status 37695b482a8SLen Brown acpi_ev_pci_bar_region_setup(acpi_handle handle, 37795b482a8SLen Brown u32 function, 37895b482a8SLen Brown void *handler_context, void **region_context) 37995b482a8SLen Brown { 38095b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); 38195b482a8SLen Brown 38295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 38395b482a8SLen Brown } 38495b482a8SLen Brown 38595b482a8SLen Brown /******************************************************************************* 38695b482a8SLen Brown * 38795b482a8SLen Brown * FUNCTION: acpi_ev_cmos_region_setup 38895b482a8SLen Brown * 389ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 390ba494beeSBob Moore * function - Start or stop 39195b482a8SLen Brown * handler_context - Address space handler context 39295b482a8SLen Brown * region_context - Region specific context 39395b482a8SLen Brown * 39495b482a8SLen Brown * RETURN: Status 39595b482a8SLen Brown * 39695b482a8SLen Brown * DESCRIPTION: Setup a CMOS operation region 39795b482a8SLen Brown * 39895b482a8SLen Brown * MUTEX: Assumes namespace is not locked 39995b482a8SLen Brown * 40095b482a8SLen Brown ******************************************************************************/ 40195b482a8SLen Brown 40295b482a8SLen Brown acpi_status 40395b482a8SLen Brown acpi_ev_cmos_region_setup(acpi_handle handle, 40495b482a8SLen Brown u32 function, 40595b482a8SLen Brown void *handler_context, void **region_context) 40695b482a8SLen Brown { 40795b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_cmos_region_setup); 40895b482a8SLen Brown 40995b482a8SLen Brown return_ACPI_STATUS(AE_OK); 41095b482a8SLen Brown } 41195b482a8SLen Brown 41295b482a8SLen Brown /******************************************************************************* 41395b482a8SLen Brown * 41495b482a8SLen Brown * FUNCTION: acpi_ev_default_region_setup 41595b482a8SLen Brown * 416ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 417ba494beeSBob Moore * function - Start or stop 41895b482a8SLen Brown * handler_context - Address space handler context 41995b482a8SLen Brown * region_context - Region specific context 42095b482a8SLen Brown * 42195b482a8SLen Brown * RETURN: Status 42295b482a8SLen Brown * 42395b482a8SLen Brown * DESCRIPTION: Default region initialization 42495b482a8SLen Brown * 42595b482a8SLen Brown ******************************************************************************/ 42695b482a8SLen Brown 42795b482a8SLen Brown acpi_status 42895b482a8SLen Brown acpi_ev_default_region_setup(acpi_handle handle, 42995b482a8SLen Brown u32 function, 43095b482a8SLen Brown void *handler_context, void **region_context) 43195b482a8SLen Brown { 43295b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_default_region_setup); 43395b482a8SLen Brown 43495b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 43595b482a8SLen Brown *region_context = NULL; 43695b482a8SLen Brown } else { 43795b482a8SLen Brown *region_context = handler_context; 43895b482a8SLen Brown } 43995b482a8SLen Brown 44095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 44195b482a8SLen Brown } 44295b482a8SLen Brown 44395b482a8SLen Brown /******************************************************************************* 44495b482a8SLen Brown * 44595b482a8SLen Brown * FUNCTION: acpi_ev_initialize_region 44695b482a8SLen Brown * 44795b482a8SLen Brown * PARAMETERS: region_obj - Region we are initializing 44895b482a8SLen Brown * 44995b482a8SLen Brown * RETURN: Status 45095b482a8SLen Brown * 45195b482a8SLen Brown * DESCRIPTION: Initializes the region, finds any _REG methods and saves them 45295b482a8SLen Brown * for execution at a later time 45395b482a8SLen Brown * 45495b482a8SLen Brown * Get the appropriate address space handler for a newly 45595b482a8SLen Brown * created region. 45695b482a8SLen Brown * 45795b482a8SLen Brown * This also performs address space specific initialization. For 45895b482a8SLen Brown * example, PCI regions must have an _ADR object that contains 45995b482a8SLen Brown * a PCI address in the scope of the definition. This address is 46095b482a8SLen Brown * required to perform an access to PCI config space. 46195b482a8SLen Brown * 46295b482a8SLen Brown * MUTEX: Interpreter should be unlocked, because we may run the _REG 46395b482a8SLen Brown * method for this region. 46495b482a8SLen Brown * 465760235cdSLv Zheng * NOTE: Possible incompliance: 466760235cdSLv Zheng * There is a behavior conflict in automatic _REG execution: 467760235cdSLv Zheng * 1. When the interpreter is evaluating a method, we can only 468760235cdSLv Zheng * automatically run _REG for the following case: 469760235cdSLv Zheng * operation_region (OPR1, 0x80, 0x1000010, 0x4) 470760235cdSLv Zheng * 2. When the interpreter is loading a table, we can also 471760235cdSLv Zheng * automatically run _REG for the following case: 472760235cdSLv Zheng * operation_region (OPR1, 0x80, 0x1000010, 0x4) 473760235cdSLv Zheng * Though this may not be compliant to the de-facto standard, the 474760235cdSLv Zheng * logic is kept in order not to trigger regressions. And keeping 475760235cdSLv Zheng * this logic should be taken care by the caller of this function. 476760235cdSLv Zheng * 47795b482a8SLen Brown ******************************************************************************/ 47895b482a8SLen Brown 479760235cdSLv Zheng acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj) 48095b482a8SLen Brown { 48195b482a8SLen Brown union acpi_operand_object *handler_obj; 48295b482a8SLen Brown union acpi_operand_object *obj_desc; 48395b482a8SLen Brown acpi_adr_space_type space_id; 48495b482a8SLen Brown struct acpi_namespace_node *node; 48595b482a8SLen Brown 486760235cdSLv Zheng ACPI_FUNCTION_TRACE(ev_initialize_region); 48795b482a8SLen Brown 48895b482a8SLen Brown if (!region_obj) { 48995b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 49095b482a8SLen Brown } 49195b482a8SLen Brown 49295b482a8SLen Brown if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { 49395b482a8SLen Brown return_ACPI_STATUS(AE_OK); 49495b482a8SLen Brown } 49595b482a8SLen Brown 496849c2571SLv Zheng region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; 49795b482a8SLen Brown 498c45b5c09SAlexey Starikovskiy node = region_obj->region.node->parent; 49995b482a8SLen Brown space_id = region_obj->region.space_id; 50095b482a8SLen Brown 50195b482a8SLen Brown /* 50295b482a8SLen Brown * The following loop depends upon the root Node having no parent 5037b738064SBob Moore * ie: acpi_gbl_root_node->Parent being set to NULL 50495b482a8SLen Brown */ 50595b482a8SLen Brown while (node) { 50695b482a8SLen Brown 50795b482a8SLen Brown /* Check to see if a handler exists */ 50895b482a8SLen Brown 50995b482a8SLen Brown handler_obj = NULL; 51095b482a8SLen Brown obj_desc = acpi_ns_get_attached_object(node); 51195b482a8SLen Brown if (obj_desc) { 51295b482a8SLen Brown 51395b482a8SLen Brown /* Can only be a handler if the object exists */ 51495b482a8SLen Brown 51595b482a8SLen Brown switch (node->type) { 51695b482a8SLen Brown case ACPI_TYPE_DEVICE: 51795b482a8SLen Brown case ACPI_TYPE_PROCESSOR: 51895b482a8SLen Brown case ACPI_TYPE_THERMAL: 51995b482a8SLen Brown 520aa6abd2bSLv Zheng handler_obj = obj_desc->common_notify.handler; 52195b482a8SLen Brown break; 52295b482a8SLen Brown 523e31c32cfSLin Ming case ACPI_TYPE_METHOD: 524e31c32cfSLin Ming /* 525e31c32cfSLin Ming * If we are executing module level code, the original 526e31c32cfSLin Ming * Node's object was replaced by this Method object and we 527e31c32cfSLin Ming * saved the handler in the method object. 528e31c32cfSLin Ming * 529e31c32cfSLin Ming * See acpi_ns_exec_module_code 530e31c32cfSLin Ming */ 531e7d970f6SBob Moore if (!acpi_gbl_execute_tables_as_methods && 532de56ba95SLv Zheng obj_desc->method. 53326294842SLin Ming info_flags & ACPI_METHOD_MODULE_LEVEL) { 534e31c32cfSLin Ming handler_obj = 53526294842SLin Ming obj_desc->method.dispatch.handler; 536e31c32cfSLin Ming } 537e31c32cfSLin Ming break; 538e31c32cfSLin Ming 53995b482a8SLen Brown default: 5401d1ea1b7SChao Guan 54195b482a8SLen Brown /* Ignore other objects */ 5421d1ea1b7SChao Guan 54395b482a8SLen Brown break; 54495b482a8SLen Brown } 54595b482a8SLen Brown 546f31a99ceSLv Zheng handler_obj = 547f31a99ceSLv Zheng acpi_ev_find_region_handler(space_id, handler_obj); 548f31a99ceSLv Zheng if (handler_obj) { 54995b482a8SLen Brown 55095b482a8SLen Brown /* Found correct handler */ 55195b482a8SLen Brown 55295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 55395b482a8SLen Brown "Found handler %p for region %p in obj %p\n", 554f31a99ceSLv Zheng handler_obj, region_obj, 55595b482a8SLen Brown obj_desc)); 55695b482a8SLen Brown 557760235cdSLv Zheng (void)acpi_ev_attach_region(handler_obj, 558760235cdSLv Zheng region_obj, FALSE); 55995b482a8SLen Brown 56095b482a8SLen Brown /* 561d4913dc6SBob Moore * Tell all users that this region is usable by 562d4913dc6SBob Moore * running the _REG method 56395b482a8SLen Brown */ 5648633db6bSLv Zheng acpi_ex_exit_interpreter(); 565760235cdSLv Zheng (void)acpi_ev_execute_reg_method(region_obj, 566f31a99ceSLv Zheng ACPI_REG_CONNECT); 5678633db6bSLv Zheng acpi_ex_enter_interpreter(); 56895b482a8SLen Brown return_ACPI_STATUS(AE_OK); 56995b482a8SLen Brown } 57095b482a8SLen Brown } 57195b482a8SLen Brown 57295b482a8SLen Brown /* This node does not have the handler we need; Pop up one level */ 57395b482a8SLen Brown 574c45b5c09SAlexey Starikovskiy node = node->parent; 57595b482a8SLen Brown } 57695b482a8SLen Brown 577760235cdSLv Zheng /* 578760235cdSLv Zheng * If we get here, there is no handler for this region. This is not 579760235cdSLv Zheng * fatal because many regions get created before a handler is installed 580760235cdSLv Zheng * for said region. 581760235cdSLv Zheng */ 58295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 58395b482a8SLen Brown "No handler for RegionType %s(%X) (RegionObj %p)\n", 58495b482a8SLen Brown acpi_ut_get_region_name(space_id), space_id, 58595b482a8SLen Brown region_obj)); 58695b482a8SLen Brown 587760235cdSLv Zheng return_ACPI_STATUS(AE_OK); 58895b482a8SLen Brown } 589