195857638SErik 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 * 6487ea80aSBob Moore * Copyright (C) 2000 - 2022, Intel Corp. 795b482a8SLen Brown * 895857638SErik 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 /******************************************************************************* 2095b482a8SLen Brown * 2195b482a8SLen Brown * FUNCTION: acpi_ev_system_memory_region_setup 2295b482a8SLen Brown * 23ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 24ba494beeSBob Moore * function - Start or stop 2595b482a8SLen Brown * handler_context - Address space handler context 2695b482a8SLen Brown * region_context - Region specific context 2795b482a8SLen Brown * 2895b482a8SLen Brown * RETURN: Status 2995b482a8SLen Brown * 3095b482a8SLen Brown * DESCRIPTION: Setup a system_memory operation region 3195b482a8SLen Brown * 3295b482a8SLen Brown ******************************************************************************/ 3395b482a8SLen Brown acpi_status 3495b482a8SLen Brown acpi_ev_system_memory_region_setup(acpi_handle handle, 3595b482a8SLen Brown u32 function, 3695b482a8SLen Brown void *handler_context, void **region_context) 3795b482a8SLen Brown { 3895b482a8SLen Brown union acpi_operand_object *region_desc = 3995b482a8SLen Brown (union acpi_operand_object *)handle; 4095b482a8SLen Brown struct acpi_mem_space_context *local_region_context; 41b8fcd0e5SRafael J. Wysocki struct acpi_mem_mapping *mm; 4295b482a8SLen Brown 4395b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); 4495b482a8SLen Brown 4595b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 4695b482a8SLen Brown if (*region_context) { 4795b482a8SLen Brown local_region_context = 4895b482a8SLen Brown (struct acpi_mem_space_context *)*region_context; 4995b482a8SLen Brown 50b8fcd0e5SRafael J. Wysocki /* Delete memory mappings if present */ 5195b482a8SLen Brown 52b8fcd0e5SRafael J. Wysocki while (local_region_context->first_mm) { 53b8fcd0e5SRafael J. Wysocki mm = local_region_context->first_mm; 54b8fcd0e5SRafael J. Wysocki local_region_context->first_mm = mm->next_mm; 55b8fcd0e5SRafael J. Wysocki acpi_os_unmap_memory(mm->logical_address, 56b8fcd0e5SRafael J. Wysocki mm->length); 57b8fcd0e5SRafael J. Wysocki ACPI_FREE(mm); 5895b482a8SLen Brown } 5995b482a8SLen Brown ACPI_FREE(local_region_context); 6095b482a8SLen Brown *region_context = NULL; 6195b482a8SLen Brown } 6295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 6395b482a8SLen Brown } 6495b482a8SLen Brown 6595b482a8SLen Brown /* Create a new context */ 6695b482a8SLen Brown 6795b482a8SLen Brown local_region_context = 6895b482a8SLen Brown ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); 6995b482a8SLen Brown if (!(local_region_context)) { 7095b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 7195b482a8SLen Brown } 7295b482a8SLen Brown 7395b482a8SLen Brown /* Save the region length and address for use in the handler */ 7495b482a8SLen Brown 7595b482a8SLen Brown local_region_context->length = region_desc->region.length; 7695b482a8SLen Brown local_region_context->address = region_desc->region.address; 7795b482a8SLen Brown 7895b482a8SLen Brown *region_context = local_region_context; 7995b482a8SLen Brown return_ACPI_STATUS(AE_OK); 8095b482a8SLen Brown } 8195b482a8SLen Brown 8295b482a8SLen Brown /******************************************************************************* 8395b482a8SLen Brown * 8495b482a8SLen Brown * FUNCTION: acpi_ev_io_space_region_setup 8595b482a8SLen Brown * 86ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 87ba494beeSBob Moore * function - Start or stop 8895b482a8SLen Brown * handler_context - Address space handler context 8995b482a8SLen Brown * region_context - Region specific context 9095b482a8SLen Brown * 9195b482a8SLen Brown * RETURN: Status 9295b482a8SLen Brown * 9395b482a8SLen Brown * DESCRIPTION: Setup a IO operation region 9495b482a8SLen Brown * 9595b482a8SLen Brown ******************************************************************************/ 9695b482a8SLen Brown 9795b482a8SLen Brown acpi_status 9895b482a8SLen Brown acpi_ev_io_space_region_setup(acpi_handle handle, 9995b482a8SLen Brown u32 function, 10095b482a8SLen Brown void *handler_context, void **region_context) 10195b482a8SLen Brown { 10295b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_io_space_region_setup); 10395b482a8SLen Brown 10495b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 10595b482a8SLen Brown *region_context = NULL; 10695b482a8SLen Brown } else { 10795b482a8SLen Brown *region_context = handler_context; 10895b482a8SLen Brown } 10995b482a8SLen Brown 11095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 11195b482a8SLen Brown } 11295b482a8SLen Brown 11395b482a8SLen Brown /******************************************************************************* 11495b482a8SLen Brown * 11595b482a8SLen Brown * FUNCTION: acpi_ev_pci_config_region_setup 11695b482a8SLen Brown * 117ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 118ba494beeSBob Moore * function - Start or stop 11995b482a8SLen Brown * handler_context - Address space handler context 12095b482a8SLen Brown * region_context - Region specific context 12195b482a8SLen Brown * 12295b482a8SLen Brown * RETURN: Status 12395b482a8SLen Brown * 12495b482a8SLen Brown * DESCRIPTION: Setup a PCI_Config operation region 12595b482a8SLen Brown * 12695b482a8SLen Brown * MUTEX: Assumes namespace is not locked 12795b482a8SLen Brown * 12895b482a8SLen Brown ******************************************************************************/ 12995b482a8SLen Brown 13095b482a8SLen Brown acpi_status 13195b482a8SLen Brown acpi_ev_pci_config_region_setup(acpi_handle handle, 13295b482a8SLen Brown u32 function, 13395b482a8SLen Brown void *handler_context, void **region_context) 13495b482a8SLen Brown { 13595b482a8SLen Brown acpi_status status = AE_OK; 1365df7e6cbSBob Moore u64 pci_value; 13795b482a8SLen Brown struct acpi_pci_id *pci_id = *region_context; 13895b482a8SLen Brown union acpi_operand_object *handler_obj; 13995b482a8SLen Brown struct acpi_namespace_node *parent_node; 14095b482a8SLen Brown struct acpi_namespace_node *pci_root_node; 14195b482a8SLen Brown struct acpi_namespace_node *pci_device_node; 14295b482a8SLen Brown union acpi_operand_object *region_obj = 14395b482a8SLen Brown (union acpi_operand_object *)handle; 14495b482a8SLen Brown 14595b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); 14695b482a8SLen Brown 14795b482a8SLen Brown handler_obj = region_obj->region.handler; 14895b482a8SLen Brown if (!handler_obj) { 14995b482a8SLen Brown /* 15095b482a8SLen Brown * No installed handler. This shouldn't happen because the dispatch 15195b482a8SLen Brown * routine checks before we get here, but we check again just in case. 15295b482a8SLen Brown */ 15395b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 15495b482a8SLen Brown "Attempting to init a region %p, with no handler\n", 15595b482a8SLen Brown region_obj)); 15695b482a8SLen Brown return_ACPI_STATUS(AE_NOT_EXIST); 15795b482a8SLen Brown } 15895b482a8SLen Brown 15995b482a8SLen Brown *region_context = NULL; 16095b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 16195b482a8SLen Brown if (pci_id) { 16295b482a8SLen Brown ACPI_FREE(pci_id); 16395b482a8SLen Brown } 16495b482a8SLen Brown return_ACPI_STATUS(status); 16595b482a8SLen Brown } 16695b482a8SLen Brown 167c45b5c09SAlexey Starikovskiy parent_node = region_obj->region.node->parent; 16895b482a8SLen Brown 16995b482a8SLen Brown /* 17095b482a8SLen Brown * Get the _SEG and _BBN values from the device upon which the handler 17195b482a8SLen Brown * is installed. 17295b482a8SLen Brown * 17395b482a8SLen Brown * We need to get the _SEG and _BBN objects relative to the PCI BUS device. 17495b482a8SLen Brown * This is the device the handler has been registered to handle. 17595b482a8SLen Brown */ 17695b482a8SLen Brown 17795b482a8SLen Brown /* 17895b482a8SLen Brown * If the address_space.Node is still pointing to the root, we need 17995b482a8SLen Brown * to scan upward for a PCI Root bridge and re-associate the op_region 18095b482a8SLen Brown * handlers with that device. 18195b482a8SLen Brown */ 18295b482a8SLen Brown if (handler_obj->address_space.node == acpi_gbl_root_node) { 18395b482a8SLen Brown 18495b482a8SLen Brown /* Start search from the parent object */ 18595b482a8SLen Brown 18695b482a8SLen Brown pci_root_node = parent_node; 18795b482a8SLen Brown while (pci_root_node != acpi_gbl_root_node) { 18895b482a8SLen Brown 18995b482a8SLen Brown /* Get the _HID/_CID in order to detect a root_bridge */ 19095b482a8SLen Brown 19195b482a8SLen Brown if (acpi_ev_is_pci_root_bridge(pci_root_node)) { 19295b482a8SLen Brown 19395b482a8SLen Brown /* Install a handler for this PCI root bridge */ 19495b482a8SLen Brown 1951f86e8c1SLv Zheng status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); 19695b482a8SLen Brown if (ACPI_FAILURE(status)) { 19795b482a8SLen Brown if (status == AE_SAME_HANDLER) { 19895b482a8SLen Brown /* 19995b482a8SLen Brown * It is OK if the handler is already installed on the 20095b482a8SLen Brown * root bridge. Still need to return a context object 20195b482a8SLen Brown * for the new PCI_Config operation region, however. 20295b482a8SLen Brown */ 20395b482a8SLen Brown } else { 20495b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 205d4913dc6SBob Moore "Could not install PciConfig handler " 206d4913dc6SBob Moore "for Root Bridge %4.4s", 20795b482a8SLen Brown acpi_ut_get_node_name 20895b482a8SLen Brown (pci_root_node))); 20995b482a8SLen Brown } 21095b482a8SLen Brown } 21195b482a8SLen Brown break; 21295b482a8SLen Brown } 21395b482a8SLen Brown 214c45b5c09SAlexey Starikovskiy pci_root_node = pci_root_node->parent; 21595b482a8SLen Brown } 21695b482a8SLen Brown 21795b482a8SLen Brown /* PCI root bridge not found, use namespace root node */ 21895b482a8SLen Brown } else { 21995b482a8SLen Brown pci_root_node = handler_obj->address_space.node; 22095b482a8SLen Brown } 22195b482a8SLen Brown 22295b482a8SLen Brown /* 22395b482a8SLen Brown * If this region is now initialized, we are done. 22495b482a8SLen Brown * (install_address_space_handler could have initialized it) 22595b482a8SLen Brown */ 22695b482a8SLen Brown if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { 22795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 22895b482a8SLen Brown } 22995b482a8SLen Brown 23095b482a8SLen Brown /* Region is still not initialized. Create a new context */ 23195b482a8SLen Brown 23295b482a8SLen Brown pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); 23395b482a8SLen Brown if (!pci_id) { 23495b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 23595b482a8SLen Brown } 23695b482a8SLen Brown 23795b482a8SLen Brown /* 23895b482a8SLen Brown * For PCI_Config space access, we need the segment, bus, device and 23995b482a8SLen Brown * function numbers. Acquire them here. 24095b482a8SLen Brown * 24195b482a8SLen Brown * Find the parent device object. (This allows the operation region to be 24295b482a8SLen Brown * within a subscope under the device, such as a control method.) 24395b482a8SLen Brown */ 24495b482a8SLen Brown pci_device_node = region_obj->region.node; 24595b482a8SLen Brown while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { 246c45b5c09SAlexey Starikovskiy pci_device_node = pci_device_node->parent; 24795b482a8SLen Brown } 24895b482a8SLen Brown 24995b482a8SLen Brown if (!pci_device_node) { 25095b482a8SLen Brown ACPI_FREE(pci_id); 25195b482a8SLen Brown return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 25295b482a8SLen Brown } 25395b482a8SLen Brown 25495b482a8SLen Brown /* 25595abccb5SBob Moore * Get the PCI device and function numbers from the _ADR object 25695abccb5SBob Moore * contained in the parent's scope. 25795b482a8SLen Brown */ 258d4913dc6SBob Moore status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, 259d4913dc6SBob Moore pci_device_node, &pci_value); 26095b482a8SLen Brown 26195b482a8SLen Brown /* 26295b482a8SLen Brown * The default is zero, and since the allocation above zeroed the data, 26395b482a8SLen Brown * just do nothing on failure. 26495b482a8SLen Brown */ 26595b482a8SLen Brown if (ACPI_SUCCESS(status)) { 26695b482a8SLen Brown pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); 26795b482a8SLen Brown pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); 26895b482a8SLen Brown } 26995b482a8SLen Brown 27095b482a8SLen Brown /* The PCI segment number comes from the _SEG method */ 27195b482a8SLen Brown 272d4913dc6SBob Moore status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, 273d4913dc6SBob Moore pci_root_node, &pci_value); 27495b482a8SLen Brown if (ACPI_SUCCESS(status)) { 27595b482a8SLen Brown pci_id->segment = ACPI_LOWORD(pci_value); 27695b482a8SLen Brown } 27795b482a8SLen Brown 27895b482a8SLen Brown /* The PCI bus number comes from the _BBN method */ 27995b482a8SLen Brown 280d4913dc6SBob Moore status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, 281d4913dc6SBob Moore pci_root_node, &pci_value); 28295b482a8SLen Brown if (ACPI_SUCCESS(status)) { 28395b482a8SLen Brown pci_id->bus = ACPI_LOWORD(pci_value); 28495b482a8SLen Brown } 28595b482a8SLen Brown 28695abccb5SBob Moore /* Complete/update the PCI ID for this device */ 28795b482a8SLen Brown 28895abccb5SBob Moore status = 28995abccb5SBob Moore acpi_hw_derive_pci_id(pci_id, pci_root_node, 29095abccb5SBob Moore region_obj->region.node); 29195abccb5SBob Moore if (ACPI_FAILURE(status)) { 29295abccb5SBob Moore ACPI_FREE(pci_id); 29395abccb5SBob Moore return_ACPI_STATUS(status); 29495abccb5SBob Moore } 29595b482a8SLen Brown 29695b482a8SLen Brown *region_context = pci_id; 29795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 29895b482a8SLen Brown } 29995b482a8SLen Brown 30095b482a8SLen Brown /******************************************************************************* 30195b482a8SLen Brown * 30295b482a8SLen Brown * FUNCTION: acpi_ev_is_pci_root_bridge 30395b482a8SLen Brown * 304ba494beeSBob Moore * PARAMETERS: node - Device node being examined 30595b482a8SLen Brown * 30695b482a8SLen Brown * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge 30795b482a8SLen Brown * 30895b482a8SLen Brown * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by 30995b482a8SLen Brown * examining the _HID and _CID for the device. 31095b482a8SLen Brown * 31195b482a8SLen Brown ******************************************************************************/ 31295b482a8SLen Brown 3138b1cafdcSBob Moore u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) 31495b482a8SLen Brown { 31595b482a8SLen Brown acpi_status status; 31678e25fefSLv Zheng struct acpi_pnp_device_id *hid; 31778e25fefSLv Zheng struct acpi_pnp_device_id_list *cid; 31895b482a8SLen Brown u32 i; 31915b8dd53SBob Moore u8 match; 32095b482a8SLen Brown 32195b482a8SLen Brown /* Get the _HID and check for a PCI Root Bridge */ 32295b482a8SLen Brown 32395b482a8SLen Brown status = acpi_ut_execute_HID(node, &hid); 32495b482a8SLen Brown if (ACPI_FAILURE(status)) { 32595b482a8SLen Brown return (FALSE); 32695b482a8SLen Brown } 32795b482a8SLen Brown 32815b8dd53SBob Moore match = acpi_ut_is_pci_root_bridge(hid->string); 32915b8dd53SBob Moore ACPI_FREE(hid); 33015b8dd53SBob Moore 33115b8dd53SBob Moore if (match) { 33295b482a8SLen Brown return (TRUE); 33395b482a8SLen Brown } 33495b482a8SLen Brown 33595b482a8SLen Brown /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ 33695b482a8SLen Brown 33795b482a8SLen Brown status = acpi_ut_execute_CID(node, &cid); 33895b482a8SLen Brown if (ACPI_FAILURE(status)) { 33995b482a8SLen Brown return (FALSE); 34095b482a8SLen Brown } 34195b482a8SLen Brown 34295b482a8SLen Brown /* Check all _CIDs in the returned list */ 34395b482a8SLen Brown 34495b482a8SLen Brown for (i = 0; i < cid->count; i++) { 34515b8dd53SBob Moore if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) { 34695b482a8SLen Brown ACPI_FREE(cid); 34795b482a8SLen Brown return (TRUE); 34895b482a8SLen Brown } 34995b482a8SLen Brown } 35095b482a8SLen Brown 35195b482a8SLen Brown ACPI_FREE(cid); 35295b482a8SLen Brown return (FALSE); 35395b482a8SLen Brown } 35495b482a8SLen Brown 35595b482a8SLen Brown /******************************************************************************* 35695b482a8SLen Brown * 35795b482a8SLen Brown * FUNCTION: acpi_ev_pci_bar_region_setup 35895b482a8SLen Brown * 359ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 360ba494beeSBob Moore * function - Start or stop 36195b482a8SLen Brown * handler_context - Address space handler context 36295b482a8SLen Brown * region_context - Region specific context 36395b482a8SLen Brown * 36495b482a8SLen Brown * RETURN: Status 36595b482a8SLen Brown * 366ba494beeSBob Moore * DESCRIPTION: Setup a pci_BAR operation region 36795b482a8SLen Brown * 36895b482a8SLen Brown * MUTEX: Assumes namespace is not locked 36995b482a8SLen Brown * 37095b482a8SLen Brown ******************************************************************************/ 37195b482a8SLen Brown 37295b482a8SLen Brown acpi_status 37395b482a8SLen Brown acpi_ev_pci_bar_region_setup(acpi_handle handle, 37495b482a8SLen Brown u32 function, 37595b482a8SLen Brown void *handler_context, void **region_context) 37695b482a8SLen Brown { 37795b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); 37895b482a8SLen Brown 37995b482a8SLen Brown return_ACPI_STATUS(AE_OK); 38095b482a8SLen Brown } 38195b482a8SLen Brown 38295b482a8SLen Brown /******************************************************************************* 38395b482a8SLen Brown * 38495b482a8SLen Brown * FUNCTION: acpi_ev_cmos_region_setup 38595b482a8SLen Brown * 386ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 387ba494beeSBob Moore * function - Start or stop 38895b482a8SLen Brown * handler_context - Address space handler context 38995b482a8SLen Brown * region_context - Region specific context 39095b482a8SLen Brown * 39195b482a8SLen Brown * RETURN: Status 39295b482a8SLen Brown * 39395b482a8SLen Brown * DESCRIPTION: Setup a CMOS operation region 39495b482a8SLen Brown * 39595b482a8SLen Brown * MUTEX: Assumes namespace is not locked 39695b482a8SLen Brown * 39795b482a8SLen Brown ******************************************************************************/ 39895b482a8SLen Brown 39995b482a8SLen Brown acpi_status 40095b482a8SLen Brown acpi_ev_cmos_region_setup(acpi_handle handle, 40195b482a8SLen Brown u32 function, 40295b482a8SLen Brown void *handler_context, void **region_context) 40395b482a8SLen Brown { 40495b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_cmos_region_setup); 40595b482a8SLen Brown 40695b482a8SLen Brown return_ACPI_STATUS(AE_OK); 40795b482a8SLen Brown } 40895b482a8SLen Brown 40995b482a8SLen Brown /******************************************************************************* 41095b482a8SLen Brown * 411ca25f92bSJessica Clarke * FUNCTION: acpi_ev_data_table_region_setup 412ca25f92bSJessica Clarke * 413ca25f92bSJessica Clarke * PARAMETERS: handle - Region we are interested in 414ca25f92bSJessica Clarke * function - Start or stop 415ca25f92bSJessica Clarke * handler_context - Address space handler context 416ca25f92bSJessica Clarke * region_context - Region specific context 417ca25f92bSJessica Clarke * 418ca25f92bSJessica Clarke * RETURN: Status 419ca25f92bSJessica Clarke * 420ca25f92bSJessica Clarke * DESCRIPTION: Setup a data_table_region 421ca25f92bSJessica Clarke * 422ca25f92bSJessica Clarke * MUTEX: Assumes namespace is not locked 423ca25f92bSJessica Clarke * 424ca25f92bSJessica Clarke ******************************************************************************/ 425ca25f92bSJessica Clarke 426ca25f92bSJessica Clarke acpi_status 427ca25f92bSJessica Clarke acpi_ev_data_table_region_setup(acpi_handle handle, 428ca25f92bSJessica Clarke u32 function, 429ca25f92bSJessica Clarke void *handler_context, void **region_context) 430ca25f92bSJessica Clarke { 431ca25f92bSJessica Clarke union acpi_operand_object *region_desc = 432ca25f92bSJessica Clarke (union acpi_operand_object *)handle; 433*9737ff46SPedro Falcato struct acpi_data_table_mapping *local_region_context; 434ca25f92bSJessica Clarke 435ca25f92bSJessica Clarke ACPI_FUNCTION_TRACE(ev_data_table_region_setup); 436ca25f92bSJessica Clarke 437ca25f92bSJessica Clarke if (function == ACPI_REGION_DEACTIVATE) { 438ca25f92bSJessica Clarke if (*region_context) { 439ca25f92bSJessica Clarke ACPI_FREE(*region_context); 440ca25f92bSJessica Clarke *region_context = NULL; 441ca25f92bSJessica Clarke } 442ca25f92bSJessica Clarke return_ACPI_STATUS(AE_OK); 443ca25f92bSJessica Clarke } 444ca25f92bSJessica Clarke 445ca25f92bSJessica Clarke /* Create a new context */ 446ca25f92bSJessica Clarke 447ca25f92bSJessica Clarke local_region_context = 448*9737ff46SPedro Falcato ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_mapping)); 449ca25f92bSJessica Clarke if (!(local_region_context)) { 450ca25f92bSJessica Clarke return_ACPI_STATUS(AE_NO_MEMORY); 451ca25f92bSJessica Clarke } 452ca25f92bSJessica Clarke 453ca25f92bSJessica Clarke /* Save the data table pointer for use in the handler */ 454ca25f92bSJessica Clarke 455ca25f92bSJessica Clarke local_region_context->pointer = region_desc->region.pointer; 456ca25f92bSJessica Clarke 457ca25f92bSJessica Clarke *region_context = local_region_context; 458ca25f92bSJessica Clarke return_ACPI_STATUS(AE_OK); 459ca25f92bSJessica Clarke } 460ca25f92bSJessica Clarke 461ca25f92bSJessica Clarke /******************************************************************************* 462ca25f92bSJessica Clarke * 46395b482a8SLen Brown * FUNCTION: acpi_ev_default_region_setup 46495b482a8SLen Brown * 465ba494beeSBob Moore * PARAMETERS: handle - Region we are interested in 466ba494beeSBob Moore * function - Start or stop 46795b482a8SLen Brown * handler_context - Address space handler context 46895b482a8SLen Brown * region_context - Region specific context 46995b482a8SLen Brown * 47095b482a8SLen Brown * RETURN: Status 47195b482a8SLen Brown * 47295b482a8SLen Brown * DESCRIPTION: Default region initialization 47395b482a8SLen Brown * 47495b482a8SLen Brown ******************************************************************************/ 47595b482a8SLen Brown 47695b482a8SLen Brown acpi_status 47795b482a8SLen Brown acpi_ev_default_region_setup(acpi_handle handle, 47895b482a8SLen Brown u32 function, 47995b482a8SLen Brown void *handler_context, void **region_context) 48095b482a8SLen Brown { 48195b482a8SLen Brown ACPI_FUNCTION_TRACE(ev_default_region_setup); 48295b482a8SLen Brown 48395b482a8SLen Brown if (function == ACPI_REGION_DEACTIVATE) { 48495b482a8SLen Brown *region_context = NULL; 48595b482a8SLen Brown } else { 48695b482a8SLen Brown *region_context = handler_context; 48795b482a8SLen Brown } 48895b482a8SLen Brown 48995b482a8SLen Brown return_ACPI_STATUS(AE_OK); 49095b482a8SLen Brown } 49195b482a8SLen Brown 49295b482a8SLen Brown /******************************************************************************* 49395b482a8SLen Brown * 49495b482a8SLen Brown * FUNCTION: acpi_ev_initialize_region 49595b482a8SLen Brown * 49695b482a8SLen Brown * PARAMETERS: region_obj - Region we are initializing 49795b482a8SLen Brown * 49895b482a8SLen Brown * RETURN: Status 49995b482a8SLen Brown * 50095b482a8SLen Brown * DESCRIPTION: Initializes the region, finds any _REG methods and saves them 50195b482a8SLen Brown * for execution at a later time 50295b482a8SLen Brown * 50395b482a8SLen Brown * Get the appropriate address space handler for a newly 50495b482a8SLen Brown * created region. 50595b482a8SLen Brown * 50695b482a8SLen Brown * This also performs address space specific initialization. For 50795b482a8SLen Brown * example, PCI regions must have an _ADR object that contains 50895b482a8SLen Brown * a PCI address in the scope of the definition. This address is 50995b482a8SLen Brown * required to perform an access to PCI config space. 51095b482a8SLen Brown * 51195b482a8SLen Brown * MUTEX: Interpreter should be unlocked, because we may run the _REG 51295b482a8SLen Brown * method for this region. 51395b482a8SLen Brown * 514760235cdSLv Zheng * NOTE: Possible incompliance: 515760235cdSLv Zheng * There is a behavior conflict in automatic _REG execution: 516760235cdSLv Zheng * 1. When the interpreter is evaluating a method, we can only 517760235cdSLv Zheng * automatically run _REG for the following case: 518760235cdSLv Zheng * operation_region (OPR1, 0x80, 0x1000010, 0x4) 519760235cdSLv Zheng * 2. When the interpreter is loading a table, we can also 520760235cdSLv Zheng * automatically run _REG for the following case: 521760235cdSLv Zheng * operation_region (OPR1, 0x80, 0x1000010, 0x4) 522760235cdSLv Zheng * Though this may not be compliant to the de-facto standard, the 523760235cdSLv Zheng * logic is kept in order not to trigger regressions. And keeping 524760235cdSLv Zheng * this logic should be taken care by the caller of this function. 525760235cdSLv Zheng * 52695b482a8SLen Brown ******************************************************************************/ 52795b482a8SLen Brown 528760235cdSLv Zheng acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj) 52995b482a8SLen Brown { 53095b482a8SLen Brown union acpi_operand_object *handler_obj; 53195b482a8SLen Brown union acpi_operand_object *obj_desc; 53295b482a8SLen Brown acpi_adr_space_type space_id; 53395b482a8SLen Brown struct acpi_namespace_node *node; 53495b482a8SLen Brown 535760235cdSLv Zheng ACPI_FUNCTION_TRACE(ev_initialize_region); 53695b482a8SLen Brown 53795b482a8SLen Brown if (!region_obj) { 53895b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 53995b482a8SLen Brown } 54095b482a8SLen Brown 54195b482a8SLen Brown if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { 54295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 54395b482a8SLen Brown } 54495b482a8SLen Brown 545849c2571SLv Zheng region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; 54695b482a8SLen Brown 547c45b5c09SAlexey Starikovskiy node = region_obj->region.node->parent; 54895b482a8SLen Brown space_id = region_obj->region.space_id; 54995b482a8SLen Brown 55095b482a8SLen Brown /* 55195b482a8SLen Brown * The following loop depends upon the root Node having no parent 5527b738064SBob Moore * ie: acpi_gbl_root_node->Parent being set to NULL 55395b482a8SLen Brown */ 55495b482a8SLen Brown while (node) { 55595b482a8SLen Brown 55695b482a8SLen Brown /* Check to see if a handler exists */ 55795b482a8SLen Brown 55895b482a8SLen Brown handler_obj = NULL; 55995b482a8SLen Brown obj_desc = acpi_ns_get_attached_object(node); 56095b482a8SLen Brown if (obj_desc) { 56195b482a8SLen Brown 56295b482a8SLen Brown /* Can only be a handler if the object exists */ 56395b482a8SLen Brown 56495b482a8SLen Brown switch (node->type) { 56595b482a8SLen Brown case ACPI_TYPE_DEVICE: 56695b482a8SLen Brown case ACPI_TYPE_PROCESSOR: 56795b482a8SLen Brown case ACPI_TYPE_THERMAL: 56895b482a8SLen Brown 569aa6abd2bSLv Zheng handler_obj = obj_desc->common_notify.handler; 57095b482a8SLen Brown break; 57195b482a8SLen Brown 57295b482a8SLen Brown default: 5731d1ea1b7SChao Guan 57495b482a8SLen Brown /* Ignore other objects */ 5751d1ea1b7SChao Guan 57695b482a8SLen Brown break; 57795b482a8SLen Brown } 57895b482a8SLen Brown 579f31a99ceSLv Zheng handler_obj = 580f31a99ceSLv Zheng acpi_ev_find_region_handler(space_id, handler_obj); 581f31a99ceSLv Zheng if (handler_obj) { 58295b482a8SLen Brown 58395b482a8SLen Brown /* Found correct handler */ 58495b482a8SLen Brown 58595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 58695b482a8SLen Brown "Found handler %p for region %p in obj %p\n", 587f31a99ceSLv Zheng handler_obj, region_obj, 58895b482a8SLen Brown obj_desc)); 58995b482a8SLen Brown 590760235cdSLv Zheng (void)acpi_ev_attach_region(handler_obj, 591760235cdSLv Zheng region_obj, FALSE); 59295b482a8SLen Brown 59395b482a8SLen Brown /* 594d4913dc6SBob Moore * Tell all users that this region is usable by 595d4913dc6SBob Moore * running the _REG method 59695b482a8SLen Brown */ 5978633db6bSLv Zheng acpi_ex_exit_interpreter(); 598760235cdSLv Zheng (void)acpi_ev_execute_reg_method(region_obj, 599f31a99ceSLv Zheng ACPI_REG_CONNECT); 6008633db6bSLv Zheng acpi_ex_enter_interpreter(); 60195b482a8SLen Brown return_ACPI_STATUS(AE_OK); 60295b482a8SLen Brown } 60395b482a8SLen Brown } 60495b482a8SLen Brown 60595b482a8SLen Brown /* This node does not have the handler we need; Pop up one level */ 60695b482a8SLen Brown 607c45b5c09SAlexey Starikovskiy node = node->parent; 60895b482a8SLen Brown } 60995b482a8SLen Brown 610760235cdSLv Zheng /* 611760235cdSLv Zheng * If we get here, there is no handler for this region. This is not 612760235cdSLv Zheng * fatal because many regions get created before a handler is installed 613760235cdSLv Zheng * for said region. 614760235cdSLv Zheng */ 61595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 61695b482a8SLen Brown "No handler for RegionType %s(%X) (RegionObj %p)\n", 61795b482a8SLen Brown acpi_ut_get_region_name(space_id), space_id, 61895b482a8SLen Brown region_obj)); 61995b482a8SLen Brown 620760235cdSLv Zheng return_ACPI_STATUS(AE_OK); 62195b482a8SLen Brown } 622