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

📄 exfldio.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
			 * Put together the appropriate bits of the two raw data to make a			 * single complete field datum			 *			 * 1) Normalize the first datum down to bit 0			 */			merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset);			/* 2) Insert the second datum "above" the first datum */			merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits);			if ((datum_offset >= (datum_count -1))) {				/*				 * This is the last iteration of the loop.  We need to clear				 * any unused bits (bits that are not part of this field) that				 * came from the last raw datum before we store the final				 * merged datum into the caller buffer.				 */				if (obj_desc->common_field.end_buffer_valid_bits) {					merged_datum &=						MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);				}			}		}		/*		 * Store the merged field datum in the caller's buffer, according to		 * the granularity of the field (size of each datum).		 */		acpi_ex_set_buffer_datum (merged_datum, buffer, obj_desc->common_field.access_byte_width,				datum_offset);		/*		 * Save the raw datum that was just acquired since it may contain bits		 * of the *next* field datum.  Update offsets		 */		previous_raw_datum = this_raw_datum;		datum_offset++;	}	return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION:    Acpi_ex_write_field_datum * * PARAMETERS:  *Obj_desc           - Field to be set *              Value               - Value to store * * RETURN:      Status * * DESCRIPTION: Store the value into the given field * ******************************************************************************/static acpi_statusacpi_ex_write_field_datum (	acpi_operand_object     *obj_desc,	u32                     field_datum_byte_offset,	u32                     value){	acpi_status             status = AE_OK;	acpi_operand_object     *rgn_desc = NULL;	ACPI_PHYSICAL_ADDRESS   address;	FUNCTION_TRACE_U32 ("Ex_write_field_datum", field_datum_byte_offset);	/*	 * Buffer_fields - Read from a Buffer	 * Other Fields - Read from a Operation Region.	 */	switch (obj_desc->common.type) {	case ACPI_TYPE_BUFFER_FIELD:		/*		 * For Buffer_fields, we only need to copy the data to the		 * target buffer.  Length is the field width in bytes.		 */		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 INTERNAL_TYPE_REGION_FIELD:	case INTERNAL_TYPE_BANK_FIELD:		/*		 * For other fields, we need to go through an Operation Region		 * (Only types that will get here are Region_fields and Bank_fields)		 */		status = acpi_ex_setup_field (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;		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,			"Store %X in Region %s(%X) at %8.8X%8.8X width %X\n",			value, acpi_ut_get_region_name (rgn_desc->region.space_id),			rgn_desc->region.space_id, HIDWORD(address), LODWORD(address),			obj_desc->common_field.access_bit_width));		/* Invoke the appropriate Address_space/Op_region handler */		status = acpi_ev_address_space_dispatch (rgn_desc, ACPI_WRITE_ADR_SPACE,				  address, obj_desc->common_field.access_bit_width, &value);		if (status == AE_NOT_IMPLEMENTED) {			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,				"**** Region type %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_DEBUG_PRINT ((ACPI_DB_ERROR,				"**** Region type %s(%X) does not have a handler\n",				acpi_ut_get_region_name (rgn_desc->region.space_id),				rgn_desc->region.space_id));		}		break;	default:		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n",			obj_desc, acpi_ut_get_type_name (obj_desc->common.type)));		status = AE_AML_INTERNAL;		break;	}	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value written=%08X \n", value));	return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION:    Acpi_ex_write_field_datum_with_update_rule * * PARAMETERS:  *Obj_desc           - Field to be set *              Value               - Value to store * * RETURN:      Status * * DESCRIPTION: Apply the field update rule to a field write * ******************************************************************************/static acpi_statusacpi_ex_write_field_datum_with_update_rule (	acpi_operand_object     *obj_desc,	u32                     mask,	u32                     field_value,	u32                     field_datum_byte_offset){	acpi_status             status = AE_OK;	u32                     merged_value;	u32                     current_value;	FUNCTION_TRACE ("Ex_write_field_datum_with_update_rule");	/* Start with the new bits  */	merged_value = field_value;	/* If the mask is all ones, we don't need to worry about the update rule */	if (mask != ACPI_UINT32_MAX) {		/* Decode the update rule */		switch (obj_desc->common_field.update_rule) {		case UPDATE_PRESERVE:			/*			 * Check if update rule needs to be applied (not if mask is all			 * ones)  The left shift drops the bits we want to ignore.			 */			if ((~mask << (sizeof (mask) * 8 -					  obj_desc->common_field.access_bit_width)) != 0) {				/*				 * Read the current contents of the byte/word/dword containing				 * the field, and merge with the new field value.				 */				status = acpi_ex_read_field_datum (obj_desc, field_datum_byte_offset,						  &current_value);				merged_value |= (current_value & ~mask);			}			break;		case UPDATE_WRITE_AS_ONES:			/* Set positions outside the field to all ones */			merged_value |= ~mask;			break;		case UPDATE_WRITE_AS_ZEROS:			/* Set positions outside the field to all zeros */			merged_value &= mask;			break;		default:			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,				"Write_with_update_rule: Unknown Update_rule setting: %x\n",				obj_desc->common_field.update_rule));			return_ACPI_STATUS (AE_AML_OPERAND_VALUE);			break;		}	}	/* Write the merged value */	status = acpi_ex_write_field_datum (obj_desc, field_datum_byte_offset,			  merged_value);	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Mask %X Datum_offset %X Value %X, Merged_value %X\n",		mask, field_datum_byte_offset, field_value, merged_value));	return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION:    Acpi_ex_insert_into_field * * PARAMETERS:  *Obj_desc           - Field to be set *              Buffer              - Value to store * * RETURN:      Status * * DESCRIPTION: Store the value into the given field * ******************************************************************************/acpi_statusacpi_ex_insert_into_field (	acpi_operand_object     *obj_desc,	void                    *buffer,	u32                     buffer_length){	acpi_status             status;	u32                     field_datum_byte_offset;	u32                     datum_offset;	u32                     mask;	u32                     merged_datum;	u32                     previous_raw_datum;	u32                     this_raw_datum;	u32                     byte_field_length;	u32                     datum_count;	FUNCTION_TRACE ("Ex_insert_into_field");	/*	 * Incoming buffer must be at least as long as the field, we do not	 * allow "partial" field writes.  We do not care if the buffer is	 * larger than the field, this typically happens when an integer is	 * written to a field that is actually smaller than an integer.	 */	byte_field_length = ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);	if (buffer_length < byte_field_length) {		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer length %X too small for field %X\n",			buffer_length, byte_field_length));		/* TBD: Need a better error code */		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);	}	/* Convert byte count to datum count, round up if necessary */	datum_count = ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width);	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,		"Byte_len=%x, Datum_len=%x, Bit_gran=%x, Byte_gran=%x\n",		byte_field_length, datum_count, obj_desc->common_field.access_bit_width,		obj_desc->common_field.access_byte_width));	/*	 * Break the request into up to three parts (similar to an I/O request):	 * 1) non-aligned part at start	 * 2) aligned part in middle	 * 3) non-aligned part at the end	 */	field_datum_byte_offset = 0;	datum_offset= 0;	/* Get a single datum from the caller's buffer */	acpi_ex_get_buffer_datum (&previous_raw_datum, buffer,			obj_desc->common_field.access_byte_width, datum_offset);	/*	 * Part1:	 * Write a partial field datum if field does not begin on a datum boundary	 * Note: The code in this section also handles the aligned case	 *	 * Construct Mask with 1 bits where the field is, 0 bits elsewhere	 * (Only the bottom 5 bits of Bit_length are valid for a shift operation)	 *	 * Mask off bits that are "below" the field (if any)	 */	mask = MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);	/* If the field fits in one datum, may need to mask upper bits */	if ((obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM) &&		 obj_desc->common_field.end_field_valid_bits) {		/* There are bits above the field, mask them off also */		mask &= MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);	}	/* Shift and mask the value into the field position */	merged_datum = (previous_raw_datum << obj_desc->common_field.start_field_bit_offset);	merged_datum &= mask;	/* Apply the update rule (if necessary) and write the datum to the field */	status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask, merged_datum,			   field_datum_byte_offset);	if (ACPI_FAILURE (status)) {		return_ACPI_STATUS (status);	}	/* If the entire field fits within one datum, we are done. */	if ((datum_count == 1) &&	   (obj_desc->common_field.access_flags & AFIELD_SINGLE_DATUM)) {		return_ACPI_STATUS (AE_OK);	}	/*	 * Part2:	 * Write the aligned data.	 *	 * We don't need to worry about the update rule for these data, because	 * all of the bits in each datum are part of the field.	 *	 * The last datum must be special cased because it might contain bits	 * that are not part of the field -- therefore the "update rule" must be	 * applied in Part3 below.	 */	while (datum_offset < datum_count) {		datum_offset++;		field_datum_byte_offset += obj_desc->common_field.access_byte_width;		/*		 * Get the next raw buffer datum.  It may contain bits of the previous		 * field datum		 */		acpi_ex_get_buffer_datum (&this_raw_datum, buffer,				obj_desc->common_field.access_byte_width, datum_offset);		/* Create the field datum based on the field alignment */		if (obj_desc->common_field.start_field_bit_offset != 0) {			/*			 * Put together appropriate bits of the two raw buffer data to make			 * a single complete field datum			 */			merged_datum =				(previous_raw_datum >> obj_desc->common_field.datum_valid_bits) |				(this_raw_datum << obj_desc->common_field.start_field_bit_offset);		}		else {			/* Field began aligned on datum boundary */			merged_datum = this_raw_datum;		}		/*		 * Special handling for the last datum if the field does NOT end on		 * a datum boundary.  Update Rule must be applied to the bits outside		 * the field.		 */		if (datum_offset == datum_count) {			/*			 * If there are dangling non-aligned bits, perform one more merged write			 * Else - field is aligned at the end, no need for any more writes			 */			if (obj_desc->common_field.end_field_valid_bits) {				/*				 * Part3:				 * This is the last datum and the field does not end on a datum boundary.				 * Build the partial datum and write with the update rule.				 *				 * Mask off the unused bits above (after) the end-of-field				 */				mask = MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);				merged_datum &= mask;				/* Write the last datum with the update rule */				status = acpi_ex_write_field_datum_with_update_rule (obj_desc, mask,						  merged_datum, field_datum_byte_offset);				if (ACPI_FAILURE (status)) {					return_ACPI_STATUS (status);				}			}		}		else {			/* Normal case -- write the completed datum */			status = acpi_ex_write_field_datum (obj_desc,					  field_datum_byte_offset, merged_datum);			if (ACPI_FAILURE (status)) {				return_ACPI_STATUS (status);			}		}		/*		 * Save the most recent datum since it may contain bits of the *next*		 * field datum.  Update current byte offset.		 */		previous_raw_datum = this_raw_datum;	}	return_ACPI_STATUS (status);}

⌨️ 快捷键说明

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