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

📄 exfldio.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** * * Module Name: exfldio - Aml Field I/O * *****************************************************************************//* * Copyright (C) 2000 - 2005, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions, and the following disclaimer, *    without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer *    substantially similar to the "NO WARRANTY" disclaimer below *    ("Disclaimer") and any redistribution must be conditioned upon *    including a substantially similar Disclaimer requirement for further *    binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names *    of any contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */#include <acpi/acpi.h>#include <acpi/acinterp.h>#include <acpi/amlcode.h>#include <acpi/acevents.h>#include <acpi/acdispat.h>#define _COMPONENT          ACPI_EXECUTER	 ACPI_MODULE_NAME    ("exfldio")/******************************************************************************* * * FUNCTION:    acpi_ex_setup_region * * PARAMETERS:  *obj_desc               - Field to be read or written *              field_datum_byte_offset - Byte offset of this datum within the *                                        parent field * * RETURN:      Status * * DESCRIPTION: Common processing for acpi_ex_extract_from_field and *              acpi_ex_insert_into_field. Initialize the Region if necessary and *              validate the request. * ******************************************************************************/acpi_statusacpi_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 (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_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));		return_ACPI_STATUS (AE_AML_REGION_LIMIT);	}	return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION:    acpi_ex_access_region * * PARAMETERS:  *obj_desc               - Field to be read *              field_datum_byte_offset - Byte offset of this datum within the *                                        parent field *              *Value                  - Where to store value (must at least *                                        the size of acpi_integer) *              Function                - Read or Write flag plus other region- *                                        dependent flags * * RETURN:      Status * * DESCRIPTION: Read or Write a single field datum to an Operation Region. * ******************************************************************************/acpi_statusacpi_ex_access_region (	union acpi_operand_object       *obj_desc,	u32                             field_datum_byte_offset,	acpi_integer                    *value,	u32                             function){	acpi_status                     status;	union acpi_operand_object       *rgn_desc;	acpi_physical_address           address;	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;	address = rgn_desc->region.address			 + 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, byte_base %X, Offset %X at %8.8X%8.8X\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_FORMAT_UINT64 (address)));	/* Invoke the appropriate address_space/op_region handler */	status = acpi_ev_address_space_dispatch (rgn_desc, function,			  address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);	if (ACPI_FAILURE (status)) {		if (status == AE_NOT_IMPLEMENTED) {			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,				"Region %s(%X) not implemented\n",				acpi_ut_get_region_name (rgn_desc->region.space_id),				rgn_desc->region.space_id));		}		else if (status == AE_NOT_EXIST) {			ACPI_REPORT_ERROR ((				"Region %s(%X) has no handler\n",				acpi_ut_get_region_name (rgn_desc->region.space_id),				rgn_desc->region.space_id));		}	}	return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION:    acpi_ex_register_overflow * * PARAMETERS:  *obj_desc               - Register(Field) to be written *              Value                   - Value to be stored * * RETURN:      TRUE if value overflows the field, FALSE otherwise * * DESCRIPTION: Check if a value is out of range of the field being written. *              Used to check if the values written to Index and Bank registers *              are out of range.  Normally, the value is simply truncated *              to fit the field, but this case is most likely a serious *              coding error in the ASL. * ******************************************************************************/u8acpi_ex_register_overflow (	union acpi_operand_object       *obj_desc,	acpi_integer                    value){	if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {		/*		 * The field is large enough to hold the maximum integer, so we can		 * never overflow it.		 */		return (FALSE);	}	if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) {		/*		 * The Value is larger than the maximum value that can fit into		 * the register.		 */		return (TRUE);	}	/* The Value will fit into the field with no truncation */	return (FALSE);}/******************************************************************************* * * FUNCTION:    acpi_ex_field_datum_io * * PARAMETERS:  *obj_desc               - Field to be read *              field_datum_byte_offset - Byte offset of this datum within the *                                        parent field *              *Value                  - Where to store value (must be 64 bits) *              read_write              - Read or Write flag * * RETURN:      Status * * DESCRIPTION: Read or Write a single datum of a field.  The field_type is *              demultiplexed here to handle the different types of fields *              (buffer_field, region_field, index_field, bank_field) * ******************************************************************************/acpi_statusacpi_ex_field_datum_io (	union acpi_operand_object       *obj_desc,	u32                             field_datum_byte_offset,	acpi_integer                    *value,	u32                             read_write){	acpi_status                     status;	acpi_integer                    local_value;	ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);	if (read_write == ACPI_READ) {		if (!value) {			local_value = 0;			value = &local_value; /* To support reads without saving return value */		}		/* Clear the entire return buffer first, [Very Important!] */		*value = 0;	}	/*	 * The four types of fields are:	 *	 * buffer_field - Read/write from/to a Buffer	 * region_field - Read/write from/to a Operation Region.	 * bank_field  - Write to a Bank Register, then read/write from/to an op_region	 * index_field - Write to an Index Register, then read/write from/to a Data Register	 */	switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {	case ACPI_TYPE_BUFFER_FIELD:		/*		 * If the buffer_field arguments have not been previously evaluated,		 * evaluate them now and save the results.		 */		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {			status = acpi_ds_get_buffer_field_arguments (obj_desc);			if (ACPI_FAILURE (status)) {				return_ACPI_STATUS (status);			}		}		if (read_write == ACPI_READ) {			/*			 * Copy the data from the source buffer.			 * Length is the field width in bytes.			 */			ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer					  + obj_desc->buffer_field.base_byte_offset					  + field_datum_byte_offset,					  obj_desc->common_field.access_byte_width);		}		else {			/*			 * Copy the data to the target buffer.			 * Length is the field width in bytes.			 */			ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer					+ obj_desc->buffer_field.base_byte_offset					+ field_datum_byte_offset,					value, obj_desc->common_field.access_byte_width);		}		status = AE_OK;		break;	case ACPI_TYPE_LOCAL_BANK_FIELD:		/* Ensure that the bank_value is not beyond the capacity of the register */		if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,				  (acpi_integer) obj_desc->bank_field.value)) {			return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);		}		/*		 * For bank_fields, we must write the bank_value to the bank_register		 * (itself a region_field) before we can access the data.

⌨️ 快捷键说明

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