evrgnini.c
来自「linux 内核源代码」· C语言 代码 · 共 689 行 · 第 1/2 页
C
689 行
/****************************************************************************** * * Module Name: evrgnini- ACPI address_space (op_region) init * *****************************************************************************//* * Copyright (C) 2000 - 2007, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */#include <acpi/acpi.h>#include <acpi/acevents.h>#include <acpi/acnamesp.h>#define _COMPONENT ACPI_EVENTSACPI_MODULE_NAME("evrgnini")/* Local prototypes */static u8 acpi_ev_match_pci_root_bridge(char *id);static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);/******************************************************************************* * * FUNCTION: acpi_ev_system_memory_region_setup * * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * * RETURN: Status * * DESCRIPTION: Setup a system_memory operation region * ******************************************************************************/acpi_statusacpi_ev_system_memory_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context){ union acpi_operand_object *region_desc = (union acpi_operand_object *)handle; struct acpi_mem_space_context *local_region_context; ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { local_region_context = (struct acpi_mem_space_context *)*region_context; /* Delete a cached mapping if present */ if (local_region_context->mapped_length) { acpi_os_unmap_memory(local_region_context-> mapped_logical_address, local_region_context-> mapped_length); } ACPI_FREE(local_region_context); *region_context = NULL; } return_ACPI_STATUS(AE_OK); } /* Create a new context */ local_region_context = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); if (!(local_region_context)) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Save the region length and address for use in the handler */ local_region_context->length = region_desc->region.length; local_region_context->address = region_desc->region.address; *region_context = local_region_context; return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_io_space_region_setup * * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * * RETURN: Status * * DESCRIPTION: Setup a IO operation region * ******************************************************************************/acpi_statusacpi_ev_io_space_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context){ ACPI_FUNCTION_TRACE(ev_io_space_region_setup); if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; } else { *region_context = handler_context; } return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_pci_config_region_setup * * PARAMETERS: Handle - Region we are interested in * Function - Start or stop * handler_context - Address space handler context * region_context - Region specific context * * RETURN: Status * * DESCRIPTION: Setup a PCI_Config operation region * * MUTEX: Assumes namespace is not locked * ******************************************************************************/acpi_statusacpi_ev_pci_config_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context){ acpi_status status = AE_OK; acpi_integer pci_value; struct acpi_pci_id *pci_id = *region_context; union acpi_operand_object *handler_obj; struct acpi_namespace_node *parent_node; struct acpi_namespace_node *pci_root_node; struct acpi_namespace_node *pci_device_node; union acpi_operand_object *region_obj = (union acpi_operand_object *)handle; ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); handler_obj = region_obj->region.handler; if (!handler_obj) { /* * No installed handler. This shouldn't happen because the dispatch * routine checks before we get here, but we check again just in case. */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Attempting to init a region %p, with no handler\n", region_obj)); return_ACPI_STATUS(AE_NOT_EXIST); } *region_context = NULL; if (function == ACPI_REGION_DEACTIVATE) { if (pci_id) { ACPI_FREE(pci_id); } return_ACPI_STATUS(status); } parent_node = acpi_ns_get_parent_node(region_obj->region.node); /* * Get the _SEG and _BBN values from the device upon which the handler * is installed. * * We need to get the _SEG and _BBN objects relative to the PCI BUS device. * This is the device the handler has been registered to handle. */ /* * If the address_space.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the op_region * handlers with that device. */ if (handler_obj->address_space.node == acpi_gbl_root_node) { /* Start search from the parent object */ pci_root_node = parent_node; while (pci_root_node != acpi_gbl_root_node) { /* Get the _HID/_CID in order to detect a root_bridge */ if (acpi_ev_is_pci_root_bridge(pci_root_node)) { /* Install a handler for this PCI root bridge */ status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE(status)) { if (status == AE_SAME_HANDLER) { /* * It is OK if the handler is already installed on the root * bridge. Still need to return a context object for the * new PCI_Config operation region, however. */ status = AE_OK; } else { ACPI_EXCEPTION((AE_INFO, status, "Could not install PciConfig handler for Root Bridge %4.4s", acpi_ut_get_node_name (pci_root_node))); } } break; } pci_root_node = acpi_ns_get_parent_node(pci_root_node); } /* PCI root bridge not found, use namespace root node */ } else { pci_root_node = handler_obj->address_space.node; } /* * If this region is now initialized, we are done. * (install_address_space_handler could have initialized it) */ if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { return_ACPI_STATUS(AE_OK); } /* Region is still not initialized. Create a new context */ pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); if (!pci_id) { return_ACPI_STATUS(AE_NO_MEMORY); } /* * For PCI_Config space access, we need the segment, bus, * device and function numbers. Acquire them here. * * Find the parent device object. (This allows the operation region to be * within a subscope under the device, such as a control method.) */ pci_device_node = region_obj->region.node; while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { pci_device_node = acpi_ns_get_parent_node(pci_device_node); } if (!pci_device_node) { ACPI_FREE(pci_id); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* * Get the PCI device and function numbers from the _ADR object * contained in the parent's scope. */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, &pci_value); /* * The default is zero, and since the allocation above zeroed * the data, just do nothing on failure. */ if (ACPI_SUCCESS(status)) { pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); } /* The PCI segment number comes from the _SEG method */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->segment = ACPI_LOWORD(pci_value); } /* The PCI bus number comes from the _BBN method */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->bus = ACPI_LOWORD(pci_value); } /* Complete this device's pci_id */ acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); *region_context = pci_id; return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_match_pci_root_bridge * * PARAMETERS: Id - The HID/CID in string format * * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge * * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. * ******************************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?