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

📄 exfldio.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * FUNCTION:    acpi_ex_extract_from_field * * PARAMETERS:  *obj_desc           - Field to be read *              *Value              - Where to store value * * RETURN:      Status * * DESCRIPTION: Retrieve the value of the given field * ******************************************************************************/acpi_statusacpi_ex_extract_from_field (	union acpi_operand_object       *obj_desc,	void                            *buffer,	u32                             buffer_length){	acpi_status                     status;	u32                             field_datum_byte_offset;	u32                             buffer_datum_offset;	acpi_integer                    previous_raw_datum = 0;	acpi_integer                    this_raw_datum = 0;	acpi_integer                    merged_datum = 0;	u32                             byte_field_length;	u32                             datum_count;	u32                             i;	ACPI_FUNCTION_TRACE ("ex_extract_from_field");	/*	 * The field must fit within the caller's buffer	 */	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);	if (byte_field_length > buffer_length) {		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,			"Field size %X (bytes) too large for buffer (%X)\n",			byte_field_length, buffer_length));		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);	}	/* Convert field byte count to datum count, round up if necessary */	datum_count = ACPI_ROUND_UP_TO (byte_field_length,			   obj_desc->common_field.access_byte_width);	/*	 * If the field is not aligned on a datum boundary and does not	 * fit within a single datum, we must read an extra datum.	 *	 * We could just split the aligned and non-aligned cases since the	 * aligned case is so very simple, but this would require more code.	 */	if ((obj_desc->common_field.end_field_valid_bits != 0)    &&		(!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) {		datum_count++;	}	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,		"byte_len %X, datum_len %X, byte_gran %X\n",		byte_field_length, datum_count,obj_desc->common_field.access_byte_width));	/*	 * Clear the caller's buffer (the whole buffer length as given)	 * This is very important, especially in the cases where the buffer	 * is longer than the size of the field.	 */	ACPI_MEMSET (buffer, 0, buffer_length);	field_datum_byte_offset = 0;	buffer_datum_offset= 0;	/* Read the entire field */	for (i = 0; i < datum_count; i++) {		status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,				  &this_raw_datum, ACPI_READ);		if (ACPI_FAILURE (status)) {			return_ACPI_STATUS (status);		}		/* We might actually be done if the request fits in one datum */		if ((datum_count == 1) &&			(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) {			/* 1) Shift the valid data bits down to start at bit 0 */			merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);			/* 2) Mask off any upper unused bits (bits not part of the field) */			if (obj_desc->common_field.end_buffer_valid_bits) {				merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);			}			/* Store the datum to the caller buffer */			acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,					obj_desc->common_field.access_byte_width, buffer_datum_offset);			return_ACPI_STATUS (AE_OK);		}		/* Special handling for the last datum to ignore extra bits */		if ((i >= (datum_count -1))          &&			(obj_desc->common_field.end_field_valid_bits)) {			/*			 * This is the last iteration of the loop.  We need to clear			 * any unused bits (bits that are not part of this field) before			 * we store the final merged datum into the caller buffer.			 */			this_raw_datum &=				ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);		}		/*		 * Create the (possibly) merged datum to be stored to the caller buffer		 */		if (obj_desc->common_field.start_field_bit_offset == 0) {			/* Field is not skewed and we can just copy the datum */			acpi_ex_set_buffer_datum (this_raw_datum, buffer, buffer_length,					obj_desc->common_field.access_byte_width, buffer_datum_offset);			buffer_datum_offset++;		}		else {			/* Not aligned -- on the first iteration, just save the datum */			if (i != 0) {				/*				 * 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);				acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,						obj_desc->common_field.access_byte_width, buffer_datum_offset);				buffer_datum_offset++;			}			/*			 * Save the raw datum that was just acquired since it may contain bits			 * of the *next* field datum			 */			previous_raw_datum = this_raw_datum;		}		field_datum_byte_offset += obj_desc->common_field.access_byte_width;	}	/* For non-aligned case, there is one last datum to insert */	if (obj_desc->common_field.start_field_bit_offset != 0) {		merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);		acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,				obj_desc->common_field.access_byte_width, buffer_datum_offset);	}	return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * 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 (	union acpi_operand_object       *obj_desc,	void                            *buffer,	u32                             buffer_length){	acpi_status                     status;	u32                             field_datum_byte_offset;	u32                             datum_offset;	acpi_integer                    mask;	acpi_integer                    merged_datum;	acpi_integer                    previous_raw_datum;	acpi_integer                    this_raw_datum;	u32                             byte_field_length;	u32                             datum_count;	ACPI_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 = ACPI_ROUND_BITS_UP_TO_BYTES (			 obj_desc->common_field.bit_length);	if (buffer_length < byte_field_length) {		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,			"Buffer length %X too small for field %X\n",			buffer_length, byte_field_length));		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);	}	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (			 obj_desc->common_field.start_field_bit_offset +			 obj_desc->common_field.bit_length);	/* Convert byte count to datum count, round up if necessary */	datum_count = ACPI_ROUND_UP_TO (byte_field_length,			  obj_desc->common_field.access_byte_width);	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,		"Bytes %X, Datums %X, byte_gran %X\n",		byte_field_length, datum_count, 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, buffer_length,			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 = ACPI_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.flags & AOPOBJ_SINGLE_DATUM) &&		 obj_desc->common_field.end_field_valid_bits) {		/* There are bits above the field, mask them off also */		mask &= ACPI_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_with_update_rule (obj_desc, mask, merged_datum,			   field_datum_byte_offset);	if (ACPI_FAILURE (status)) {		return_ACPI_STATUS (status);	}	/* We just wrote the first datum */	datum_offset++;	/* If the entire field fits within one datum, we are done. */	if ((datum_count == 1) &&	   (obj_desc->common_field.flags & AOPOBJ_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) {		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, buffer_length,				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.		 */		datum_offset++;		if ((datum_offset == datum_count) &&			(obj_desc->common_field.end_field_valid_bits)) {			/*			 * 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			 */			/*			 * 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 = ACPI_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_with_update_rule (obj_desc, mask, merged_datum,					   field_datum_byte_offset);			if (ACPI_FAILURE (status)) {				return_ACPI_STATUS (status);			}		}		else {			/* Normal (aligned) case -- write the completed datum */			status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,					  &merged_datum, ACPI_WRITE);			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 + -