patch-2.4.1 linux/drivers/acpi/interpreter/amconvrt.c

Next file: linux/drivers/acpi/interpreter/amcreate.c
Previous file: linux/drivers/acpi/interpreter/amconfig.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0/linux/drivers/acpi/interpreter/amconvrt.c linux/drivers/acpi/interpreter/amconvrt.c
@@ -0,0 +1,525 @@
+/******************************************************************************
+ *
+ * Module Name: amconvrt - Object conversion routines
+ *              $Revision: 3 $
+ *
+ *****************************************************************************/
+
+/*
+ *  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"
+#include "acparser.h"
+#include "acnamesp.h"
+#include "acinterp.h"
+#include "acevents.h"
+#include "amlcode.h"
+#include "acdispat.h"
+
+
+#define _COMPONENT          INTERPRETER
+	 MODULE_NAME         ("amconvrt")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_target_type
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_target_type (
+	OBJECT_TYPE_INTERNAL    destination_type,
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status = AE_OK;
+
+
+	/*
+	 * If required by the target,
+	 * perform implicit conversion on the source before we store it.
+	 */
+
+	switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args))
+	{
+	case ARGI_SIMPLE_TARGET:
+	case ARGI_FIXED_TARGET:
+	case ARGI_INTEGER_REF:      /* Handles Increment, Decrement cases */
+
+		switch (destination_type)
+		{
+		case INTERNAL_TYPE_DEF_FIELD:
+			/*
+			 * Named field can always handle conversions
+			 */
+			break;
+
+		default:
+			/* No conversion allowed for these types */
+
+			if (destination_type != (*obj_desc)->common.type) {
+				status = AE_TYPE;
+			}
+		}
+		break;
+
+
+	case ARGI_TARGETREF:
+
+		switch (destination_type)
+		{
+		case ACPI_TYPE_INTEGER:
+		case ACPI_TYPE_FIELD_UNIT:
+		case INTERNAL_TYPE_BANK_FIELD:
+		case INTERNAL_TYPE_INDEX_FIELD:
+			/*
+			 * These types require an Integer operand.  We can convert
+			 * a Buffer or a String to an Integer if necessary.
+			 */
+			status = acpi_aml_convert_to_integer (obj_desc, walk_state);
+			break;
+
+
+		case ACPI_TYPE_STRING:
+
+			/*
+			 * The operand must be a String.  We can convert an
+			 * Integer or Buffer if necessary
+			 */
+			status = acpi_aml_convert_to_string (obj_desc, walk_state);
+			break;
+
+
+		case ACPI_TYPE_BUFFER:
+
+			/*
+			 * The operand must be a String.  We can convert an
+			 * Integer or Buffer if necessary
+			 */
+			status = acpi_aml_convert_to_buffer (obj_desc, walk_state);
+			break;
+		}
+		break;
+
+
+	case ARGI_REFERENCE:
+		/*
+		 * Create_xxxx_field cases - we are storing the field object into the name
+		 */
+		break;
+
+
+	default:
+		status = AE_AML_INTERNAL;
+	}
+
+
+	/*
+	 * Source-to-Target conversion semantics:
+	 *
+	 * If conversion to the target type cannot be performed, then simply
+	 * overwrite the target with the new object and type.
+	 */
+	if (status == AE_TYPE) {
+		status = AE_OK;
+	}
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_integer
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to an integer.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_integer (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	u32                     i;
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	u32                     count;
+	char                    *pointer;
+	ACPI_INTEGER            result;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+
+
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+		return (AE_OK);
+
+	case ACPI_TYPE_STRING:
+		pointer = (*obj_desc)->string.pointer;
+		count = (*obj_desc)->string.length;
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		pointer = (char *) (*obj_desc)->buffer.pointer;
+		count = (*obj_desc)->buffer.length;
+		break;
+
+	default:
+		return (AE_TYPE);
+	}
+
+	/*
+	 * Create a new integer
+	 */
+	ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
+	if (!ret_desc) {
+		return (AE_NO_MEMORY);
+	}
+
+
+	/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+	if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+		/*
+		 * We are running a method that exists in a 32-bit ACPI table.
+		 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
+		 */
+		integer_size = sizeof (u32);
+	}
+
+
+	/*
+	 * Convert the buffer/string to an integer.  Note that both buffers and
+	 * strings are treated as raw data - we don't convert ascii to hex for
+	 * strings.
+	 *
+	 * There are two terminating conditions for the loop:
+	 * 1) The size of an integer has been reached, or
+	 * 2) The end of the buffer or string has been reached
+	 */
+	result = 0;
+
+	/* Transfer no more than an integer's worth of data */
+
+	if (count > integer_size) {
+		count = integer_size;
+	}
+
+	/*
+	 * String conversion is different than Buffer conversion
+	 */
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_STRING:
+
+		/* TBD: Need to use 64-bit STRTOUL */
+
+		/*
+		 * Convert string to an integer
+		 * String must be hexadecimal as per the ACPI specification
+		 */
+
+		result = STRTOUL (pointer, NULL, 16);
+		break;
+
+
+	case ACPI_TYPE_BUFFER:
+
+		/*
+		 * Buffer conversion - we simply grab enough raw data from the
+		 * buffer to fill an integer
+		 */
+		for (i = 0; i < count; i++) {
+			/*
+			 * Get next byte and shift it into the Result.
+			 * Little endian is used, meaning that the first byte of the buffer
+			 * is the LSB of the integer
+			 */
+			result |= (((ACPI_INTEGER) pointer[i]) << (i * 8));
+		}
+
+		break;
+	}
+
+	/* Save the Result, delete original descriptor, store new descriptor */
+
+	ret_desc->integer.value = result;
+
+	if (walk_state->opcode != AML_STORE_OP) {
+		acpi_cm_remove_reference (*obj_desc);
+	}
+
+	*obj_desc = ret_desc;
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_buffer
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to an Buffer
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_buffer (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	u32                     i;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+	u8                      *new_buf;
+
+
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+
+		/*
+		 * Create a new Buffer
+		 */
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+			/*
+			 * We are running a method that exists in a 32-bit ACPI table.
+			 * Truncate the value to 32 bits by zeroing out the upper
+			 * 32-bit field
+			 */
+			integer_size = sizeof (u32);
+		}
+
+		/* Need enough space for one integers */
+
+		ret_desc->buffer.length = integer_size;
+		new_buf = acpi_cm_callocate (integer_size);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			acpi_cm_remove_reference (ret_desc);
+			return (AE_NO_MEMORY);
+		}
+
+		/* Copy the integer to the buffer */
+
+		for (i = 0; i < integer_size; i++) {
+			new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8));
+		}
+		ret_desc->buffer.pointer = new_buf;
+
+		/* Return the new buffer descriptor */
+
+		if (walk_state->opcode != AML_STORE_OP) {
+			acpi_cm_remove_reference (*obj_desc);
+		}
+		*obj_desc = ret_desc;
+		break;
+
+
+	case ACPI_TYPE_STRING:
+		break;
+
+
+	case ACPI_TYPE_BUFFER:
+		break;
+
+
+	default:
+		return (AE_TYPE);
+		break;
+   }
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_aml_convert_to_string
+ *
+ * PARAMETERS:  *Obj_desc       - Object to be converted.  Must be an
+ *                                Integer, Buffer, or String
+ *              Walk_state      - Current method state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an ACPI Object to a string
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_aml_convert_to_string (
+	ACPI_OPERAND_OBJECT     **obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_OPERAND_OBJECT     *ret_desc;
+	u32                     i;
+	u32                     index;
+	u32                     integer_size = sizeof (ACPI_INTEGER);
+	u8                      *new_buf;
+	u8                      *pointer;
+
+
+	switch ((*obj_desc)->common.type)
+	{
+	case ACPI_TYPE_INTEGER:
+
+		/*
+		 * Create a new String
+		 */
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+			/*
+			 * We are running a method that exists in a 32-bit ACPI table.
+			 * Truncate the value to 32 bits by zeroing out the upper
+			 * 32-bit field
+			 */
+			integer_size = sizeof (u32);
+		}
+
+		/* Need enough space for one ASCII integer plus null terminator */
+
+		ret_desc->string.length = (integer_size * 2) + 1;
+		new_buf = acpi_cm_callocate (ret_desc->string.length);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			acpi_cm_remove_reference (ret_desc);
+			return (AE_NO_MEMORY);
+		}
+
+		/* Copy the integer to the buffer */
+
+		for (i = 0; i < (integer_size * 2); i++) {
+			new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF];
+		}
+
+		/* Null terminate */
+
+		new_buf [i] = 0;
+		ret_desc->buffer.pointer = new_buf;
+
+		/* Return the new buffer descriptor */
+
+		if (walk_state->opcode != AML_STORE_OP) {
+			acpi_cm_remove_reference (*obj_desc);
+		}
+		*obj_desc = ret_desc;
+
+		return (AE_OK);
+
+
+	case ACPI_TYPE_BUFFER:
+
+		if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) {
+			return (AE_AML_STRING_LIMIT);
+		}
+
+		/*
+		 * Create a new String
+		 */
+		ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
+		if (!ret_desc) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Need enough space for one ASCII integer plus null terminator */
+
+		ret_desc->string.length = (*obj_desc)->buffer.length * 3;
+		new_buf = acpi_cm_callocate (ret_desc->string.length + 1);
+		if (!new_buf) {
+			REPORT_ERROR
+				(("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
+			acpi_cm_remove_reference (ret_desc);
+			return (AE_NO_MEMORY);
+		}
+
+		/*
+		 * Convert each byte of the buffer to two ASCII characters plus a space.
+		 */
+		pointer = (*obj_desc)->buffer.pointer;
+		index = 0;
+		for (i = 0; i < (*obj_desc)->buffer.length; i++) {
+			new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F];
+			new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F];
+			new_buf[index + 2] = ' ';
+			index += 3;
+		}
+
+		/* Null terminate */
+
+		new_buf [index] = 0;
+		ret_desc->buffer.pointer = new_buf;
+
+		/* Return the new buffer descriptor */
+
+		if (walk_state->opcode != AML_STORE_OP) {
+			acpi_cm_remove_reference (*obj_desc);
+		}
+		*obj_desc = ret_desc;
+		break;
+
+
+	case ACPI_TYPE_STRING:
+		break;
+
+
+	default:
+		return (AE_TYPE);
+		break;
+   }
+
+	return (AE_OK);
+}
+
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)