⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ammonad.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 2 页
字号:

/******************************************************************************
 *
 * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
 *              $Revision: 1.1 $
 *
 *****************************************************************************/

/*
 *  Copyright (C) 2000, 2001 R. Byron Moore
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include <acpi.h>


#define _COMPONENT          ACPI_EXECUTER
	 MODULE_NAME         ("ammonad")


/*******************************************************************************
 *
 * FUNCTION:    Acpi_aml_get_object_reference
 *
 * PARAMETERS:  Obj_desc        - Create a reference to this object
 *              Ret_desc        - Where to store the reference
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Obtain and return a "reference" to the target object
 *              Common code for the Ref_of_op and the Cond_ref_of_op.
 *
 ******************************************************************************/

static ACPI_STATUS
acpi_aml_get_object_reference (
	ACPI_OPERAND_OBJECT     *obj_desc,
	ACPI_OPERAND_OBJECT     **ret_desc,
	ACPI_WALK_STATE         *walk_state)
{
	ACPI_STATUS             status = AE_OK;


	if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
		if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) {
			*ret_desc = NULL;
			status = AE_TYPE;
			goto cleanup;
		}

		/*
		 * Not a Name -- an indirect name pointer would have
		 * been converted to a direct name pointer in Acpi_aml_resolve_operands
		 */
		switch (obj_desc->reference.opcode) {
		case AML_LOCAL_OP:
		case AML_ARG_OP:

			*ret_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode,
					  obj_desc->reference.offset, walk_state);
			break;

		default:

			*ret_desc = NULL;
			status = AE_AML_INTERNAL;
			goto cleanup;
		}

	}

	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
		/* Must be a named object;  Just return the Node */

		*ret_desc = obj_desc;
	}

	else {
		*ret_desc = NULL;
		status = AE_TYPE;
	}


cleanup:

	return (status);
}


/*******************************************************************************
 *
 * FUNCTION:    Acpi_aml_exec_monadic1
 *
 * PARAMETERS:  Opcode              - The opcode to be executed
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
 *              object stack
 *
 ******************************************************************************/

ACPI_STATUS
acpi_aml_exec_monadic1 (
	u16                     opcode,
	ACPI_WALK_STATE         *walk_state)
{
	ACPI_OPERAND_OBJECT     *obj_desc;
	ACPI_STATUS             status;


	/* Resolve all operands */

	status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
	/* Get all operands */

	status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}


	/* Examine the opcode */

	switch (opcode) {

	/*  Def_release :=  Release_op  Mutex_object */

	case AML_RELEASE_OP:

		status = acpi_aml_release_mutex (obj_desc, walk_state);
		break;


	/*  Def_reset   :=  Reset_op    Acpi_event_object */

	case AML_RESET_OP:

		status = acpi_aml_system_reset_event (obj_desc);
		break;


	/*  Def_signal  :=  Signal_op   Acpi_event_object */

	case AML_SIGNAL_OP:

		status = acpi_aml_system_signal_event (obj_desc);
		break;


	/*  Def_sleep   :=  Sleep_op    Msec_time   */

	case AML_SLEEP_OP:

		acpi_aml_system_do_suspend ((u32) obj_desc->integer.value);
		break;


	/*  Def_stall   :=  Stall_op    Usec_time   */

	case AML_STALL_OP:

		acpi_aml_system_do_stall ((u32) obj_desc->integer.value);
		break;


	/*  Unknown opcode  */

	default:

		REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n",
			opcode));
		status = AE_AML_BAD_OPCODE;
		break;

	} /* switch */


cleanup:

	/* Always delete the operand */

	acpi_cm_remove_reference (obj_desc);

	return (AE_OK);
}


/*******************************************************************************
 *
 * FUNCTION:    Acpi_aml_exec_monadic2_r
 *
 * PARAMETERS:  Opcode              - The opcode to be executed
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and
 *              result operand on operand stack
 *
 ******************************************************************************/

ACPI_STATUS
acpi_aml_exec_monadic2_r (
	u16                     opcode,
	ACPI_WALK_STATE         *walk_state,
	ACPI_OPERAND_OBJECT     **return_desc)
{
	ACPI_OPERAND_OBJECT     *obj_desc;
	ACPI_OPERAND_OBJECT     *res_desc;
	ACPI_OPERAND_OBJECT     *ret_desc = NULL;
	ACPI_OPERAND_OBJECT     *ret_desc2 = NULL;
	u32                     res_val;
	ACPI_STATUS             status;
	u32                     i;
	u32                     j;
	ACPI_INTEGER            digit;


	/* Resolve all operands */

	status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
	/* Get all operands */

	status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state);
	status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}


	/* Create a return object of type NUMBER for most opcodes */

	switch (opcode) {
	case AML_BIT_NOT_OP:
	case AML_FIND_SET_LEFT_BIT_OP:
	case AML_FIND_SET_RIGHT_BIT_OP:
	case AML_FROM_BCD_OP:
	case AML_TO_BCD_OP:
	case AML_COND_REF_OF_OP:

		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
		if (!ret_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		break;
	}


	switch (opcode) {
	/*  Def_not :=  Not_op  Operand Result  */

	case AML_BIT_NOT_OP:

		ret_desc->integer.value = ~obj_desc->integer.value;
		break;


	/*  Def_find_set_left_bit := Find_set_left_bit_op Operand Result */

	case AML_FIND_SET_LEFT_BIT_OP:

		ret_desc->integer.value = obj_desc->integer.value;

		/*
		 * Acpi specification describes Integer type as a little
		 * endian unsigned value, so this boundry condition is valid.
		 */
		for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
			ret_desc->integer.value >>= 1;
		}

		ret_desc->integer.value = res_val;
		break;


	/*  Def_find_set_right_bit := Find_set_right_bit_op Operand Result */

	case AML_FIND_SET_RIGHT_BIT_OP:

		ret_desc->integer.value = obj_desc->integer.value;

		/*
		 * Acpi specification describes Integer type as a little
		 * endian unsigned value, so this boundry condition is valid.
		 */
		for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
			ret_desc->integer.value <<= 1;
		}

		/* Since returns must be 1-based, subtract from 33 (65) */

		ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
		break;


	/*  Def_from_bDC := From_bCDOp  BCDValue    Result  */

	case AML_FROM_BCD_OP:

		/*
		 * The 64-bit ACPI integer can hold 16 4-bit BCD integers
		 */
		ret_desc->integer.value = 0;
		for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
			/* Get one BCD digit */

			digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF);

			/* Check the range of the digit */

			if (digit > 9) {
				status = AE_AML_NUMERIC_OVERFLOW;
				goto cleanup;
			}

			if (digit > 0) {
				/* Sum into the result with the appropriate power of 10 */

				for (j = 0; j < i; j++) {
					digit *= 10;
				}

				ret_desc->integer.value += digit;
			}
		}
		break;


	/*  Def_to_bDC  :=  To_bCDOp Operand Result */

	case AML_TO_BCD_OP:


		if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) {
			status = AE_AML_NUMERIC_OVERFLOW;
			goto cleanup;
		}

		ret_desc->integer.value = 0;
		for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
			/* Divide by nth factor of 10 */

			digit = obj_desc->integer.value;
			for (j = 0; j < i; j++) {
				digit /= 10;
			}

			/* Create the BCD digit */

			if (digit > 0) {
				ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4));
			}
		}
		break;


	/*  Def_cond_ref_of     :=  Cond_ref_of_op  Source_object   Result  */

	case AML_COND_REF_OF_OP:

		/*
		 * This op is a little strange because the internal return value is
		 * different than the return value stored in the result descriptor
		 * (There are really two return values)
		 */

		if ((ACPI_NAMESPACE_NODE *) obj_desc == acpi_gbl_root_node) {
			/*
			 * This means that the object does not exist in the namespace,
			 * return FALSE
			 */

			ret_desc->integer.value = 0;

			/*
			 * Must delete the result descriptor since there is no reference
			 * being returned
			 */

			acpi_cm_remove_reference (res_desc);
			goto cleanup;
		}

		/* Get the object reference and store it */

		status = acpi_aml_get_object_reference (obj_desc, &ret_desc2, walk_state);
		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}

		status = acpi_aml_exec_store (ret_desc2, res_desc, walk_state);

		/* The object exists in the namespace, return TRUE */

		ret_desc->integer.value = ACPI_INTEGER_MAX;
		goto cleanup;
		break;


	case AML_STORE_OP:

		/*
		 * A store operand is typically a number, string, buffer or lvalue
		 * TBD: [Unhandled] What about a store to a package?
		 */

		/*
		 * Do the store, and be careful about deleting the source object,
		 * since the object itself may have been stored.
		 */

		status = acpi_aml_exec_store (obj_desc, res_desc, walk_state);
		if (ACPI_FAILURE (status)) {
			/* On failure, just delete the Obj_desc */

			acpi_cm_remove_reference (obj_desc);
		}

		else {
			/*
			 * Normally, we would remove a reference on the Obj_desc parameter;
			 * But since it is being used as the internal return object
			 * (meaning we would normally increment it), the two cancel out,
			 * and we simply don't do anything.
			 */
			*return_desc = obj_desc;
		}

		obj_desc = NULL;
		return (status);

		break;


	case AML_DEBUG_OP:

		/* Reference, returning an Reference */

		return (AE_OK);
		break;


	/*
	 * These are obsolete opcodes
	 */

	/*  Def_shift_left_bit  :=  Shift_left_bit_op   Source          Bit_num */
	/*  Def_shift_right_bit :=  Shift_right_bit_op  Source          Bit_num */

	case AML_SHIFT_LEFT_BIT_OP:
	case AML_SHIFT_RIGHT_BIT_OP:

		status = AE_SUPPORT;
		goto cleanup;
		break;


	default:

		REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n",
			opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -