📄 evregion.c
字号:
* ******************************************************************************/voidacpi_ev_detach_region( union acpi_operand_object *region_obj, u8 acpi_ns_is_locked){ union acpi_operand_object *handler_obj; union acpi_operand_object *obj_desc; union acpi_operand_object **last_obj_ptr; acpi_adr_space_setup region_setup; void **region_context; union acpi_operand_object *region_obj2; acpi_status status; ACPI_FUNCTION_TRACE ("ev_detach_region"); region_obj2 = acpi_ns_get_secondary_object (region_obj); if (!region_obj2) { return_VOID; } region_context = ®ion_obj2->extra.region_context; /* Get the address handler from the region object */ handler_obj = region_obj->region.handler; if (!handler_obj) { /* This region has no handler, all done */ return_VOID; } /* Find this region in the handler's list */ obj_desc = handler_obj->address_space.region_list; last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { /* Is this the correct Region? */ if (obj_desc == region_obj) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Removing Region %p from address handler %p\n", region_obj, handler_obj)); /* This is it, remove it from the handler's list */ *last_obj_ptr = obj_desc->region.next; obj_desc->region.next = NULL; /* Must clear field */ if (acpi_ns_is_locked) { status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return_VOID; } } /* Now stop region accesses by executing the _REG method */ status = acpi_ev_execute_reg_method (region_obj, 0); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n", acpi_format_exception (status), acpi_ut_get_region_name (region_obj->region.space_id))); } if (acpi_ns_is_locked) { status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return_VOID; } } /* Call the setup handler with the deactivate notification */ region_setup = handler_obj->address_space.setup; status = region_setup (region_obj, ACPI_REGION_DEACTIVATE, handler_obj->address_space.context, region_context); /* Init routine may fail, Just ignore errors */ if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n", acpi_format_exception (status), acpi_ut_get_region_name (region_obj->region.space_id))); } region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); /* * Remove handler reference in the region * * NOTE: this doesn't mean that the region goes away * The region is just inaccessible as indicated to * the _REG method * * If the region is on the handler's list * this better be the region's handler */ region_obj->region.handler = NULL; acpi_ut_remove_reference (handler_obj); return_VOID; } /* Walk the linked list of handlers */ last_obj_ptr = &obj_desc->region.next; obj_desc = obj_desc->region.next; } /* If we get here, the region was not in the handler's region list */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Cannot remove region %p from address handler %p\n", region_obj, handler_obj)); return_VOID;}/******************************************************************************* * * FUNCTION: acpi_ev_attach_region * * PARAMETERS: handler_obj - Handler Object * region_obj - Region Object * acpi_ns_is_locked - Namespace Region Already Locked? * * RETURN: None * * DESCRIPTION: Create the association between the handler and the region * this is a two way association. * ******************************************************************************/acpi_statusacpi_ev_attach_region ( union acpi_operand_object *handler_obj, union acpi_operand_object *region_obj, u8 acpi_ns_is_locked){ ACPI_FUNCTION_TRACE ("ev_attach_region"); ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Adding Region [%4.4s] %p to address handler %p [%s]\n", acpi_ut_get_node_name (region_obj->region.node), region_obj, handler_obj, acpi_ut_get_region_name (region_obj->region.space_id))); /* Link this region to the front of the handler's list */ region_obj->region.next = handler_obj->address_space.region_list; handler_obj->address_space.region_list = region_obj; /* Install the region's handler */ if (region_obj->region.handler) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } region_obj->region.handler = handler_obj; acpi_ut_add_reference (handler_obj); return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_install_handler * * PARAMETERS: walk_namespace callback * * DESCRIPTION: This routine installs an address handler into objects that are * of type Region or Device. * * If the Object is a Device, and the device has a handler of * the same type then the search is terminated in that branch. * * This is because the existing handler is closer in proximity * to any more regions than the one we are trying to install. * ******************************************************************************/acpi_statusacpi_ev_install_handler ( acpi_handle obj_handle, u32 level, void *context, void **return_value){ union acpi_operand_object *handler_obj; union acpi_operand_object *next_handler_obj; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; acpi_status status; ACPI_FUNCTION_NAME ("ev_install_handler"); handler_obj = (union acpi_operand_object *) context; /* Parameter validation */ if (!handler_obj) { return (AE_OK); } /* Convert and validate the device handle */ node = acpi_ns_map_handle_to_node (obj_handle); if (!node) { return (AE_BAD_PARAMETER); } /* * We only care about regions.and objects * that are allowed to have address space handlers */ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { return (AE_OK); } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { /* No object, just exit */ return (AE_OK); } /* Devices are handled different than regions */ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ next_handler_obj = obj_desc->device.handler; while (next_handler_obj) { /* Found a handler, is it for the same address space? */ if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) handler %p\n", acpi_ut_get_region_name (handler_obj->address_space.space_id), obj_desc, next_handler_obj, handler_obj)); /* * Since the object we found it on was a device, then it * means that someone has already installed a handler for * the branch of the namespace from this device on. Just * bail out telling the walk routine to not traverse this * branch. This preserves the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } /* Walk the linked list of handlers attached to this device */ next_handler_obj = next_handler_obj->address_space.next; } /* * As long as the device didn't have a handler for this * space we don't care about it. We just ignore it and * proceed. */ return (AE_OK); } /* Object is a Region */ if (obj_desc->region.space_id != handler_obj->address_space.space_id) { /* * This region is for a different address space * -- just ignore it */ return (AE_OK); } /* * Now we have a region and it is for the handler's address * space type. * * First disconnect region for any previous handler (if any) */ acpi_ev_detach_region (obj_desc, FALSE); /* Connect the region to the new handler */ status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); return (status);}/******************************************************************************* * * FUNCTION: acpi_ev_reg_run * * PARAMETERS: walk_namespace callback * * DESCRIPTION: Run _REg method for region objects of the requested space_iD * ******************************************************************************/acpi_statusacpi_ev_reg_run ( acpi_handle obj_handle, u32 level, void *context, void **return_value){ union acpi_operand_object *handler_obj; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; acpi_status status; handler_obj = (union acpi_operand_object *) context; /* Parameter validation */ if (!handler_obj) { return (AE_OK); } /* Convert and validate the device handle */ node = acpi_ns_map_handle_to_node (obj_handle); if (!node) { return (AE_BAD_PARAMETER); } /* * We only care about regions.and objects * that are allowed to have address space handlers */ if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { return (AE_OK); } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { /* No object, just exit */ return (AE_OK); } /* Object is a Region */ if (obj_desc->region.space_id != handler_obj->address_space.space_id) { /* * This region is for a different address space * -- just ignore it */ return (AE_OK); } status = acpi_ev_execute_reg_method (obj_desc, 1); return (status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -