コード例 #1
0
ファイル: exfldio.c プロジェクト: 3sOx/asuswrt-merlin
static acpi_status
acpi_ex_setup_region(union acpi_operand_object *obj_desc,
		     u32 field_datum_byte_offset)
{
	acpi_status status = AE_OK;
	union acpi_operand_object *rgn_desc;

	ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);

	rgn_desc = obj_desc->common_field.region_obj;

	/* We must have a valid region */

	if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
		ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)",
			    ACPI_GET_OBJECT_TYPE(rgn_desc),
			    acpi_ut_get_object_type_name(rgn_desc)));

		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
	}

	/*
	 * If the Region Address and Length have not been previously evaluated,
	 * evaluate them now and save the results.
	 */
	if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
		status = acpi_ds_get_region_arguments(rgn_desc);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/* Exit if Address/Length have been disallowed by the host OS */

	if (rgn_desc->common.flags & AOPOBJ_INVALID) {
		return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
	}

	/*
	 * Exit now for SMBus address space, it has a non-linear address space
	 * and the request cannot be directly validated
	 */
	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {

		/* SMBus has a non-linear address space */

		return_ACPI_STATUS(AE_OK);
	}
#ifdef ACPI_UNDER_DEVELOPMENT
	/*
	 * If the Field access is any_acc, we can now compute the optimal
	 * access (because we know know the length of the parent region)
	 */
	if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}
#endif

	/*
	 * Validate the request.  The entire request from the byte offset for a
	 * length of one field datum (access width) must fit within the region.
	 * (Region length is specified in bytes)
	 */
	if (rgn_desc->region.length <
	    (obj_desc->common_field.base_byte_offset +
	     field_datum_byte_offset +
	     obj_desc->common_field.access_byte_width)) {
		if (acpi_gbl_enable_interpreter_slack) {
			/*
			 * Slack mode only:  We will go ahead and allow access to this
			 * field if it is within the region length rounded up to the next
			 * access width boundary.
			 */
			if (ACPI_ROUND_UP(rgn_desc->region.length,
					  obj_desc->common_field.
					  access_byte_width) >=
			    (obj_desc->common_field.base_byte_offset +
			     (acpi_native_uint) obj_desc->common_field.
			     access_byte_width + field_datum_byte_offset)) {
				return_ACPI_STATUS(AE_OK);
			}
		}

		if (rgn_desc->region.length <
		    obj_desc->common_field.access_byte_width) {
			/*
			 * This is the case where the access_type (acc_word, etc.) is wider
			 * than the region itself.  For example, a region of length one
			 * byte, and a field with Dword access specified.
			 */
			ACPI_ERROR((AE_INFO,
				    "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)",
				    acpi_ut_get_node_name(obj_desc->
							  common_field.node),
				    obj_desc->common_field.access_byte_width,
				    acpi_ut_get_node_name(rgn_desc->region.
							  node),
				    rgn_desc->region.length));
		}

		/*
		 * Offset rounded up to next multiple of field width
		 * exceeds region length, indicate an error
		 */
		ACPI_ERROR((AE_INFO,
			    "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)",
			    acpi_ut_get_node_name(obj_desc->common_field.node),
			    obj_desc->common_field.base_byte_offset,
			    field_datum_byte_offset,
			    obj_desc->common_field.access_byte_width,
			    acpi_ut_get_node_name(rgn_desc->region.node),
			    rgn_desc->region.length));

		return_ACPI_STATUS(AE_AML_REGION_LIMIT);
	}

	return_ACPI_STATUS(AE_OK);
}
コード例 #2
0
ファイル: evmisc.c プロジェクト: 12019/kernel_zte_u880
acpi_status
acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
			     u32 notify_value)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj = NULL;
	union acpi_generic_state *notify_info;
	acpi_status status = AE_OK;

	ACPI_FUNCTION_NAME(ev_queue_notify_request);

	/*
	 * For value 3 (Ejection Request), some device method may need to be run.
	 * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
	 *   to be run.
	 * For value 0x80 (Status Change) on the power button or sleep button,
	 *   initiate soft-off or sleep operation?
	 */
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n",
			  acpi_ut_get_node_name(node), node, notify_value,
			  acpi_ut_get_notify_name(notify_value)));

	/* Get the notify object attached to the NS Node */

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

		/* We have the notify object, Get the right handler */

		switch (node->type) {

			/* Notify allowed only on these types */

		case ACPI_TYPE_DEVICE:
		case ACPI_TYPE_THERMAL:
		case ACPI_TYPE_PROCESSOR:

			if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
				handler_obj =
				    obj_desc->common_notify.system_notify;
			} else {
				handler_obj =
				    obj_desc->common_notify.device_notify;
			}
			break;

		default:

			/* All other types are not supported */

			return (AE_TYPE);
		}
	}

	/*
	 * If there is any handler to run, schedule the dispatcher.
	 * Check for:
	 * 1) Global system notify handler
	 * 2) Global device notify handler
	 * 3) Per-device notify handler
	 */
	if ((acpi_gbl_system_notify.handler &&
	     (notify_value <= ACPI_MAX_SYS_NOTIFY)) ||
	    (acpi_gbl_device_notify.handler &&
	     (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) {
		notify_info = acpi_ut_create_generic_state();
		if (!notify_info) {
			return (AE_NO_MEMORY);
		}

		if (!handler_obj) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Executing system notify handler for Notify (%4.4s, %X) "
					  "node %p\n",
					  acpi_ut_get_node_name(node),
					  notify_value, node));
		}

		notify_info->common.descriptor_type =
		    ACPI_DESC_TYPE_STATE_NOTIFY;
		notify_info->notify.node = node;
		notify_info->notify.value = (u16) notify_value;
		notify_info->notify.handler_obj = handler_obj;

		status =
		    acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
				    notify_info);
		if (ACPI_FAILURE(status)) {
			acpi_ut_delete_generic_state(notify_info);
		}
	} else {
		/* There is no notify handler (per-device or system) for this device */

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "No notify handler for Notify (%4.4s, %X) node %p\n",
				  acpi_ut_get_node_name(node), notify_value,
				  node));
	}

	return (status);
}
コード例 #3
0
void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node,	/* Parent */
			  struct acpi_namespace_node *node,	/* New Child */
			  acpi_object_type type)
{
	acpi_owner_id owner_id = 0;
	struct acpi_namespace_node *child_node;

	ACPI_FUNCTION_TRACE(ns_install_node);

	if (walk_state) {
		/*
		 * Get the owner ID from the Walk state. The owner ID is used to
		 * track table deletion and deletion of objects created by methods.
		 */
		owner_id = walk_state->owner_id;

		if ((walk_state->method_desc) &&
		    (parent_node != walk_state->method_node)) {
			/*
			 * A method is creating a new node that is not a child of the
			 * method (it is non-local). Mark the executing method as having
			 * modified the namespace. This is used for cleanup when the
			 * method exits.
			 */
			walk_state->method_desc->method.info_flags |=
			    ACPI_METHOD_MODIFIED_NAMESPACE;
		}
	}

	/* Link the new entry into the parent and existing children */

	node->peer = NULL;
	node->parent = parent_node;
	child_node = parent_node->child;

	if (!child_node) {
		parent_node->child = node;
	} else {
		/* Add node to the end of the peer list */

		while (child_node->peer) {
			child_node = child_node->peer;
		}

		child_node->peer = node;
	}

	/* Init the new entry */

	node->owner_id = owner_id;
	node->type = (u8) type;

	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
			  "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
			  acpi_ut_get_node_name(node),
			  acpi_ut_get_type_name(node->type), node, owner_id,
			  acpi_ut_get_node_name(parent_node),
			  acpi_ut_get_type_name(parent_node->type),
			  parent_node));

	return_VOID;
}
コード例 #4
0
static acpi_status
acpi_ds_init_buffer_field(u16 aml_opcode,
			  union acpi_operand_object *obj_desc,
			  union acpi_operand_object *buffer_desc,
			  union acpi_operand_object *offset_desc,
			  union acpi_operand_object *length_desc,
			  union acpi_operand_object *result_desc)
{
	u32 offset;
	u32 bit_offset;
	u32 bit_count;
	u8 field_flags;
	acpi_status status;

	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);

	/* Host object must be a Buffer */

	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
		ACPI_ERROR((AE_INFO,
			    "Target of Create Field is not a Buffer object - %s",
			    acpi_ut_get_object_type_name(buffer_desc)));

		status = AE_AML_OPERAND_TYPE;
		goto cleanup;
	}

	/*
	 * The last parameter to all of these opcodes (result_desc) started
	 * out as a name_string, and should therefore now be a NS node
	 * after resolution in acpi_ex_resolve_operands().
	 */
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
		ACPI_ERROR((AE_INFO,
			    "(%s) destination not a NS Node [%s]",
			    acpi_ps_get_opcode_name(aml_opcode),
			    acpi_ut_get_descriptor_name(result_desc)));

		status = AE_AML_OPERAND_TYPE;
		goto cleanup;
	}

	offset = (u32) offset_desc->integer.value;

	/*
	 * Setup the Bit offsets and counts, according to the opcode
	 */
	switch (aml_opcode) {
	case AML_CREATE_FIELD_OP:

		/* Offset is in bits, count is in bits */

		field_flags = AML_FIELD_ACCESS_BYTE;
		bit_offset = offset;
		bit_count = (u32) length_desc->integer.value;

		/* Must have a valid (>0) bit count */

		if (bit_count == 0) {
			ACPI_ERROR((AE_INFO,
				    "Attempt to CreateField of length zero"));
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}
		break;

	case AML_CREATE_BIT_FIELD_OP:

		/* Offset is in bits, Field is one bit */

		bit_offset = offset;
		bit_count = 1;
		field_flags = AML_FIELD_ACCESS_BYTE;
		break;

	case AML_CREATE_BYTE_FIELD_OP:

		/* Offset is in bytes, field is one byte */

		bit_offset = 8 * offset;
		bit_count = 8;
		field_flags = AML_FIELD_ACCESS_BYTE;
		break;

	case AML_CREATE_WORD_FIELD_OP:

		/* Offset is in bytes, field is one word */

		bit_offset = 8 * offset;
		bit_count = 16;
		field_flags = AML_FIELD_ACCESS_WORD;
		break;

	case AML_CREATE_DWORD_FIELD_OP:

		/* Offset is in bytes, field is one dword */

		bit_offset = 8 * offset;
		bit_count = 32;
		field_flags = AML_FIELD_ACCESS_DWORD;
		break;

	case AML_CREATE_QWORD_FIELD_OP:

		/* Offset is in bytes, field is one qword */

		bit_offset = 8 * offset;
		bit_count = 64;
		field_flags = AML_FIELD_ACCESS_QWORD;
		break;

	default:

		ACPI_ERROR((AE_INFO,
			    "Unknown field creation opcode 0x%02X",
			    aml_opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	/* Entire field must fit within the current length of the buffer */

	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
		ACPI_ERROR((AE_INFO,
			    "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",
			    acpi_ut_get_node_name(result_desc),
			    bit_offset + bit_count,
			    acpi_ut_get_node_name(buffer_desc->buffer.node),
			    8 * (u32) buffer_desc->buffer.length));
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

	/*
	 * Initialize areas of the field object that are common to all fields
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
	 */
	status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
						  bit_offset, bit_count);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

	buffer_desc->common.reference_count = (u16)
	    (buffer_desc->common.reference_count +
	     obj_desc->common.reference_count);

      cleanup:

	/* Always delete the operands */

	acpi_ut_remove_reference(offset_desc);
	acpi_ut_remove_reference(buffer_desc);

	if (aml_opcode == AML_CREATE_FIELD_OP) {
		acpi_ut_remove_reference(length_desc);
	}

	/* On failure, delete the result descriptor */

	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
	} else {
		/* Now the address and length are valid for this buffer_field */

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

	return_ACPI_STATUS(status);
}
コード例 #5
0
ファイル: evmisc.c プロジェクト: kzlin129/tt-gpl
acpi_status
acpi_ev_queue_notify_request (
	struct acpi_namespace_node      *node,
	u32                             notify_value)
{
	union acpi_operand_object       *obj_desc;
	union acpi_operand_object       *handler_obj = NULL;
	union acpi_generic_state        *notify_info;
	acpi_status                     status = AE_OK;


	ACPI_FUNCTION_NAME ("ev_queue_notify_request");


	/*
	 * For value 3 (Ejection Request), some device method may need to be run.
	 * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
	 *   to be run.
	 * For value 0x80 (Status Change) on the power button or sleep button,
	 *   initiate soft-off or sleep operation?
	 */
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"Dispatching Notify(%X) on node %p\n", notify_value, node));

	if (notify_value <= 7) {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
				acpi_notify_value_names[notify_value]));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"Notify value: 0x%2.2X **Device Specific**\n",
			notify_value));
	}

	/* Get the notify object attached to the NS Node */

	obj_desc = acpi_ns_get_attached_object (node);
	if (obj_desc) {
		/* We have the notify object, Get the right handler */

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

			if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
				handler_obj = obj_desc->common_notify.system_notify;
			}
			else {
				handler_obj = obj_desc->common_notify.device_notify;
			}
			break;

		default:
			/* All other types are not supported */
			return (AE_TYPE);
		}
	}

	/* If there is any handler to run, schedule the dispatcher */

	if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) ||
		(acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) ||
		handler_obj) {
		notify_info = acpi_ut_create_generic_state ();
		if (!notify_info) {
			return (AE_NO_MEMORY);
		}

		notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
		notify_info->notify.node      = node;
		notify_info->notify.value     = (u16) notify_value;
		notify_info->notify.handler_obj = handler_obj;

		status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
				  acpi_ev_notify_dispatch, notify_info);
		if (ACPI_FAILURE (status)) {
			acpi_ut_delete_generic_state (notify_info);
		}
	}

	if (!handler_obj) {
		/*
		 * There is no per-device notify handler for this device.
		 * This may or may not be a problem.
		 */
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"No notify handler for Notify(%4.4s, %X) node %p\n",
			acpi_ut_get_node_name (node), notify_value, node));
	}

	return (status);
}
コード例 #6
0
ファイル: exfldio.c プロジェクト: Brainiarc7/ralink_sdk
acpi_status
acpi_ex_setup_region (
	union acpi_operand_object       *obj_desc,
	u32                             field_datum_byte_offset)
{
	acpi_status                     status = AE_OK;
	union acpi_operand_object       *rgn_desc;


	ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);


	rgn_desc = obj_desc->common_field.region_obj;

	/* We must have a valid region */

	if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
			ACPI_GET_OBJECT_TYPE (rgn_desc),
			acpi_ut_get_object_type_name (rgn_desc)));

		return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
	}

	/*
	 * If the Region Address and Length have not been previously evaluated,
	 * evaluate them now and save the results.
	 */
	if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
		status = acpi_ds_get_region_arguments (rgn_desc);
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}
	}

	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
		/* SMBus has a non-linear address space */

		return_ACPI_STATUS (AE_OK);
	}

#ifdef ACPI_UNDER_DEVELOPMENT
	/*
	 * If the Field access is any_acc, we can now compute the optimal
	 * access (because we know know the length of the parent region)
	 */
	if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
		if (ACPI_FAILURE (status)) {
			return_ACPI_STATUS (status);
		}
	}
#endif

	/*
	 * Validate the request.  The entire request from the byte offset for a
	 * length of one field datum (access width) must fit within the region.
	 * (Region length is specified in bytes)
	 */
	if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
			   + field_datum_byte_offset
			   + obj_desc->common_field.access_byte_width)) {
		if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
			/*
			 * This is the case where the access_type (acc_word, etc.) is wider
			 * than the region itself.  For example, a region of length one
			 * byte, and a field with Dword access specified.
			 */
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
				acpi_ut_get_node_name (obj_desc->common_field.node),
				obj_desc->common_field.access_byte_width,
				acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
		}

		/*
		 * Offset rounded up to next multiple of field width
		 * exceeds region length, indicate an error
		 */
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
			acpi_ut_get_node_name (obj_desc->common_field.node),
			obj_desc->common_field.base_byte_offset,
			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));

		if (!acpi_strict) {
			/*
			 * Allow access to the field if it is within the region size
			 * rounded up to a multiple of the access byte width.  This
			 * overcomes "off-by-one" programming errors in the AML often
			 * found in Toshiba laptops.  These errors were allowed by
			 * the Microsoft ASL compiler.
			 */
			u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length,
									obj_desc->common_field.access_byte_width);

			if (rounded_length < (obj_desc->common_field.base_byte_offset
						+ field_datum_byte_offset
						+ obj_desc->common_field.access_byte_width)) {
				return_ACPI_STATUS (AE_AML_REGION_LIMIT);
			} else {
				static int	warn_once = 1;
				if (warn_once) {
					// Could also associate a flag with each field, and
					// warn once for each field.
					ACPI_REPORT_WARNING((
						"The ACPI AML in your computer contains errors, "
						"please nag the manufacturer to correct it.\n"));
					ACPI_REPORT_WARNING((
						"Allowing relaxed access to fields; "
						"turn on CONFIG_ACPI_DEBUG for details.\n"));
					warn_once = 0;
				}
				return_ACPI_STATUS (AE_OK);
			}
		}
		else {
			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
		}
	}

	return_ACPI_STATUS (AE_OK);
}
コード例 #7
0
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
    union acpi_operand_object *obj_desc;
    union acpi_operand_object *second_desc = NULL;
    u32 type;
    acpi_status status;

    ACPI_FUNCTION_TRACE(ex_prep_field_value);



    if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
        if (!info->region_node) {
            ACPI_ERROR((AE_INFO, "Null RegionNode"));
            return_ACPI_STATUS(AE_AML_NO_OPERAND);
        }

        type = acpi_ns_get_type(info->region_node);
        if (type != ACPI_TYPE_REGION) {
            ACPI_ERROR((AE_INFO,
                        "Needed Region, found type %X (%s)",
                        type, acpi_ut_get_type_name(type)));

            return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
        }
    }



    obj_desc = acpi_ut_create_internal_object(info->field_type);
    if (!obj_desc) {
        return_ACPI_STATUS(AE_NO_MEMORY);
    }



    obj_desc->common_field.node = info->field_node;
    status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
             info->attribute,
             info->field_bit_position,
             info->field_bit_length);
    if (ACPI_FAILURE(status)) {
        acpi_ut_delete_object_desc(obj_desc);
        return_ACPI_STATUS(status);
    }



    switch (info->field_type) {
    case ACPI_TYPE_LOCAL_REGION_FIELD:

        obj_desc->field.region_obj =
            acpi_ns_get_attached_object(info->region_node);



        acpi_ut_add_reference(obj_desc->field.region_obj);

        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                          "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
                          obj_desc->field.start_field_bit_offset,
                          obj_desc->field.base_byte_offset,
                          obj_desc->field.access_byte_width,
                          obj_desc->field.region_obj));
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:

        obj_desc->bank_field.value = info->bank_value;
        obj_desc->bank_field.region_obj =
            acpi_ns_get_attached_object(info->region_node);
        obj_desc->bank_field.bank_obj =
            acpi_ns_get_attached_object(info->register_node);



        acpi_ut_add_reference(obj_desc->bank_field.region_obj);
        acpi_ut_add_reference(obj_desc->bank_field.bank_obj);

        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                          "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
                          obj_desc->bank_field.start_field_bit_offset,
                          obj_desc->bank_field.base_byte_offset,
                          obj_desc->field.access_byte_width,
                          obj_desc->bank_field.region_obj,
                          obj_desc->bank_field.bank_obj));


        second_desc = obj_desc->common.next_object;
        second_desc->extra.aml_start =
            ACPI_CAST_PTR(union acpi_parse_object,
                          info->data_register_node)->named.data;
        second_desc->extra.aml_length =
            ACPI_CAST_PTR(union acpi_parse_object,
                          info->data_register_node)->named.length;

        break;

    case ACPI_TYPE_LOCAL_INDEX_FIELD:



        obj_desc->index_field.index_obj =
            acpi_ns_get_attached_object(info->register_node);
        obj_desc->index_field.data_obj =
            acpi_ns_get_attached_object(info->data_register_node);

        if (!obj_desc->index_field.data_obj
                || !obj_desc->index_field.index_obj) {
            ACPI_ERROR((AE_INFO,
                        "Null Index Object during field prep"));
            acpi_ut_delete_object_desc(obj_desc);
            return_ACPI_STATUS(AE_AML_INTERNAL);
        }



        acpi_ut_add_reference(obj_desc->index_field.data_obj);
        acpi_ut_add_reference(obj_desc->index_field.index_obj);


        obj_desc->index_field.value =
            (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position),
                                  obj_desc->index_field.
                                  access_byte_width);

        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                          "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
                          obj_desc->index_field.start_field_bit_offset,
                          obj_desc->index_field.base_byte_offset,
                          obj_desc->index_field.value,
                          obj_desc->field.access_byte_width,
                          obj_desc->index_field.index_obj,
                          obj_desc->index_field.data_obj));
        break;

    default:

        break;
    }


    status = acpi_ns_attach_object(info->field_node, obj_desc,
                                   acpi_ns_get_type(info->field_node));

    ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                      "Set NamedObj %p [%4.4s], ObjDesc %p\n",
                      info->field_node,
                      acpi_ut_get_node_name(info->field_node), obj_desc));



    acpi_ut_remove_reference(obj_desc);
    return_ACPI_STATUS(status);
}
コード例 #8
0
ファイル: dsinit.c プロジェクト: Antonio-Zhou/Linux-2.6.11
acpi_status
acpi_ds_init_one_object (
	acpi_handle                     obj_handle,
	u32                             level,
	void                            *context,
	void                            **return_value)
{
	acpi_object_type                type;
	acpi_status                     status;
	struct acpi_init_walk_info      *info = (struct acpi_init_walk_info *) context;


	ACPI_FUNCTION_NAME ("ds_init_one_object");


	/*
	 * We are only interested in objects owned by the table that
	 * was just loaded
	 */
	if (((struct acpi_namespace_node *) obj_handle)->owner_id !=
			info->table_desc->table_id) {
		return (AE_OK);
	}

	info->object_count++;

	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type (obj_handle);

	switch (type) {
	case ACPI_TYPE_REGION:

		status = acpi_ds_initialize_region (obj_handle);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n",
				obj_handle, acpi_ut_get_node_name (obj_handle),
				acpi_format_exception (status)));
		}

		info->op_region_count++;
		break;


	case ACPI_TYPE_METHOD:

		info->method_count++;

		/* Print a dot for each method unless we are going to print the entire pathname */

		if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
		}

		/*
		 * Set the execution data width (32 or 64) based upon the
		 * revision number of the parent ACPI table.
		 * TBD: This is really for possible future support of integer width
		 * on a per-table basis. Currently, we just use a global for the width.
		 */
		if (info->table_desc->pointer->revision == 1) {
			((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
		}

		/*
		 * Always parse methods to detect errors, we will delete
		 * the parse tree below
		 */
		status = acpi_ds_parse_method (obj_handle);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n",
				obj_handle, acpi_ut_get_node_name (obj_handle),
				acpi_format_exception (status)));

			/* This parse failed, but we will continue parsing more methods */

			break;
		}

		/*
		 * Delete the parse tree.  We simply re-parse the method
		 * for every execution since there isn't much overhead
		 */
		acpi_ns_delete_namespace_subtree (obj_handle);
		acpi_ns_delete_namespace_by_owner (((struct acpi_namespace_node *) obj_handle)->object->method.owning_id);
		break;


	case ACPI_TYPE_DEVICE:

		info->device_count++;
		break;


	default:
		break;
	}

	/*
	 * We ignore errors from above, and always return OK, since
	 * we don't want to abort the walk on a single error.
	 */
	return (AE_OK);
}
コード例 #9
0
acpi_status
acpi_ns_lookup(union acpi_generic_state *scope_info,
	       char *pathname,
	       acpi_object_type type,
	       acpi_interpreter_mode interpreter_mode,
	       u32 flags,
	       struct acpi_walk_state *walk_state,
	       struct acpi_namespace_node **return_node)
{
	acpi_status status;
	char *path = pathname;
	struct acpi_namespace_node *prefix_node;
	struct acpi_namespace_node *current_node = NULL;
	struct acpi_namespace_node *this_node = NULL;
	u32 num_segments;
	u32 num_carats;
	acpi_name simple_name;
	acpi_object_type type_to_check_for;
	acpi_object_type this_search_type;
	u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
	u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
				    ACPI_NS_SEARCH_PARENT);

	ACPI_FUNCTION_TRACE("ns_lookup");

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

	acpi_gbl_ns_lookup_count++;
	*return_node = ACPI_ENTRY_NOT_FOUND;

	if (!acpi_gbl_root_node) {
		return_ACPI_STATUS(AE_NO_NAMESPACE);
	}

	/*
	 * Get the prefix scope.
	 * A null scope means use the root scope
	 */
	if ((!scope_info) || (!scope_info->scope.node)) {
		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
				  "Null scope prefix, using root node (%p)\n",
				  acpi_gbl_root_node));

		prefix_node = acpi_gbl_root_node;
	} else {
		prefix_node = scope_info->scope.node;
		if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) !=
		    ACPI_DESC_TYPE_NAMED) {
			ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]",
				    prefix_node,
				    acpi_ut_get_descriptor_name(prefix_node)));
			return_ACPI_STATUS(AE_AML_INTERNAL);
		}

		/*
		 * This node might not be a actual "scope" node (such as a
		 * Device/Method, etc.)  It could be a Package or other object node.
		 * Backup up the tree to find the containing scope node.
		 */
		while (!acpi_ns_opens_scope(prefix_node->type) &&
		       prefix_node->type != ACPI_TYPE_ANY) {
			prefix_node = acpi_ns_get_parent_node(prefix_node);
		}
	}

	/* Save type   TBD: may be no longer necessary */

	type_to_check_for = type;

	/*
	 * Begin examination of the actual pathname
	 */
	if (!pathname) {
		/* A Null name_path is allowed and refers to the root */

		num_segments = 0;
		this_node = acpi_gbl_root_node;
		path = "";

		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
				  "Null Pathname (Zero segments), Flags=%X\n",
				  flags));
	} else {
		/*
		 * Name pointer is valid (and must be in internal name format)
		 *
		 * Check for scope prefixes:
		 *
		 * As represented in the AML stream, a namepath consists of an
		 * optional scope prefix followed by a name segment part.
		 *
		 * If present, the scope prefix is either a Root Prefix (in
		 * which case the name is fully qualified), or one or more
		 * Parent Prefixes (in which case the name's scope is relative
		 * to the current scope).
		 */
		if (*path == (u8) AML_ROOT_PREFIX) {
			/* Pathname is fully qualified, start from the root */

			this_node = acpi_gbl_root_node;
			search_parent_flag = ACPI_NS_NO_UPSEARCH;

			/* Point to name segment part */

			path++;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Path is absolute from root [%p]\n",
					  this_node));
		} else {
			/* Pathname is relative to current scope, start there */

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Searching relative to prefix scope [%4.4s] (%p)\n",
					  acpi_ut_get_node_name(prefix_node),
					  prefix_node));

			/*
			 * Handle multiple Parent Prefixes (carat) by just getting
			 * the parent node for each prefix instance.
			 */
			this_node = prefix_node;
			num_carats = 0;
			while (*path == (u8) AML_PARENT_PREFIX) {
				/* Name is fully qualified, no search rules apply */

				search_parent_flag = ACPI_NS_NO_UPSEARCH;
				/*
				 * Point past this prefix to the name segment
				 * part or the next Parent Prefix
				 */
				path++;

				/* Backup to the parent node */

				num_carats++;
				this_node = acpi_ns_get_parent_node(this_node);
				if (!this_node) {
					/* Current scope has no parent scope */

					ACPI_ERROR((AE_INFO,
						    "ACPI path has too many parent prefixes (^) - reached beyond root node"));
					return_ACPI_STATUS(AE_NOT_FOUND);
				}
			}

			if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
				ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
						  "Search scope is [%4.4s], path has %d carat(s)\n",
						  acpi_ut_get_node_name
						  (this_node), num_carats));
			}
		}

		/*
		 * Determine the number of ACPI name segments in this pathname.
		 *
		 * The segment part consists of either:
		 *  - A Null name segment (0)
		 *  - A dual_name_prefix followed by two 4-byte name segments
		 *  - A multi_name_prefix followed by a byte indicating the
		 *      number of segments and the segments themselves.
		 *  - A single 4-byte name segment
		 *
		 * Examine the name prefix opcode, if any, to determine the number of
		 * segments.
		 */
		switch (*path) {
		case 0:
			/*
			 * Null name after a root or parent prefixes. We already
			 * have the correct target node and there are no name segments.
			 */
			num_segments = 0;
			type = this_node->type;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Prefix-only Pathname (Zero name segments), Flags=%X\n",
					  flags));
			break;

		case AML_DUAL_NAME_PREFIX:

			/* More than one name_seg, search rules do not apply */

			search_parent_flag = ACPI_NS_NO_UPSEARCH;

			/* Two segments, point to first name segment */

			num_segments = 2;
			path++;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Dual Pathname (2 segments, Flags=%X)\n",
					  flags));
			break;

		case AML_MULTI_NAME_PREFIX_OP:

			/* More than one name_seg, search rules do not apply */

			search_parent_flag = ACPI_NS_NO_UPSEARCH;

			/* Extract segment count, point to first name segment */

			path++;
			num_segments = (u32) (u8) * path;
			path++;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Multi Pathname (%d Segments, Flags=%X)\n",
					  num_segments, flags));
			break;

		default:
			/*
			 * Not a Null name, no Dual or Multi prefix, hence there is
			 * only one name segment and Pathname is already pointing to it.
			 */
			num_segments = 1;

			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Simple Pathname (1 segment, Flags=%X)\n",
					  flags));
			break;
		}

		ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path));
	}

	/*
	 * Search namespace for each segment of the name.  Loop through and
	 * verify (or add to the namespace) each name segment.
	 *
	 * The object type is significant only at the last name
	 * segment.  (We don't care about the types along the path, only
	 * the type of the final target object.)
	 */
	this_search_type = ACPI_TYPE_ANY;
	current_node = this_node;
	while (num_segments && current_node) {
		num_segments--;
		if (!num_segments) {
			/*
			 * This is the last segment, enable typechecking
			 */
			this_search_type = type;

			/*
			 * Only allow automatic parent search (search rules) if the caller
			 * requested it AND we have a single, non-fully-qualified name_seg
			 */
			if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
			    (flags & ACPI_NS_SEARCH_PARENT)) {
				local_flags |= ACPI_NS_SEARCH_PARENT;
			}

			/* Set error flag according to caller */

			if (flags & ACPI_NS_ERROR_IF_FOUND) {
				local_flags |= ACPI_NS_ERROR_IF_FOUND;
			}
		}

		/* Extract one ACPI name from the front of the pathname */

		ACPI_MOVE_32_TO_32(&simple_name, path);

		/* Try to find the single (4 character) ACPI name */

		status =
		    acpi_ns_search_and_enter(simple_name, walk_state,
					     current_node, interpreter_mode,
					     this_search_type, local_flags,
					     &this_node);
		if (ACPI_FAILURE(status)) {
			if (status == AE_NOT_FOUND) {
				/* Name not found in ACPI namespace */

				ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
						  "Name [%4.4s] not found in scope [%4.4s] %p\n",
						  (char *)&simple_name,
						  (char *)&current_node->name,
						  current_node));
			}

			*return_node = this_node;
			return_ACPI_STATUS(status);
		}

		/*
		 * Sanity typecheck of the target object:
		 *
		 * If 1) This is the last segment (num_segments == 0)
		 *    2) And we are looking for a specific type
		 *       (Not checking for TYPE_ANY)
		 *    3) Which is not an alias
		 *    4) Which is not a local type (TYPE_SCOPE)
		 *    5) And the type of target object is known (not TYPE_ANY)
		 *    6) And target object does not match what we are looking for
		 *
		 * Then we have a type mismatch.  Just warn and ignore it.
		 */
		if ((num_segments == 0) &&
		    (type_to_check_for != ACPI_TYPE_ANY) &&
		    (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
		    (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
		    (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
		    (this_node->type != ACPI_TYPE_ANY) &&
		    (this_node->type != type_to_check_for)) {
			/* Complain about a type mismatch */

			ACPI_WARNING((AE_INFO,
				      "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)",
				      ACPI_CAST_PTR(char, &simple_name),
				      acpi_ut_get_type_name(this_node->type),
				      acpi_ut_get_type_name
				      (type_to_check_for)));
		}

		/*
		 * If this is the last name segment and we are not looking for a
		 * specific type, but the type of found object is known, use that type
		 * to see if it opens a scope.
		 */
		if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
			type = this_node->type;
		}

		/* Point to next name segment and make this node current */

		path += ACPI_NAME_SIZE;
		current_node = this_node;
	}
コード例 #10
0
acpi_status
acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
			char *path,
			u32 expected_return_btypes,
			union acpi_operand_object **return_desc)
{
	struct acpi_evaluate_info *info;
	acpi_status status;
	u32 return_btype;

	ACPI_FUNCTION_TRACE(ut_evaluate_object);

	/* Allocate the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	info->prefix_node = prefix_node;
	info->pathname = path;

	/* Evaluate the object/method */

	status = acpi_ns_evaluate(info);
	if (ACPI_FAILURE(status)) {
		if (status == AE_NOT_FOUND) {
			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
					  "[%4.4s.%s] was not found\n",
					  acpi_ut_get_node_name(prefix_node),
					  path));
		} else {
			ACPI_ERROR_METHOD("Method execution failed",
					  prefix_node, path, status);
		}

		goto cleanup;
	}

	/* Did we get a return object? */

	if (!info->return_object) {
		if (expected_return_btypes) {
			ACPI_ERROR_METHOD("No object was returned from",
					  prefix_node, path, AE_NOT_EXIST);

			status = AE_NOT_EXIST;
		}

		goto cleanup;
	}

	/* Map the return object type to the bitmapped type */

	switch ((info->return_object)->common.type) {
	case ACPI_TYPE_INTEGER:
		return_btype = ACPI_BTYPE_INTEGER;
		break;

	case ACPI_TYPE_BUFFER:
		return_btype = ACPI_BTYPE_BUFFER;
		break;

	case ACPI_TYPE_STRING:
		return_btype = ACPI_BTYPE_STRING;
		break;

	case ACPI_TYPE_PACKAGE:
		return_btype = ACPI_BTYPE_PACKAGE;
		break;

	default:
		return_btype = 0;
		break;
	}

	if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) {
		/*
		 * We received a return object, but one was not expected. This can
		 * happen frequently if the "implicit return" feature is enabled.
		 * Just delete the return object and return AE_OK.
		 */
		acpi_ut_remove_reference(info->return_object);
		goto cleanup;
	}

	/* Is the return object one of the expected types? */

	if (!(expected_return_btypes & return_btype)) {
		ACPI_ERROR_METHOD("Return object type is incorrect",
				  prefix_node, path, AE_TYPE);

		ACPI_ERROR((AE_INFO,
			    "Type returned from %s was incorrect: %s, expected Btypes: 0x%X",
			    path,
			    acpi_ut_get_object_type_name(info->return_object),
			    expected_return_btypes));

		/* On error exit, we must delete the return object */

		acpi_ut_remove_reference(info->return_object);
		status = AE_TYPE;
		goto cleanup;
	}

	/* Object type is OK, return it */

	*return_desc = info->return_object;

      cleanup:
	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}