예제 #1
0
파일: evrgnini.c 프로젝트: a2hojsjsjs/linux
acpi_status
acpi_ev_initialize_region(union acpi_operand_object *region_obj,
			  u8 acpi_ns_locked)
{
	union acpi_operand_object *handler_obj;
	union acpi_operand_object *obj_desc;
	acpi_adr_space_type space_id;
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);

	if (!region_obj) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
		return_ACPI_STATUS(AE_OK);
	}

	acpi_ev_associate_reg_method(region_obj);
	region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;

	node = region_obj->region.node->parent;
	space_id = region_obj->region.space_id;

	/*
	 * The following loop depends upon the root Node having no parent
	 * ie: acpi_gbl_root_node->Parent being set to NULL
	 */
	while (node) {

		/* Check to see if a handler exists */

		handler_obj = NULL;
		obj_desc = acpi_ns_get_attached_object(node);
		if (obj_desc) {

			/* Can only be a handler if the object exists */

			switch (node->type) {
			case ACPI_TYPE_DEVICE:
			case ACPI_TYPE_PROCESSOR:
			case ACPI_TYPE_THERMAL:

				handler_obj = obj_desc->common_notify.handler;
				break;

			case ACPI_TYPE_METHOD:
				/*
				 * If we are executing module level code, the original
				 * Node's object was replaced by this Method object and we
				 * saved the handler in the method object.
				 *
				 * See acpi_ns_exec_module_code
				 */
				if (obj_desc->method.
				    info_flags & ACPI_METHOD_MODULE_LEVEL) {
					handler_obj =
					    obj_desc->method.dispatch.handler;
				}
				break;

			default:

				/* Ignore other objects */

				break;
			}

			handler_obj =
			    acpi_ev_find_region_handler(space_id, handler_obj);
			if (handler_obj) {

				/* Found correct handler */

				ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
						  "Found handler %p for region %p in obj %p\n",
						  handler_obj, region_obj,
						  obj_desc));

				status =
				    acpi_ev_attach_region(handler_obj,
							  region_obj,
							  acpi_ns_locked);

				/*
				 * Tell all users that this region is usable by
				 * running the _REG method
				 */
				if (acpi_ns_locked) {
					status =
					    acpi_ut_release_mutex
					    (ACPI_MTX_NAMESPACE);
					if (ACPI_FAILURE(status)) {
						return_ACPI_STATUS(status);
					}
				}

				status =
				    acpi_ev_execute_reg_method(region_obj,
							       ACPI_REG_CONNECT);

				if (acpi_ns_locked) {
					status =
					    acpi_ut_acquire_mutex
					    (ACPI_MTX_NAMESPACE);
					if (ACPI_FAILURE(status)) {
						return_ACPI_STATUS(status);
					}
				}

				return_ACPI_STATUS(AE_OK);
			}
		}

		/* This node does not have the handler we need; Pop up one level */

		node = node->parent;
	}

	/* If we get here, there is no handler for this region */

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "No handler for RegionType %s(%X) (RegionObj %p)\n",
			  acpi_ut_get_region_name(space_id), space_id,
			  region_obj));

	return_ACPI_STATUS(AE_NOT_EXIST);
}
예제 #2
0
static acpi_status
acpi_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_validate_handle(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 (obj_desc->common.type == ACPI_TYPE_DEVICE) {

		/* Check if this Device already has a handler for this address space */

		next_handler_obj =
		    acpi_ev_find_region_handler(handler_obj->address_space.
						space_id,
						obj_desc->common_notify.
						handler);
		if (next_handler_obj) {

			/* Found a handler, is it for the same address space? */

			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);
		}

		/*
		 * 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);
}
예제 #3
0
acpi_status
acpi_ev_install_space_handler(struct acpi_namespace_node *node,
			      acpi_adr_space_type space_id,
			      acpi_adr_space_handler handler,
			      acpi_adr_space_setup setup, void *context)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;
	acpi_status status = AE_OK;
	acpi_object_type type;
	u8 flags = 0;

	ACPI_FUNCTION_TRACE(ev_install_space_handler);

	/*
	 * This registration is valid for only the types below and the root.
	 * The root node is where the default handlers get installed.
	 */
	if ((node->type != ACPI_TYPE_DEVICE) &&
	    (node->type != ACPI_TYPE_PROCESSOR) &&
	    (node->type != ACPI_TYPE_THERMAL) && (node != acpi_gbl_root_node)) {
		status = AE_BAD_PARAMETER;
		goto unlock_and_exit;
	}

	if (handler == ACPI_DEFAULT_HANDLER) {
		flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;

		switch (space_id) {
		case ACPI_ADR_SPACE_SYSTEM_MEMORY:

			handler = acpi_ex_system_memory_space_handler;
			setup = acpi_ev_system_memory_region_setup;
			break;

		case ACPI_ADR_SPACE_SYSTEM_IO:

			handler = acpi_ex_system_io_space_handler;
			setup = acpi_ev_io_space_region_setup;
			break;

		case ACPI_ADR_SPACE_PCI_CONFIG:

			handler = acpi_ex_pci_config_space_handler;
			setup = acpi_ev_pci_config_region_setup;
			break;

		case ACPI_ADR_SPACE_CMOS:

			handler = acpi_ex_cmos_space_handler;
			setup = acpi_ev_cmos_region_setup;
			break;

		case ACPI_ADR_SPACE_PCI_BAR_TARGET:

			handler = acpi_ex_pci_bar_space_handler;
			setup = acpi_ev_pci_bar_region_setup;
			break;

		case ACPI_ADR_SPACE_DATA_TABLE:

			handler = acpi_ex_data_table_space_handler;
			setup = NULL;
			break;

		default:

			status = AE_BAD_PARAMETER;
			goto unlock_and_exit;
		}
	}

	/* If the caller hasn't specified a setup routine, use the default */

	if (!setup) {
		setup = acpi_ev_default_region_setup;
	}

	/* Check for an existing internal object */

	obj_desc = acpi_ns_get_attached_object(node);
	if (obj_desc) {
		/*
		 * The attached device object already exists. Now make sure
		 * the handler is not already installed.
		 */
		handler_obj = acpi_ev_find_region_handler(space_id,
							  obj_desc->
							  common_notify.
							  handler);

		if (handler_obj) {
			if (handler_obj->address_space.handler == handler) {
				/*
				 * It is (relatively) OK to attempt to install the SAME
				 * handler twice. This can easily happen with the
				 * PCI_Config space.
				 */
				status = AE_SAME_HANDLER;
				goto unlock_and_exit;
			} else {
				/* A handler is already installed */

				status = AE_ALREADY_EXISTS;
			}

			goto unlock_and_exit;
		}
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
				  "Creating object on Device %p while installing handler\n",
				  node));

		/* obj_desc does not exist, create one */

		if (node->type == ACPI_TYPE_ANY) {
			type = ACPI_TYPE_DEVICE;
		} else {
			type = node->type;
		}

		obj_desc = acpi_ut_create_internal_object(type);
		if (!obj_desc) {
			status = AE_NO_MEMORY;
			goto unlock_and_exit;
		}

		/* Init new descriptor */

		obj_desc->common.type = (u8)type;

		/* Attach the new object to the Node */

		status = acpi_ns_attach_object(node, obj_desc, type);

		/* Remove local reference to the object */

		acpi_ut_remove_reference(obj_desc);

		if (ACPI_FAILURE(status)) {
			goto unlock_and_exit;
		}
	}

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "Installing address handler for region %s(%X) "
			  "on Device %4.4s %p(%p)\n",
			  acpi_ut_get_region_name(space_id), space_id,
			  acpi_ut_get_node_name(node), node, obj_desc));

	/*
	 * Install the handler
	 *
	 * At this point there is no existing handler. Just allocate the object
	 * for the handler and link it into the list.
	 */
	handler_obj =
	    acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
	if (!handler_obj) {
		status = AE_NO_MEMORY;
		goto unlock_and_exit;
	}

	/* Init handler obj */

	handler_obj->address_space.space_id = (u8)space_id;
	handler_obj->address_space.handler_flags = flags;
	handler_obj->address_space.region_list = NULL;
	handler_obj->address_space.node = node;
	handler_obj->address_space.handler = handler;
	handler_obj->address_space.context = context;
	handler_obj->address_space.setup = setup;

	/* Install at head of Device.address_space list */

	handler_obj->address_space.next = obj_desc->common_notify.handler;

	/*
	 * The Device object is the first reference on the handler_obj.
	 * Each region that uses the handler adds a reference.
	 */
	obj_desc->common_notify.handler = handler_obj;

	/*
	 * Walk the namespace finding all of the regions this handler will
	 * manage.
	 *
	 * Start at the device and search the branch toward the leaf nodes
	 * until either the leaf is encountered or a device is detected that
	 * has an address handler of the same type.
	 *
	 * In either case, back up and search down the remainder of the branch
	 */
	status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node,
					ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
					acpi_ev_install_handler, NULL,
					handler_obj, NULL);

unlock_and_exit:
	return_ACPI_STATUS(status);
}
예제 #4
0
파일: dbdisply.c 프로젝트: a2hojsjsjs/linux
void acpi_db_display_handlers(void)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;
	acpi_adr_space_type space_id;
	u32 i;

	/* Operation region handlers */

	acpi_os_printf("\nOperation Region Handlers at the namespace root:\n");

	obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
	if (obj_desc) {
		for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_space_id_list); i++) {
			space_id = acpi_gbl_space_id_list[i];

			acpi_os_printf(ACPI_PREDEFINED_PREFIX,
				       acpi_ut_get_region_name((u8)space_id),
				       space_id);

			handler_obj =
			    acpi_ev_find_region_handler(space_id,
							obj_desc->common_notify.
							handler);
			if (handler_obj) {
				acpi_os_printf(ACPI_HANDLER_PRESENT_STRING,
					       (handler_obj->address_space.
						handler_flags &
						ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
					       ? "Default" : "User",
					       handler_obj->address_space.
					       handler);

				goto found_handler;
			}

			/* There is no handler for this space_id */

			acpi_os_printf("None\n");

found_handler:		;
		}

		/* Find all handlers for user-defined space_IDs */

		handler_obj = obj_desc->common_notify.handler;
		while (handler_obj) {
			if (handler_obj->address_space.space_id >=
			    ACPI_USER_REGION_BEGIN) {
				acpi_os_printf(ACPI_PREDEFINED_PREFIX,
					       "User-defined ID",
					       handler_obj->address_space.
					       space_id);
				acpi_os_printf(ACPI_HANDLER_PRESENT_STRING,
					       (handler_obj->address_space.
						handler_flags &
						ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
					       ? "Default" : "User",
					       handler_obj->address_space.
					       handler);
			}

			handler_obj = handler_obj->address_space.next;
		}
	}
#if (!ACPI_REDUCED_HARDWARE)

	/* Fixed event handlers */

	acpi_os_printf("\nFixed Event Handlers:\n");

	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
		acpi_os_printf(ACPI_PREDEFINED_PREFIX,
			       acpi_ut_get_event_name(i), i);
		if (acpi_gbl_fixed_event_handlers[i].handler) {
			acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User",
				       acpi_gbl_fixed_event_handlers[i].
				       handler);
		} else {
			acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None");
		}
	}

#endif				/* !ACPI_REDUCED_HARDWARE */

	/* Miscellaneous global handlers */

	acpi_os_printf("\nMiscellaneous Global Handlers:\n");

	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_handler_list); i++) {
		acpi_os_printf(ACPI_HANDLER_NAME_STRING,
			       acpi_gbl_handler_list[i].name);

		if (acpi_gbl_handler_list[i].handler) {
			acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User",
				       acpi_gbl_handler_list[i].handler);
		} else {
			acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None");
		}
	}

	/* Other handlers that are installed throughout the namespace */

	acpi_os_printf("\nOperation Region Handlers for specific devices:\n");

	(void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
				  ACPI_UINT32_MAX,
				  acpi_db_display_non_root_handlers, NULL, NULL,
				  NULL);
}