예제 #1
0
acpi_status
acpi_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);
}
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
	u64 address;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_write);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
		status = acpi_os_write_memory((acpi_physical_address)
					      address, (u64)value,
					      reg->bit_width);
	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

		status = acpi_hw_write_port((acpi_io_address)
					    address, value, reg->bit_width);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
			  value, reg->bit_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}
예제 #3
0
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
	u64 address;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_read);

	

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	

	*value = 0;

	
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
		status = acpi_os_read_memory((acpi_physical_address)
					     address, value, reg->bit_width);
	} else {		

		status = acpi_hw_read_port((acpi_io_address)
					   address, value, reg->bit_width);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
			  *value, reg->bit_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}
예제 #4
0
u32
acpi_ut_check_address_range(acpi_adr_space_type space_id,
			    acpi_physical_address address, u32 length, u8 warn)
{
	struct acpi_address_range *range_info;
	acpi_physical_address end_address;
	char *pathname;
	u32 overlap_count = 0;

	ACPI_FUNCTION_TRACE(ut_check_address_range);

	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
		return_UINT32(0);
	}

	range_info = acpi_gbl_address_range_list[space_id];
	end_address = address + length - 1;

	/* Check entire list for all possible conflicts */

	while (range_info) {
		/*
		 * Check if the requested address/length overlaps this
		 * address range. There are four cases to consider:
		 *
		 * 1) Input address/length is contained completely in the
		 *    address range
		 * 2) Input address/length overlaps range at the range start
		 * 3) Input address/length overlaps range at the range end
		 * 4) Input address/length completely encompasses the range
		 */
		if ((address <= range_info->end_address) &&
		    (end_address >= range_info->start_address)) {

			/* Found an address range overlap */

			overlap_count++;
			if (warn) {	/* Optional warning message */
				pathname =
				    acpi_ns_get_external_pathname(range_info->
								  region_node);

				ACPI_WARNING((AE_INFO,
					      "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)",
					      acpi_ut_get_region_name (space_id),
					      ACPI_CAST_PTR(void, address),
					      ACPI_CAST_PTR(void, end_address),
					      ACPI_CAST_PTR(void, range_info->start_address),
					      ACPI_CAST_PTR(void, range_info->end_address),
					      pathname));
				ACPI_FREE(pathname);
			}
		}

		range_info = range_info->next;
	}
예제 #5
0
acpi_status
acpi_ev_attach_region (
	union acpi_operand_object       *handler_obj,
	union acpi_operand_object       *region_obj,
	u8                              acpi_ns_is_locked)
{
	acpi_status                     status;
	acpi_status                     status2;


	ACPI_FUNCTION_TRACE ("ev_attach_region");


	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
		"Adding Region %p to address handler %p [%s]\n",
		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.address_space) {
		return_ACPI_STATUS (AE_ALREADY_EXISTS);
	}

	region_obj->region.address_space = handler_obj;
	acpi_ut_add_reference (handler_obj);

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

	status = acpi_ev_execute_reg_method (region_obj, 1);

	if (acpi_ns_is_locked) {
		status2 = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}
	}

	return_ACPI_STATUS (status);
}
예제 #6
0
파일: evregion.c 프로젝트: 0-T-0/ps4-linux
acpi_status
acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
			    acpi_adr_space_type space_id)
{
	acpi_status status;
	struct acpi_reg_walk_info info;

	ACPI_FUNCTION_TRACE(ev_execute_reg_methods);

	info.space_id = space_id;
	info.reg_run_count = 0;

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
			      "    Running _REG methods for SpaceId %s\n",
			      acpi_ut_get_region_name(info.space_id)));

	/*
	 * Run all _REG methods for all Operation Regions for this space ID. This
	 * is a separate walk in order to handle any interdependencies between
	 * regions and _REG methods. (i.e. handlers must be installed for all
	 * regions of this Space ID before we can run any _REG methods)
	 */
	status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
					ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
					NULL, &info, NULL);

	/* Special case for EC: handle "orphan" _REG methods with no region */

	if (space_id == ACPI_ADR_SPACE_EC) {
		acpi_ev_orphan_ec_reg_method(node);
	}

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
			      "    Executed %u _REG methods for SpaceId %s\n",
			      info.reg_run_count,
			      acpi_ut_get_region_name(info.space_id)));

	return_ACPI_STATUS(status);
}
예제 #7
0
파일: dbdisply.c 프로젝트: a2hojsjsjs/linux
static acpi_status
acpi_db_display_non_root_handlers(acpi_handle obj_handle,
				  u32 nesting_level,
				  void *context, void **return_value)
{
	struct acpi_namespace_node *node =
	    ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;
	char *pathname;

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return (AE_OK);
	}

	pathname = acpi_ns_get_normalized_pathname(node, TRUE);
	if (!pathname) {
		return (AE_OK);
	}

	/* Display all handlers associated with this device */

	handler_obj = obj_desc->common_notify.handler;
	while (handler_obj) {
		acpi_os_printf(ACPI_PREDEFINED_PREFIX,
			       acpi_ut_get_region_name((u8)handler_obj->
						       address_space.space_id),
			       handler_obj->address_space.space_id);

		acpi_os_printf(ACPI_HANDLER_PRESENT_STRING2,
			       (handler_obj->address_space.handler_flags &
				ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default"
			       : "User", handler_obj->address_space.handler);

		acpi_os_printf(" Device Name: %s (%p)\n", pathname, node);

		handler_obj = handler_obj->address_space.next;
	}

	ACPI_FREE(pathname);
	return (AE_OK);
}
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
	u64 address;
	u64 value64;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_read);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/* Initialize entire 32-bit return value to zero */

	*value = 0;

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
		status = acpi_os_read_memory((acpi_physical_address)
					     address, &value64, reg->bit_width);

		*value = (u32)value64;
	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

		status = acpi_hw_read_port((acpi_io_address)
					   address, value, reg->bit_width);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
			  *value, reg->bit_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}
예제 #9
0
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;
	struct acpi_namespace_node *method_node;
	acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
	union acpi_operand_object *region_obj2;

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

	region_obj2 = acpi_ns_get_secondary_object(region_obj);
	if (!region_obj2) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	node = acpi_ns_get_parent_node(region_obj->region.node);
	space_id = region_obj->region.space_id;

	/* Setup defaults */

	region_obj->region.handler = NULL;
	region_obj2->extra.method_REG = NULL;
	region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE);
	region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;

	/* Find any "_REG" method associated with this region definition */

	status =
	    acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
				     &method_node);
	if (ACPI_SUCCESS(status)) {
		/*
		 * The _REG method is optional and there can be only one per region
		 * definition.  This will be executed when the handler is attached
		 * or removed
		 */
		region_obj2->extra.method_REG = method_node;
	}

	/*
	 * The following loop depends upon the root Node having no parent
	 * ie: acpi_gbl_root_node->parent_entry 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:

				handler_obj = obj_desc->device.handler;
				break;

			case ACPI_TYPE_PROCESSOR:

				handler_obj = obj_desc->processor.handler;
				break;

			case ACPI_TYPE_THERMAL:

				handler_obj = obj_desc->thermal_zone.handler;
				break;

			default:
				/* Ignore other objects */
				break;
			}

			while (handler_obj) {

				/* Is this handler of the correct type? */

				if (handler_obj->address_space.space_id ==
				    space_id) {

					/* 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, 1);

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

				/* Try next handler in the list */

				handler_obj = handler_obj->address_space.next;
			}
		}

		/*
		 * This node does not have the handler we need;
		 * Pop up one level
		 */
		node = acpi_ns_get_parent_node(node);
	}

	/* 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);
}
예제 #10
0
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                               union acpi_operand_object *field_obj,
                               u32 function,
                               u32 region_offset, u32 bit_width, u64 *value)
{
    acpi_status status;
    acpi_adr_space_handler handler;
    acpi_adr_space_setup region_setup;
    union acpi_operand_object *handler_desc;
    union acpi_operand_object *region_obj2;
    void *region_context = NULL;
    struct acpi_connection_info *context;
    acpi_physical_address address;

    ACPI_FUNCTION_TRACE(ev_address_space_dispatch);

    region_obj2 = acpi_ns_get_secondary_object(region_obj);
    if (!region_obj2) {
        return_ACPI_STATUS(AE_NOT_EXIST);
    }

    /* Ensure that there is a handler associated with this region */

    handler_desc = region_obj->region.handler;
    if (!handler_desc) {
        ACPI_ERROR((AE_INFO,
                    "No handler for Region [%4.4s] (%p) [%s]",
                    acpi_ut_get_node_name(region_obj->region.node),
                    region_obj,
                    acpi_ut_get_region_name(region_obj->region.
                                            space_id)));

        return_ACPI_STATUS(AE_NOT_EXIST);
    }

    context = handler_desc->address_space.context;

    /*
     * It may be the case that the region has never been initialized.
     * Some types of regions require special init code
     */
    if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {

        /* This region has not been initialized yet, do it */

        region_setup = handler_desc->address_space.setup;
        if (!region_setup) {

            /* No initialization routine, exit with error */

            ACPI_ERROR((AE_INFO,
                        "No init routine for region(%p) [%s]",
                        region_obj,
                        acpi_ut_get_region_name(region_obj->region.
                                                space_id)));
            return_ACPI_STATUS(AE_NOT_EXIST);
        }

        /*
         * We must exit the interpreter because the region setup will
         * potentially execute control methods (for example, the _REG method
         * for this region)
         */
        acpi_ex_exit_interpreter();

        status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
                              context, &region_context);

        /* Re-enter the interpreter */

        acpi_ex_enter_interpreter();

        /* Check for failure of the Region Setup */

        if (ACPI_FAILURE(status)) {
            ACPI_EXCEPTION((AE_INFO, status,
                            "During region initialization: [%s]",
                            acpi_ut_get_region_name(region_obj->
                                                    region.
                                                    space_id)));
            return_ACPI_STATUS(status);
        }

        /* Region initialization may have been completed by region_setup */

        if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
            region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;

            /*
             * Save the returned context for use in all accesses to
             * the handler for this particular region
             */
            if (!(region_obj2->extra.region_context)) {
                region_obj2->extra.region_context =
                    region_context;
            }
        }
    }

    /* We have everything we need, we can invoke the address space handler */

    handler = handler_desc->address_space.handler;
    address = (region_obj->region.address + region_offset);

    /*
     * Special handling for generic_serial_bus and general_purpose_io:
     * There are three extra parameters that must be passed to the
     * handler via the context:
     *   1) Connection buffer, a resource template from Connection() op
     *   2) Length of the above buffer
     *   3) Actual access length from the access_as() op
     *
     * In addition, for general_purpose_io, the Address and bit_width fields
     * are defined as follows:
     *   1) Address is the pin number index of the field (bit offset from
     *      the previous Connection)
     *   2) bit_width is the actual bit length of the field (number of pins)
     */
    if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
            context && field_obj) {

        /* Get the Connection (resource_template) buffer */

        context->connection = field_obj->field.resource_buffer;
        context->length = field_obj->field.resource_length;
        context->access_length = field_obj->field.access_length;
    }
    if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
            context && field_obj) {

        /* Get the Connection (resource_template) buffer */

        context->connection = field_obj->field.resource_buffer;
        context->length = field_obj->field.resource_length;
        context->access_length = field_obj->field.access_length;
        address = field_obj->field.pin_number_index;
        bit_width = field_obj->field.bit_length;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                      "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
                      &region_obj->region.handler->address_space, handler,
                      ACPI_FORMAT_NATIVE_UINT(address),
                      acpi_ut_get_region_name(region_obj->region.
                              space_id)));

    if (!(handler_desc->address_space.handler_flags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
        /*
         * For handlers other than the default (supplied) handlers, we must
         * exit the interpreter because the handler *might* block -- we don't
         * know what it will do, so we can't hold the lock on the intepreter.
         */
        acpi_ex_exit_interpreter();
    }

    /* Call the handler */

    status = handler(function, address, bit_width, value, context,
                     region_obj2->extra.region_context);

    if (ACPI_FAILURE(status)) {
        ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
                        acpi_ut_get_region_name(region_obj->region.
                                                space_id)));
    }

    if (!(handler_desc->address_space.handler_flags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
        /*
         * We just returned from a non-default handler, we must re-enter the
         * interpreter
         */
        acpi_ex_enter_interpreter();
    }

    return_ACPI_STATUS(status);
}
예제 #11
0
파일: exfldio.c 프로젝트: AiWinters/linux
acpi_status
acpi_ex_access_region(union acpi_operand_object *obj_desc,
		      u32 field_datum_byte_offset, u64 *value, u32 function)
{
	acpi_status status;
	union acpi_operand_object *rgn_desc;
	u32 region_offset;

	ACPI_FUNCTION_TRACE(ex_access_region);

	/*
	 * Ensure that the region operands are fully evaluated and verify
	 * the validity of the request
	 */
	status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * The physical address of this field datum is:
	 *
	 * 1) The base of the region, plus
	 * 2) The base offset of the field, plus
	 * 3) The current offset into the field
	 */
	rgn_desc = obj_desc->common_field.region_obj;
	region_offset =
	    obj_desc->common_field.base_byte_offset + field_datum_byte_offset;

	if ((function & ACPI_IO_MASK) == ACPI_READ) {
		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
	}

	ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
			      " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
			      acpi_ut_get_region_name(rgn_desc->region.
						      space_id),
			      rgn_desc->region.space_id,
			      obj_desc->common_field.access_byte_width,
			      obj_desc->common_field.base_byte_offset,
			      field_datum_byte_offset, ACPI_CAST_PTR(void,
								     (rgn_desc->
								      region.
								      address +
								      region_offset))));

	/* Invoke the appropriate address_space/op_region handler */

	status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
						function, region_offset,
						ACPI_MUL_8(obj_desc->
							   common_field.
							   access_byte_width),
						value);

	if (ACPI_FAILURE(status)) {
		if (status == AE_NOT_IMPLEMENTED) {
			ACPI_ERROR((AE_INFO,
				    "Region %s (ID=%u) not implemented",
				    acpi_ut_get_region_name(rgn_desc->region.
							    space_id),
				    rgn_desc->region.space_id));
		} else if (status == AE_NOT_EXIST) {
			ACPI_ERROR((AE_INFO,
				    "Region %s (ID=%u) has no handler",
				    acpi_ut_get_region_name(rgn_desc->region.
							    space_id),
				    rgn_desc->region.space_id));
		}
	}

	return_ACPI_STATUS(status);
}
예제 #12
0
파일: nsdump.c 프로젝트: PyroOS/Pyro
acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
	struct acpi_namespace_node *this_node;
	union acpi_operand_object *obj_desc = NULL;
	acpi_object_type obj_type;
	acpi_object_type type;
	u32 bytes_to_dump;
	u32 dbg_level;
	u32 i;

	ACPI_FUNCTION_NAME(ns_dump_one_object);

	/* Is output enabled? */

	if (!(acpi_dbg_level & info->debug_level)) {
		return (AE_OK);
	}

	if (!obj_handle) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
		return (AE_OK);
	}

	this_node = acpi_ns_map_handle_to_node(obj_handle);
	type = this_node->type;

	/* Check if the owner matches */

	if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
	    (info->owner_id != this_node->owner_id)) {
		return (AE_OK);
	}

	if (!(info->display_type & ACPI_DISPLAY_SHORT)) {

		/* Indent the object according to the level */

		acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");

		/* Check the node type and name */

		if (type > ACPI_TYPE_LOCAL_MAX) {
			ACPI_WARNING((AE_INFO, "Invalid ACPI Object Type %08X",
				      type));
		}

		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
			this_node->name.integer =
			    acpi_ut_repair_name(this_node->name.ascii);

			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
				      this_node->name.integer));
		}

		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
	}

	/*
	 * Now we can print out the pertinent information
	 */
	acpi_os_printf(" %-12s %p %2.2X ",
		       acpi_ut_get_type_name(type), this_node,
		       this_node->owner_id);

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	/* Temp nodes are those nodes created by a control method */

	if (this_node->flags & ANOBJ_TEMPORARY) {
		acpi_os_printf("(T) ");
	}

	switch (info->display_type & ACPI_DISPLAY_MASK) {
	case ACPI_DISPLAY_SUMMARY:

		if (!obj_desc) {

			/* No attached object, we are done */

			acpi_os_printf("\n");
			return (AE_OK);
		}

		switch (type) {
		case ACPI_TYPE_PROCESSOR:

			acpi_os_printf("ID %X Len %.4X Addr %p\n",
				       obj_desc->processor.proc_id,
				       obj_desc->processor.length,
				       ACPI_CAST_PTR(void,
						     obj_desc->processor.
						     address));
			break;

		case ACPI_TYPE_DEVICE:

			acpi_os_printf("Notify Object: %p\n", obj_desc);
			break;

		case ACPI_TYPE_METHOD:

			acpi_os_printf("Args %X Len %.4X Aml %p\n",
				       (u32) obj_desc->method.param_count,
				       obj_desc->method.aml_length,
				       obj_desc->method.aml_start);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf("= %8.8X%8.8X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_PACKAGE:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Elements %.2X\n",
					       obj_desc->package.count);
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_BUFFER:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Len %.2X",
					       obj_desc->buffer.length);

				/* Dump some of the buffer */

				if (obj_desc->buffer.length > 0) {
					acpi_os_printf(" =");
					for (i = 0;
					     (i < obj_desc->buffer.length
					      && i < 12); i++) {
						acpi_os_printf(" %.2hX",
							       obj_desc->buffer.
							       pointer[i]);
					}
				}
				acpi_os_printf("\n");
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf("Len %.2X ", obj_desc->string.length);
			acpi_ut_print_string(obj_desc->string.pointer, 32);
			acpi_os_printf("\n");
			break;

		case ACPI_TYPE_REGION:

			acpi_os_printf("[%s]",
				       acpi_ut_get_region_name(obj_desc->region.
							       space_id));
			if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
					       ACPI_FORMAT_NATIVE_UINT
					       (obj_desc->region.address),
					       obj_desc->region.length);
			} else {
				acpi_os_printf
				    (" [Address/Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_LOCAL_REFERENCE:

			acpi_os_printf("[%s]\n",
				       acpi_ps_get_opcode_name(obj_desc->
							       reference.
							       opcode));
			break;

		case ACPI_TYPE_BUFFER_FIELD:

			if (obj_desc->buffer_field.buffer_obj &&
			    obj_desc->buffer_field.buffer_obj->buffer.node) {
				acpi_os_printf("Buf [%4.4s]",
					       acpi_ut_get_node_name(obj_desc->
								     buffer_field.
								     buffer_obj->
								     buffer.
								     node));
			}
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:

			acpi_os_printf("Rgn [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node));
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:

			acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node),
				       acpi_ut_get_node_name(obj_desc->
							     bank_field.
							     bank_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     index_obj->
							     common_field.node),
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     data_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_ALIAS:
		case ACPI_TYPE_LOCAL_METHOD_ALIAS:

			acpi_os_printf("Target %4.4s (%p)\n",
				       acpi_ut_get_node_name(obj_desc),
				       obj_desc);
			break;

		default:

			acpi_os_printf("Object %p\n", obj_desc);
			break;
		}

		/* Common field handling */

		switch (type) {
		case ACPI_TYPE_BUFFER_FIELD:
		case ACPI_TYPE_LOCAL_REGION_FIELD:
		case ACPI_TYPE_LOCAL_BANK_FIELD:
		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n",
				       (obj_desc->common_field.
					base_byte_offset * 8)
				       +
				       obj_desc->common_field.
				       start_field_bit_offset,
				       obj_desc->common_field.bit_length,
				       obj_desc->common_field.
				       access_byte_width);
			break;

		default:
			break;
		}
		break;

	case ACPI_DISPLAY_OBJECTS:

		acpi_os_printf("O:%p", obj_desc);
		if (!obj_desc) {

			/* No attached object, we are done */

			acpi_os_printf("\n");
			return (AE_OK);
		}

		acpi_os_printf("(R%d)", obj_desc->common.reference_count);

		switch (type) {
		case ACPI_TYPE_METHOD:

			/* Name is a Method and its AML offset/length are set */

			acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start,
				       obj_desc->method.aml_length);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf(" I:%8.8X8.8%X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer,
				       obj_desc->string.length);
			break;

		case ACPI_TYPE_BUFFER:

			acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer,
				       obj_desc->buffer.length);
			break;

		default:

			acpi_os_printf("\n");
			break;
		}
		break;

	default:
		acpi_os_printf("\n");
		break;
	}

	/* If debug turned off, done */

	if (!(acpi_dbg_level & ACPI_LV_VALUES)) {
		return (AE_OK);
	}

	/* If there is an attached object, display it */

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	/* Dump attached objects */

	while (obj_desc) {
		obj_type = ACPI_TYPE_INVALID;
		acpi_os_printf("Attached Object %p: ", obj_desc);

		/* Decode the type of attached object and dump the contents */

		switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
		case ACPI_DESC_TYPE_NAMED:

			acpi_os_printf("(Ptr to Node)\n");
			bytes_to_dump = sizeof(struct acpi_namespace_node);
			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			break;

		case ACPI_DESC_TYPE_OPERAND:

			obj_type = ACPI_GET_OBJECT_TYPE(obj_desc);

			if (obj_type > ACPI_TYPE_LOCAL_MAX) {
				acpi_os_printf
				    ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
				     obj_type);
				bytes_to_dump = 32;
			} else {
				acpi_os_printf
				    ("(Ptr to ACPI Object type %X [%s])\n",
				     obj_type, acpi_ut_get_type_name(obj_type));
				bytes_to_dump =
				    sizeof(union acpi_operand_object);
			}

			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			break;

		default:

			break;
		}

		/* If value is NOT an internal object, we are done */

		if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
		    ACPI_DESC_TYPE_OPERAND) {
			goto cleanup;
		}

		/*
		 * Valid object, get the pointer to next level, if any
		 */
		switch (obj_type) {
		case ACPI_TYPE_BUFFER:
		case ACPI_TYPE_STRING:
			/*
			 * NOTE: takes advantage of common fields between string/buffer
			 */
			bytes_to_dump = obj_desc->string.length;
			obj_desc = (void *)obj_desc->string.pointer;
			acpi_os_printf("(Buffer/String pointer %p length %X)\n",
				       obj_desc, bytes_to_dump);
			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			goto cleanup;

		case ACPI_TYPE_BUFFER_FIELD:
			obj_desc =
			    (union acpi_operand_object *)obj_desc->buffer_field.
			    buffer_obj;
			break;

		case ACPI_TYPE_PACKAGE:
			obj_desc = (void *)obj_desc->package.elements;
			break;

		case ACPI_TYPE_METHOD:
			obj_desc = (void *)obj_desc->method.aml_start;
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:
			obj_desc = (void *)obj_desc->field.region_obj;
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:
			obj_desc = (void *)obj_desc->bank_field.region_obj;
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:
			obj_desc = (void *)obj_desc->index_field.index_obj;
			break;

		default:
			goto cleanup;
		}

		obj_type = ACPI_TYPE_INVALID;	/* Terminate loop after next pass */
	}

      cleanup:
	acpi_os_printf("\n");
	return (AE_OK);
}
예제 #13
0
파일: hwregs.c 프로젝트: AngleFork/linux
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
	u64 address;
	u8 access_width;
	u32 bit_width;
	u8 bit_offset;
	u64 value64;
	u32 value32;
	u8 index;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_read);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/*
	 * Initialize entire 32-bit return value to zero, convert access_width
	 * into number of bits based
	 */
	*value = 0;
	access_width = acpi_hw_get_access_bit_width(reg, 32);
	bit_width = reg->bit_offset + reg->bit_width;
	bit_offset = reg->bit_offset;

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	index = 0;
	while (bit_width) {
		if (bit_offset >= access_width) {
			value32 = 0;
			bit_offset -= access_width;
		} else {
			if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
				status =
				    acpi_os_read_memory((acpi_physical_address)
							address +
							index *
							ACPI_DIV_8
							(access_width),
							&value64, access_width);
				value32 = (u32)value64;
			} else {	/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

				status = acpi_hw_read_port((acpi_io_address)
							   address +
							   index *
							   ACPI_DIV_8
							   (access_width),
							   &value32,
							   access_width);
			}

			/*
			 * Use offset style bit masks because:
			 * bit_offset < access_width/bit_width < access_width, and
			 * access_width is ensured to be less than 32-bits by
			 * acpi_hw_validate_register().
			 */
			if (bit_offset) {
				value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
				bit_offset = 0;
			}
			if (bit_width < access_width) {
				value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
			}
		}

		/*
		 * Use offset style bit writes because "Index * AccessWidth" is
		 * ensured to be less than 32-bits by acpi_hw_validate_register().
		 */
		ACPI_SET_BITS(value, index * access_width,
			      ACPI_MASK_BITS_ABOVE_32(access_width), value32);

		bit_width -=
		    bit_width > access_width ? access_width : bit_width;
		index++;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
			  *value, access_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}
예제 #14
0
void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
{
	u32 length;
	u32 index;

	ACPI_FUNCTION_NAME(ex_dump_operand)

	    if (!
		((ACPI_LV_EXEC & acpi_dbg_level)
		 && (_COMPONENT & acpi_dbg_layer))) {
		return;
	}

	if (!obj_desc) {

		/* This could be a null element of a package */

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n"));
		return;
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p Namespace Node: ",
				  obj_desc));
		ACPI_DUMP_ENTRY(obj_desc, ACPI_LV_EXEC);
		return;
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "%p is not a node or operand object: [%s]\n",
				  obj_desc,
				  acpi_ut_get_descriptor_name(obj_desc)));
		ACPI_DUMP_BUFFER(obj_desc, sizeof(union acpi_operand_object));
		return;
	}

	/* obj_desc is a valid object */

	if (depth > 0) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%*s[%u] %p ",
				  depth, " ", depth, obj_desc));
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p ", obj_desc));
	}

	/* Decode object type */

	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
	case ACPI_TYPE_LOCAL_REFERENCE:

		switch (obj_desc->reference.opcode) {
		case AML_DEBUG_OP:

			acpi_os_printf("Reference: Debug\n");
			break;

		case AML_NAME_OP:

			ACPI_DUMP_PATHNAME(obj_desc->reference.object,
					   "Reference: Name: ", ACPI_LV_INFO,
					   _COMPONENT);
			ACPI_DUMP_ENTRY(obj_desc->reference.object,
					ACPI_LV_INFO);
			break;

		case AML_INDEX_OP:

			acpi_os_printf("Reference: Index %p\n",
				       obj_desc->reference.object);
			break;

		case AML_REF_OF_OP:

			acpi_os_printf("Reference: (RefOf) %p\n",
				       obj_desc->reference.object);
			break;

		case AML_ARG_OP:

			acpi_os_printf("Reference: Arg%d",
				       obj_desc->reference.offset);

			if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {

				/* Value is an Integer */

				acpi_os_printf(" value is [%8.8X%8.8x]",
					       ACPI_FORMAT_UINT64(obj_desc->
								  integer.
								  value));
			}

			acpi_os_printf("\n");
			break;

		case AML_LOCAL_OP:

			acpi_os_printf("Reference: Local%d",
				       obj_desc->reference.offset);

			if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {

				/* Value is an Integer */

				acpi_os_printf(" value is [%8.8X%8.8x]",
					       ACPI_FORMAT_UINT64(obj_desc->
								  integer.
								  value));
			}

			acpi_os_printf("\n");
			break;

		case AML_INT_NAMEPATH_OP:

			acpi_os_printf("Reference.Node->Name %X\n",
				       obj_desc->reference.node->name.integer);
			break;

		default:

			/* Unknown opcode */

			acpi_os_printf("Unknown Reference opcode=%X\n",
				       obj_desc->reference.opcode);
			break;

		}
		break;

	case ACPI_TYPE_BUFFER:

		acpi_os_printf("Buffer len %X @ %p\n",
			       obj_desc->buffer.length,
			       obj_desc->buffer.pointer);

		length = obj_desc->buffer.length;
		if (length > 64) {
			length = 64;
		}

		/* Debug only -- dump the buffer contents */

		if (obj_desc->buffer.pointer) {
			acpi_os_printf("Buffer Contents: ");

			for (index = 0; index < length; index++) {
				acpi_os_printf(" %02x",
					       obj_desc->buffer.pointer[index]);
			}
			acpi_os_printf("\n");
		}
		break;

	case ACPI_TYPE_INTEGER:

		acpi_os_printf("Integer %8.8X%8.8X\n",
			       ACPI_FORMAT_UINT64(obj_desc->integer.value));
		break;

	case ACPI_TYPE_PACKAGE:

		acpi_os_printf("Package [Len %X] ElementArray %p\n",
			       obj_desc->package.count,
			       obj_desc->package.elements);

		/*
		 * If elements exist, package element pointer is valid,
		 * and debug_level exceeds 1, dump package's elements.
		 */
		if (obj_desc->package.count &&
		    obj_desc->package.elements && acpi_dbg_level > 1) {
			for (index = 0; index < obj_desc->package.count;
			     index++) {
				acpi_ex_dump_operand(obj_desc->package.
						     elements[index],
						     depth + 1);
			}
		}
		break;

	case ACPI_TYPE_REGION:

		acpi_os_printf("Region %s (%X)",
			       acpi_ut_get_region_name(obj_desc->region.
						       space_id),
			       obj_desc->region.space_id);

		/*
		 * If the address and length have not been evaluated,
		 * don't print them.
		 */
		if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) {
			acpi_os_printf("\n");
		} else {
			acpi_os_printf(" base %8.8X%8.8X Length %X\n",
				       ACPI_FORMAT_UINT64(obj_desc->region.
							  address),
				       obj_desc->region.length);
		}
		break;

	case ACPI_TYPE_STRING:

		acpi_os_printf("String length %X @ %p ",
			       obj_desc->string.length,
			       obj_desc->string.pointer);

		acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
		acpi_os_printf("\n");
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		acpi_os_printf("BankField\n");
		break;

	case ACPI_TYPE_LOCAL_REGION_FIELD:

		acpi_os_printf
		    ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
		     obj_desc->field.bit_length,
		     obj_desc->field.access_byte_width,
		     obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
		     obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
		     obj_desc->field.base_byte_offset,
		     obj_desc->field.start_field_bit_offset);

		acpi_ex_dump_operand(obj_desc->field.region_obj, depth + 1);
		break;

	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		acpi_os_printf("IndexField\n");
		break;

	case ACPI_TYPE_BUFFER_FIELD:

		acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n",
			       obj_desc->buffer_field.bit_length,
			       obj_desc->buffer_field.base_byte_offset,
			       obj_desc->buffer_field.start_field_bit_offset);

		if (!obj_desc->buffer_field.buffer_obj) {
			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n"));
		} else
		    if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj)
			!= ACPI_TYPE_BUFFER) {
			acpi_os_printf("*not a Buffer*\n");
		} else {
			acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj,
					     depth + 1);
		}
		break;

	case ACPI_TYPE_EVENT:

		acpi_os_printf("Event\n");
		break;

	case ACPI_TYPE_METHOD:

		acpi_os_printf("Method(%X) @ %p:%X\n",
			       obj_desc->method.param_count,
			       obj_desc->method.aml_start,
			       obj_desc->method.aml_length);
		break;

	case ACPI_TYPE_MUTEX:

		acpi_os_printf("Mutex\n");
		break;

	case ACPI_TYPE_DEVICE:

		acpi_os_printf("Device\n");
		break;

	case ACPI_TYPE_POWER:

		acpi_os_printf("Power\n");
		break;

	case ACPI_TYPE_PROCESSOR:

		acpi_os_printf("Processor\n");
		break;

	case ACPI_TYPE_THERMAL:

		acpi_os_printf("Thermal\n");
		break;

	default:
		/* Unknown Type */

		acpi_os_printf("Unknown Type %X\n",
			       ACPI_GET_OBJECT_TYPE(obj_desc));
		break;
	}

	return;
}
예제 #15
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_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);
}
예제 #16
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;
	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.  This is where the default handlers
	 * get placed.
	 */
	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.
		 * Make sure the handler is not already installed.
		 */
		handler_obj = obj_desc->device.handler;

		/* Walk the handler list for this device */

		while (handler_obj) {

			/* Same space_id indicates a handler already installed */

			if (handler_obj->address_space.space_id == space_id) {
				if (handler_obj->address_space.handler ==
				    handler) {
					/*
					 * It is (relatively) OK to attempt to install the SAME
					 * handler twice. This can easily happen
					 * with 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;
			}

			/* Walk the linked list of handlers */

			handler_obj = handler_obj->address_space.next;
		}
	} 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->device.handler;

	/*
	 * The Device object is the first reference on the handler_obj.
	 * Each region that uses the handler adds a reference.
	 */
	obj_desc->device.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, handler_obj,
					NULL);

      unlock_and_exit:
	return_ACPI_STATUS(status);
}
예제 #17
0
void
acpi_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 = &region_obj2->extra.region_context;

	/* Get the address handler from the region object */

	handler_obj = region_obj->region.address_space;
	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.address_space = 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;
}
예제 #18
0
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
			       u32 function,
			       acpi_physical_address address,
			       u32 bit_width, acpi_integer * value)
{
	acpi_status status;
	acpi_status status2;
	acpi_adr_space_handler handler;
	acpi_adr_space_setup region_setup;
	union acpi_operand_object *handler_desc;
	union acpi_operand_object *region_obj2;
	void *region_context = NULL;

	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);

	region_obj2 = acpi_ns_get_secondary_object(region_obj);
	if (!region_obj2) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/* Ensure that there is a handler associated with this region */

	handler_desc = region_obj->region.handler;
	if (!handler_desc) {
		ACPI_ERROR((AE_INFO,
			    "No handler for Region [%4.4s] (%p) [%s]",
			    acpi_ut_get_node_name(region_obj->region.node),
			    region_obj,
			    acpi_ut_get_region_name(region_obj->region.
						    space_id)));

		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/*
	 * It may be the case that the region has never been initialized
	 * Some types of regions require special init code
	 */
	if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
		/*
		 * This region has not been initialized yet, do it
		 */
		region_setup = handler_desc->address_space.setup;
		if (!region_setup) {

			/* No initialization routine, exit with error */

			ACPI_ERROR((AE_INFO,
				    "No init routine for region(%p) [%s]",
				    region_obj,
				    acpi_ut_get_region_name(region_obj->region.
							    space_id)));
			return_ACPI_STATUS(AE_NOT_EXIST);
		}

		/*
		 * We must exit the interpreter because the region
		 * setup will potentially execute control methods
		 * (e.g., _REG method for this region)
		 */
		acpi_ex_exit_interpreter();

		status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
				      handler_desc->address_space.context,
				      &region_context);

		/* Re-enter the interpreter */

		status2 = acpi_ex_enter_interpreter();
		if (ACPI_FAILURE(status2)) {
			return_ACPI_STATUS(status2);
		}

		/* Check for failure of the Region Setup */

		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status,
					"During region initialization: [%s]",
					acpi_ut_get_region_name(region_obj->
								region.
								space_id)));
			return_ACPI_STATUS(status);
		}

		/*
		 * Region initialization may have been completed by region_setup
		 */
		if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
			region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;

			if (region_obj2->extra.region_context) {

				/* The handler for this region was already installed */

				ACPI_FREE(region_context);
			} else {
				/*
				 * Save the returned context for use in all accesses to
				 * this particular region
				 */
				region_obj2->extra.region_context =
				    region_context;
			}
		}
	}

	/* We have everything we need, we can invoke the address space handler */

	handler = handler_desc->address_space.handler;

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
			  &region_obj->region.handler->address_space, handler,
			  ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(region_obj->region.
						  space_id)));

	if (!(handler_desc->address_space.handler_flags &
	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * For handlers other than the default (supplied) handlers, we must
		 * exit the interpreter because the handler *might* block -- we don't
		 * know what it will do, so we can't hold the lock on the intepreter.
		 */
		acpi_ex_exit_interpreter();
	}

	/* Call the handler */

	status = handler(function, address, bit_width, value,
			 handler_desc->address_space.context,
			 region_obj2->extra.region_context);

	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
				acpi_ut_get_region_name(region_obj->region.
							space_id)));
	}

	if (!(handler_desc->address_space.handler_flags &
	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * We just returned from a non-default handler, we must re-enter the
		 * interpreter
		 */
		status2 = acpi_ex_enter_interpreter();
		if (ACPI_FAILURE(status2)) {
			return_ACPI_STATUS(status2);
		}
	}

	return_ACPI_STATUS(status);
}
예제 #19
0
void
acpi_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 *start_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 = &region_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;
    start_desc = obj_desc;
    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,
                                           ACPI_REG_DISCONNECT);
            if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
                                "from region _REG, [%s]",
                                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;
                }
            }

            /*
             * If the region has been activated, call the setup handler with
             * the deactivate notification
             */
            if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
                region_setup = handler_obj->address_space.setup;
                status =
                    region_setup(region_obj,
                                 ACPI_REGION_DEACTIVATE,
                                 handler_obj->address_space.
                                 context, region_context);

                /*
                 * region_context should have been released by the deactivate
                 * operation. We don't need access to it anymore here.
                 */
                if (region_context) {
                    *region_context = NULL;
                }

                /* Init routine may fail, Just ignore errors */

                if (ACPI_FAILURE(status)) {
                    ACPI_EXCEPTION((AE_INFO, status,
                                    "from region handler - deactivate, [%s]",
                                    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 must 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;

        /* Prevent infinite loop if list is corrupted */

        if (obj_desc == start_desc) {
            ACPI_ERROR((AE_INFO,
                        "Circular handler list in region object %p",
                        region_obj));
            return_VOID;
        }
    }

    /* 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;
}
예제 #20
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);
}
예제 #21
0
파일: hwregs.c 프로젝트: AngleFork/linux
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
	u64 address;
	u8 access_width;
	u32 bit_width;
	u8 bit_offset;
	u64 value64;
	u32 new_value32, old_value32;
	u8 index;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_write);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 32, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/* Convert access_width into number of bits based */

	access_width = acpi_hw_get_access_bit_width(reg, 32);
	bit_width = reg->bit_offset + reg->bit_width;
	bit_offset = reg->bit_offset;

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	index = 0;
	while (bit_width) {
		/*
		 * Use offset style bit reads because "Index * AccessWidth" is
		 * ensured to be less than 32-bits by acpi_hw_validate_register().
		 */
		new_value32 = ACPI_GET_BITS(&value, index * access_width,
					    ACPI_MASK_BITS_ABOVE_32
					    (access_width));

		if (bit_offset >= access_width) {
			bit_offset -= access_width;
		} else {
			/*
			 * Use offset style bit masks because access_width is ensured
			 * to be less than 32-bits by acpi_hw_validate_register() and
			 * bit_offset/bit_width is less than access_width here.
			 */
			if (bit_offset) {
				new_value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
			}
			if (bit_width < access_width) {
				new_value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
			}

			if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
				if (bit_offset || bit_width < access_width) {
					/*
					 * Read old values in order not to modify the bits that
					 * are beyond the register bit_width/bit_offset setting.
					 */
					status =
					    acpi_os_read_memory((acpi_physical_address)
								address +
								index *
								ACPI_DIV_8
								(access_width),
								&value64,
								access_width);
					old_value32 = (u32)value64;

					/*
					 * Use offset style bit masks because access_width is
					 * ensured to be less than 32-bits by
					 * acpi_hw_validate_register() and bit_offset/bit_width is
					 * less than access_width here.
					 */
					if (bit_offset) {
						old_value32 &=
						    ACPI_MASK_BITS_ABOVE
						    (bit_offset);
						bit_offset = 0;
					}
					if (bit_width < access_width) {
						old_value32 &=
						    ACPI_MASK_BITS_BELOW
						    (bit_width);
					}

					new_value32 |= old_value32;
				}

				value64 = (u64)new_value32;
				status =
				    acpi_os_write_memory((acpi_physical_address)
							 address +
							 index *
							 ACPI_DIV_8
							 (access_width),
							 value64, access_width);
			} else {	/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

				if (bit_offset || bit_width < access_width) {
					/*
					 * Read old values in order not to modify the bits that
					 * are beyond the register bit_width/bit_offset setting.
					 */
					status =
					    acpi_hw_read_port((acpi_io_address)
							      address +
							      index *
							      ACPI_DIV_8
							      (access_width),
							      &old_value32,
							      access_width);

					/*
					 * Use offset style bit masks because access_width is
					 * ensured to be less than 32-bits by
					 * acpi_hw_validate_register() and bit_offset/bit_width is
					 * less than access_width here.
					 */
					if (bit_offset) {
						old_value32 &=
						    ACPI_MASK_BITS_ABOVE
						    (bit_offset);
						bit_offset = 0;
					}
					if (bit_width < access_width) {
						old_value32 &=
						    ACPI_MASK_BITS_BELOW
						    (bit_width);
					}

					new_value32 |= old_value32;
				}

				status = acpi_hw_write_port((acpi_io_address)
							    address +
							    index *
							    ACPI_DIV_8
							    (access_width),
							    new_value32,
							    access_width);
			}
		}

		/*
		 * Index * access_width is ensured to be less than 32-bits by
		 * acpi_hw_validate_register().
		 */
		bit_width -=
		    bit_width > access_width ? access_width : bit_width;
		index++;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
			  value, access_width, ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}
예제 #22
0
acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
	struct acpi_namespace_node *this_node;
	union acpi_operand_object *obj_desc = NULL;
	acpi_object_type obj_type;
	acpi_object_type type;
	u32 bytes_to_dump;
	u32 dbg_level;
	u32 i;

	ACPI_FUNCTION_NAME(ns_dump_one_object);

	

	if (!(acpi_dbg_level & info->debug_level)) {
		return (AE_OK);
	}

	if (!obj_handle) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
		return (AE_OK);
	}

	this_node = acpi_ns_validate_handle(obj_handle);
	if (!this_node) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n",
				  obj_handle));
		return (AE_OK);
	}

	type = this_node->type;

	

	if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
	    (info->owner_id != this_node->owner_id)) {
		return (AE_OK);
	}

	if (!(info->display_type & ACPI_DISPLAY_SHORT)) {

		

		acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");

		

		if (type > ACPI_TYPE_LOCAL_MAX) {
			ACPI_WARNING((AE_INFO,
				      "Invalid ACPI Object Type 0x%08X", type));
		}

		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
			this_node->name.integer =
			    acpi_ut_repair_name(this_node->name.ascii);

			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
				      this_node->name.integer));
		}

		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
	}

	

	acpi_os_printf(" %-12s %p %2.2X ",
		       acpi_ut_get_type_name(type), this_node,
		       this_node->owner_id);

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	

	if (this_node->flags & ANOBJ_TEMPORARY) {
		acpi_os_printf("(T) ");
	}

	switch (info->display_type & ACPI_DISPLAY_MASK) {
	case ACPI_DISPLAY_SUMMARY:

		if (!obj_desc) {

			

			switch (type) {
			case ACPI_TYPE_INTEGER:
			case ACPI_TYPE_PACKAGE:
			case ACPI_TYPE_BUFFER:
			case ACPI_TYPE_STRING:
			case ACPI_TYPE_METHOD:
				acpi_os_printf("<No attached object>");
				break;

			default:
				break;
			}

			acpi_os_printf("\n");
			return (AE_OK);
		}

		switch (type) {
		case ACPI_TYPE_PROCESSOR:

			acpi_os_printf("ID %X Len %.4X Addr %p\n",
				       obj_desc->processor.proc_id,
				       obj_desc->processor.length,
				       ACPI_CAST_PTR(void,
						     obj_desc->processor.
						     address));
			break;

		case ACPI_TYPE_DEVICE:

			acpi_os_printf("Notify Object: %p\n", obj_desc);
			break;

		case ACPI_TYPE_METHOD:

			acpi_os_printf("Args %X Len %.4X Aml %p\n",
				       (u32) obj_desc->method.param_count,
				       obj_desc->method.aml_length,
				       obj_desc->method.aml_start);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf("= %8.8X%8.8X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_PACKAGE:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Elements %.2X\n",
					       obj_desc->package.count);
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_BUFFER:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Len %.2X",
					       obj_desc->buffer.length);

				

				if (obj_desc->buffer.length > 0) {
					acpi_os_printf(" =");
					for (i = 0;
					     (i < obj_desc->buffer.length
					      && i < 12); i++) {
						acpi_os_printf(" %.2hX",
							       obj_desc->buffer.
							       pointer[i]);
					}
				}
				acpi_os_printf("\n");
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf("Len %.2X ", obj_desc->string.length);
			acpi_ut_print_string(obj_desc->string.pointer, 32);
			acpi_os_printf("\n");
			break;

		case ACPI_TYPE_REGION:

			acpi_os_printf("[%s]",
				       acpi_ut_get_region_name(obj_desc->region.
							       space_id));
			if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
					       ACPI_FORMAT_NATIVE_UINT
					       (obj_desc->region.address),
					       obj_desc->region.length);
			} else {
				acpi_os_printf
				    (" [Address/Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_LOCAL_REFERENCE:

			acpi_os_printf("[%s]\n",
				       acpi_ut_get_reference_name(obj_desc));
			break;

		case ACPI_TYPE_BUFFER_FIELD:

			if (obj_desc->buffer_field.buffer_obj &&
			    obj_desc->buffer_field.buffer_obj->buffer.node) {
				acpi_os_printf("Buf [%4.4s]",
					       acpi_ut_get_node_name(obj_desc->
								     buffer_field.
								     buffer_obj->
								     buffer.
								     node));
			}
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:

			acpi_os_printf("Rgn [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node));
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:

			acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node),
				       acpi_ut_get_node_name(obj_desc->
							     bank_field.
							     bank_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     index_obj->
							     common_field.node),
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     data_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_ALIAS:
		case ACPI_TYPE_LOCAL_METHOD_ALIAS:

			acpi_os_printf("Target %4.4s (%p)\n",
				       acpi_ut_get_node_name(obj_desc),
				       obj_desc);
			break;

		default:

			acpi_os_printf("Object %p\n", obj_desc);
			break;
		}

		

		switch (type) {
		case ACPI_TYPE_BUFFER_FIELD:
		case ACPI_TYPE_LOCAL_REGION_FIELD:
		case ACPI_TYPE_LOCAL_BANK_FIELD:
		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n",
				       (obj_desc->common_field.
					base_byte_offset * 8)
				       +
				       obj_desc->common_field.
				       start_field_bit_offset,
				       obj_desc->common_field.bit_length,
				       obj_desc->common_field.
				       access_byte_width);
			break;

		default:
			break;
		}
		break;

	case ACPI_DISPLAY_OBJECTS:

		acpi_os_printf("O:%p", obj_desc);
		if (!obj_desc) {

			

			acpi_os_printf("\n");
			return (AE_OK);
		}

		acpi_os_printf("(R%u)", obj_desc->common.reference_count);

		switch (type) {
		case ACPI_TYPE_METHOD:

			

			acpi_os_printf(" M:%p-%X\n", obj_desc->method.aml_start,
				       obj_desc->method.aml_length);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf(" I:%8.8X8.8%X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf(" S:%p-%X\n", obj_desc->string.pointer,
				       obj_desc->string.length);
			break;

		case ACPI_TYPE_BUFFER:

			acpi_os_printf(" B:%p-%X\n", obj_desc->buffer.pointer,
				       obj_desc->buffer.length);
			break;

		default:

			acpi_os_printf("\n");
			break;
		}
		break;

	default:
		acpi_os_printf("\n");
		break;
	}

	

	if (!(acpi_dbg_level & ACPI_LV_VALUES)) {
		return (AE_OK);
	}

	

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	

	while (obj_desc) {
		obj_type = ACPI_TYPE_INVALID;
		acpi_os_printf("Attached Object %p: ", obj_desc);

		

		switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
		case ACPI_DESC_TYPE_NAMED:

			acpi_os_printf("(Ptr to Node)\n");
			bytes_to_dump = sizeof(struct acpi_namespace_node);
			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			break;

		case ACPI_DESC_TYPE_OPERAND:

			obj_type = obj_desc->common.type;

			if (obj_type > ACPI_TYPE_LOCAL_MAX) {
				acpi_os_printf
				    ("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
				     obj_type);
				bytes_to_dump = 32;
			} else {
				acpi_os_printf
				    ("(Pointer to ACPI Object type %.2X [%s])\n",
				     obj_type, acpi_ut_get_type_name(obj_type));
				bytes_to_dump =
				    sizeof(union acpi_operand_object);
			}

			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			break;

		default:

			break;
		}

		

		if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
		    ACPI_DESC_TYPE_OPERAND) {
			goto cleanup;
		}

		

		switch (obj_type) {
		case ACPI_TYPE_BUFFER:
		case ACPI_TYPE_STRING:
			bytes_to_dump = obj_desc->string.length;
			obj_desc = (void *)obj_desc->string.pointer;
			acpi_os_printf("(Buffer/String pointer %p length %X)\n",
				       obj_desc, bytes_to_dump);
			ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
			goto cleanup;

		case ACPI_TYPE_BUFFER_FIELD:
			obj_desc =
			    (union acpi_operand_object *)obj_desc->buffer_field.
			    buffer_obj;
			break;

		case ACPI_TYPE_PACKAGE:
			obj_desc = (void *)obj_desc->package.elements;
			break;

		case ACPI_TYPE_METHOD:
			obj_desc = (void *)obj_desc->method.aml_start;
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:
			obj_desc = (void *)obj_desc->field.region_obj;
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:
			obj_desc = (void *)obj_desc->bank_field.region_obj;
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:
			obj_desc = (void *)obj_desc->index_field.index_obj;
			break;

		default:
			goto cleanup;
		}

		obj_type = ACPI_TYPE_INVALID;	
	}

      cleanup:
	acpi_os_printf("\n");
	return (AE_OK);
}
예제 #23
0
파일: evxfregn.c 프로젝트: 03199618/linux
/*******************************************************************************
 *
 * FUNCTION:    acpi_remove_address_space_handler
 *
 * PARAMETERS:  device          - Handle for the device
 *              space_id        - The address space ID
 *              handler         - Address of the handler
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Remove a previously installed handler.
 *
 ******************************************************************************/
acpi_status
acpi_remove_address_space_handler(acpi_handle device,
				  acpi_adr_space_type space_id,
				  acpi_adr_space_handler handler)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;
	union acpi_operand_object *region_obj;
	union acpi_operand_object **last_obj_ptr;
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);

	/* Parameter validation */

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

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

	/* Convert and validate the device handle */

	node = acpi_ns_validate_handle(device);
	if (!node ||
	    ((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;
	}

	/* Make sure the internal object exists */

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		status = AE_NOT_EXIST;
		goto unlock_and_exit;
	}

	/* Find the address handler the user requested */

	handler_obj = obj_desc->device.handler;
	last_obj_ptr = &obj_desc->device.handler;
	while (handler_obj) {

		/* We have a handler, see if user requested this one */

		if (handler_obj->address_space.space_id == space_id) {

			/* Handler must be the same as the installed handler */

			if (handler_obj->address_space.handler != handler) {
				status = AE_BAD_PARAMETER;
				goto unlock_and_exit;
			}

			/* Matched space_id, first dereference this in the Regions */

			ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
					  "Removing address handler %p(%p) for region %s "
					  "on Device %p(%p)\n",
					  handler_obj, handler,
					  acpi_ut_get_region_name(space_id),
					  node, obj_desc));

			region_obj = handler_obj->address_space.region_list;

			/* Walk the handler's region list */

			while (region_obj) {
				/*
				 * First disassociate the handler from the region.
				 *
				 * NOTE: this doesn't mean that the region goes away
				 * The region is just inaccessible as indicated to
				 * the _REG method
				 */
				acpi_ev_detach_region(region_obj, TRUE);

				/*
				 * Walk the list: Just grab the head because the
				 * detach_region removed the previous head.
				 */
				region_obj =
				    handler_obj->address_space.region_list;

			}

			/* Remove this Handler object from the list */

			*last_obj_ptr = handler_obj->address_space.next;

			/* Now we can delete the handler object */

			acpi_ut_remove_reference(handler_obj);
			goto unlock_and_exit;
		}

		/* Walk the linked list of handlers */

		last_obj_ptr = &handler_obj->address_space.next;
		handler_obj = handler_obj->address_space.next;
	}

	/* The handler does not exist */

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
			  handler, acpi_ut_get_region_name(space_id), space_id,
			  node, obj_desc));

	status = AE_NOT_EXIST;

      unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}
예제 #24
0
파일: hwregs.c 프로젝트: Camedpuffer/linux
acpi_status acpi_hw_write(u64 value, struct acpi_generic_address *reg)
{
	u64 address;
	u8 access_width;
	u32 bit_width;
	u8 bit_offset;
	u64 value64;
	u8 index;
	acpi_status status;

	ACPI_FUNCTION_NAME(hw_write);

	/* Validate contents of the GAS register */

	status = acpi_hw_validate_register(reg, 64, &address);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/* Convert access_width into number of bits based */

	access_width = acpi_hw_get_access_bit_width(address, reg, 64);
	bit_width = reg->bit_offset + reg->bit_width;
	bit_offset = reg->bit_offset;

	/*
	 * Two address spaces supported: Memory or IO. PCI_Config is
	 * not supported here because the GAS structure is insufficient
	 */
	index = 0;
	while (bit_width) {
		/*
		 * Use offset style bit reads because "Index * AccessWidth" is
		 * ensured to be less than 64-bits by acpi_hw_validate_register().
		 */
		value64 = ACPI_GET_BITS(&value, index * access_width,
					ACPI_MASK_BITS_ABOVE_64(access_width));

		if (bit_offset >= access_width) {
			bit_offset -= access_width;
		} else {
			if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
				status =
				    acpi_os_write_memory((acpi_physical_address)
							 address +
							 index *
							 ACPI_DIV_8
							 (access_width),
							 value64, access_width);
			} else {	/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */

				status = acpi_hw_write_port((acpi_io_address)
							    address +
							    index *
							    ACPI_DIV_8
							    (access_width),
							    (u32)value64,
							    access_width);
			}
		}

		/*
		 * Index * access_width is ensured to be less than 32-bits by
		 * acpi_hw_validate_register().
		 */
		bit_width -=
		    bit_width > access_width ? access_width : bit_width;
		index++;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_IO,
			  "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
			  ACPI_FORMAT_UINT64(value), access_width,
			  ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(reg->space_id)));

	return (status);
}
예제 #25
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);
}
예제 #26
0
파일: dbtest.c 프로젝트: a2hojsjsjs/linux
static acpi_status
acpi_db_test_one_object(acpi_handle obj_handle,
			u32 nesting_level, void *context, void **return_value)
{
	struct acpi_namespace_node *node;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *region_obj;
	acpi_object_type local_type;
	u32 bit_length = 0;
	u32 byte_length = 0;
	acpi_status status = AE_OK;

	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	obj_desc = node->object;

	/*
	 * For the supported types, get the actual bit length or
	 * byte length. Map the type to one of Integer/String/Buffer.
	 */
	switch (node->type) {
	case ACPI_TYPE_INTEGER:

		/* Integer width is either 32 or 64 */

		local_type = ACPI_TYPE_INTEGER;
		bit_length = acpi_gbl_integer_bit_width;
		break;

	case ACPI_TYPE_STRING:

		local_type = ACPI_TYPE_STRING;
		byte_length = obj_desc->string.length;
		break;

	case ACPI_TYPE_BUFFER:

		local_type = ACPI_TYPE_BUFFER;
		byte_length = obj_desc->buffer.length;
		bit_length = byte_length * 8;
		break;

	case ACPI_TYPE_FIELD_UNIT:
	case ACPI_TYPE_BUFFER_FIELD:
	case ACPI_TYPE_LOCAL_REGION_FIELD:
	case ACPI_TYPE_LOCAL_INDEX_FIELD:
	case ACPI_TYPE_LOCAL_BANK_FIELD:

		local_type = ACPI_TYPE_INTEGER;
		if (obj_desc) {
			/*
			 * Returned object will be a Buffer if the field length
			 * is larger than the size of an Integer (32 or 64 bits
			 * depending on the DSDT version).
			 */
			bit_length = obj_desc->common_field.bit_length;
			byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length);
			if (bit_length > acpi_gbl_integer_bit_width) {
				local_type = ACPI_TYPE_BUFFER;
			}
		}
		break;

	default:

		/* Ignore all other types */

		return (AE_OK);
	}

	/* Emit the common prefix: Type:Name */

	acpi_os_printf("%14s: %4.4s",
		       acpi_ut_get_type_name(node->type), node->name.ascii);
	if (!obj_desc) {
		acpi_os_printf(" Ignoring, no attached object\n");
		return (AE_OK);
	}

	/*
	 * Check for unsupported region types. Note: acpi_exec simulates
	 * access to system_memory, system_IO, PCI_Config, and EC.
	 */
	switch (node->type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:

		region_obj = obj_desc->field.region_obj;
		switch (region_obj->region.space_id) {
		case ACPI_ADR_SPACE_SYSTEM_MEMORY:
		case ACPI_ADR_SPACE_SYSTEM_IO:
		case ACPI_ADR_SPACE_PCI_CONFIG:
		case ACPI_ADR_SPACE_EC:

			break;

		default:

			acpi_os_printf
			    ("    %s space is not supported [%4.4s]\n",
			     acpi_ut_get_region_name(region_obj->region.
						     space_id),
			     region_obj->region.node->name.ascii);
			return (AE_OK);
		}
		break;

	default:
		break;
	}

	/* At this point, we have resolved the object to one of the major types */

	switch (local_type) {
	case ACPI_TYPE_INTEGER:

		status = acpi_db_test_integer_type(node, bit_length);
		break;

	case ACPI_TYPE_STRING:

		status = acpi_db_test_string_type(node, byte_length);
		break;

	case ACPI_TYPE_BUFFER:

		status = acpi_db_test_buffer_type(node, bit_length);
		break;

	default:

		acpi_os_printf(" Ignoring, type not implemented (%2.2X)",
			       local_type);
		break;
	}

	switch (node->type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:

		region_obj = obj_desc->field.region_obj;
		acpi_os_printf(" (%s)",
			       acpi_ut_get_region_name(region_obj->region.
						       space_id));
		break;

	default:
		break;
	}

	acpi_os_printf("\n");
	return (status);
}
예제 #27
0
acpi_status
acpi_ns_dump_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
	struct acpi_namespace_node *this_node;
	union acpi_operand_object *obj_desc = NULL;
	acpi_object_type obj_type;
	acpi_object_type type;
	u32 bytes_to_dump;
	u32 dbg_level;
	u32 i;

	ACPI_FUNCTION_NAME(ns_dump_one_object);

	/* Is output enabled? */

	if (!(acpi_dbg_level & info->debug_level)) {
		return (AE_OK);
	}

	if (!obj_handle) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null object handle\n"));
		return (AE_OK);
	}

	this_node = acpi_ns_validate_handle(obj_handle);
	if (!this_node) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n",
				  obj_handle));
		return (AE_OK);
	}

	type = this_node->type;

	/* Check if the owner matches */

	if ((info->owner_id != ACPI_OWNER_ID_MAX) &&
	    (info->owner_id != this_node->owner_id)) {
		return (AE_OK);
	}

	if (!(info->display_type & ACPI_DISPLAY_SHORT)) {

		/* Indent the object according to the level */

		acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");

		/* Check the node type and name */

		if (type > ACPI_TYPE_LOCAL_MAX) {
			ACPI_WARNING((AE_INFO,
				      "Invalid ACPI Object Type 0x%08X", type));
		}

		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
			this_node->name.integer =
			    acpi_ut_repair_name(this_node->name.ascii);

			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
				      this_node->name.integer));
		}

		acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
	}

	/* Now we can print out the pertinent information */

	acpi_os_printf(" %-12s %p %2.2X ",
		       acpi_ut_get_type_name(type), this_node,
		       this_node->owner_id);

	dbg_level = acpi_dbg_level;
	acpi_dbg_level = 0;
	obj_desc = acpi_ns_get_attached_object(this_node);
	acpi_dbg_level = dbg_level;

	/* Temp nodes are those nodes created by a control method */

	if (this_node->flags & ANOBJ_TEMPORARY) {
		acpi_os_printf("(T) ");
	}

	switch (info->display_type & ACPI_DISPLAY_MASK) {
	case ACPI_DISPLAY_SUMMARY:

		if (!obj_desc) {

			/* No attached object, we are done */

			acpi_os_printf("\n");
			return (AE_OK);
		}

		switch (type) {
		case ACPI_TYPE_PROCESSOR:

			acpi_os_printf("ID %X Len %.4X Addr %p\n",
				       obj_desc->processor.proc_id,
				       obj_desc->processor.length,
				       ACPI_CAST_PTR(void,
						     obj_desc->processor.
						     address));
			break;

		case ACPI_TYPE_DEVICE:

			acpi_os_printf("Notify Object: %p\n", obj_desc);
			break;

		case ACPI_TYPE_METHOD:

			acpi_os_printf("Args %X Len %.4X Aml %p\n",
				       (u32) obj_desc->method.param_count,
				       obj_desc->method.aml_length,
				       obj_desc->method.aml_start);
			break;

		case ACPI_TYPE_INTEGER:

			acpi_os_printf("= %8.8X%8.8X\n",
				       ACPI_FORMAT_UINT64(obj_desc->integer.
							  value));
			break;

		case ACPI_TYPE_PACKAGE:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Elements %.2X\n",
					       obj_desc->package.count);
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_BUFFER:

			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf("Len %.2X",
					       obj_desc->buffer.length);

				/* Dump some of the buffer */

				if (obj_desc->buffer.length > 0) {
					acpi_os_printf(" =");
					for (i = 0;
					     (i < obj_desc->buffer.length
					      && i < 12); i++) {
						acpi_os_printf(" %.2hX",
							       obj_desc->buffer.
							       pointer[i]);
					}
				}
				acpi_os_printf("\n");
			} else {
				acpi_os_printf("[Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_STRING:

			acpi_os_printf("Len %.2X ", obj_desc->string.length);
			acpi_ut_print_string(obj_desc->string.pointer, 32);
			acpi_os_printf("\n");
			break;

		case ACPI_TYPE_REGION:

			acpi_os_printf("[%s]",
				       acpi_ut_get_region_name(obj_desc->region.
							       space_id));
			if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
				acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
					       ACPI_FORMAT_NATIVE_UINT
					       (obj_desc->region.address),
					       obj_desc->region.length);
			} else {
				acpi_os_printf
				    (" [Address/Length not yet evaluated]\n");
			}
			break;

		case ACPI_TYPE_LOCAL_REFERENCE:

			acpi_os_printf("[%s]\n",
				       acpi_ut_get_reference_name(obj_desc));
			break;

		case ACPI_TYPE_BUFFER_FIELD:

			if (obj_desc->buffer_field.buffer_obj &&
			    obj_desc->buffer_field.buffer_obj->buffer.node) {
				acpi_os_printf("Buf [%4.4s]",
					       acpi_ut_get_node_name(obj_desc->
								     buffer_field.
								     buffer_obj->
								     buffer.
								     node));
			}
			break;

		case ACPI_TYPE_LOCAL_REGION_FIELD:

			acpi_os_printf("Rgn [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node));
			break;

		case ACPI_TYPE_LOCAL_BANK_FIELD:

			acpi_os_printf("Rgn [%4.4s] Bnk [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     common_field.
							     region_obj->region.
							     node),
				       acpi_ut_get_node_name(obj_desc->
							     bank_field.
							     bank_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf("Idx [%4.4s] Dat [%4.4s]",
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     index_obj->
							     common_field.node),
				       acpi_ut_get_node_name(obj_desc->
							     index_field.
							     data_obj->
							     common_field.
							     node));
			break;

		case ACPI_TYPE_LOCAL_ALIAS:
		case ACPI_TYPE_LOCAL_METHOD_ALIAS:

			acpi_os_printf("Target %4.4s (%p)\n",
				       acpi_ut_get_node_name(obj_desc),
				       obj_desc);
			break;

		default:

			acpi_os_printf("Object %p\n", obj_desc);
			break;
		}

		/* Common field handling */

		switch (type) {
		case ACPI_TYPE_BUFFER_FIELD:
		case ACPI_TYPE_LOCAL_REGION_FIELD:
		case ACPI_TYPE_LOCAL_BANK_FIELD:
		case ACPI_TYPE_LOCAL_INDEX_FIELD:

			acpi_os_printf(" Off %.3X Len %.2X Acc %.2hd\n",
				       (obj_desc->common_field.
					base_byte_offset * 8)
				       +
				       obj_desc->common_field.
				       start_field_bit_offset,
				       obj_desc->common_field.bit_length,
				       obj_desc->common_field.
				       access_byte_width);
			break;

		default:
			break;
		}
		break;

	case ACPI_DISPLAY_OBJECTS:

		acpi_os_printf("O:%p", obj_desc);
		if (!obj_desc) {

			/* No attached object, we are done */

			acpi_os_printf("\n");
			return (AE_OK);
		}

<<<<<<< HEAD
		acpi_os_printf("(R%u)", obj_desc->common.reference_count);
=======