📄 exfldio.c
字号:
* 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. */ status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj, &obj_desc->bank_field.value, sizeof (obj_desc->bank_field.value)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* * Now that the Bank has been selected, fall through to the * region_field case and write the datum to the Operation Region */ /*lint -fallthrough */ case ACPI_TYPE_LOCAL_REGION_FIELD: /* * For simple region_fields, we just directly access the owning * Operation Region. */ status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value, read_write); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* Ensure that the index_value is not beyond the capacity of the register */ if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, (acpi_integer) obj_desc->index_field.value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } /* Write the index value to the index_register (itself a region_field) */ field_datum_byte_offset += obj_desc->index_field.value; ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Write to Index Register: Value %8.8X\n", field_datum_byte_offset)); status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj, &field_datum_byte_offset, sizeof (field_datum_byte_offset)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "I/O to Data Register: value_ptr %p\n", value)); if (read_write == ACPI_READ) { /* Read the datum from the data_register */ status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj, value, sizeof (acpi_integer)); } else { /* Write the datum to the data_register */ status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj, value, sizeof (acpi_integer)); } break; default: ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n", ACPI_GET_OBJECT_TYPE (obj_desc))); status = AE_AML_INTERNAL; break; } if (ACPI_SUCCESS (status)) { if (read_write == ACPI_READ) { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n", ACPI_FORMAT_UINT64 (*value), obj_desc->common_field.access_byte_width)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", ACPI_FORMAT_UINT64 (*value), obj_desc->common_field.access_byte_width)); } } return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: acpi_ex_write_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 * ******************************************************************************/acpi_statusacpi_ex_write_with_update_rule ( union acpi_operand_object *obj_desc, acpi_integer mask, acpi_integer field_value, u32 field_datum_byte_offset){ acpi_status status = AE_OK; acpi_integer merged_value; acpi_integer current_value; ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask); /* 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_INTEGER_MAX) { /* Decode the update rule */ switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) { case AML_FIELD_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 << (ACPI_MUL_8 (sizeof (mask)) - ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) { /* * Read the current contents of the byte/word/dword containing * the field, and merge with the new field value. */ status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, ¤t_value, ACPI_READ); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } merged_value |= (current_value & ~mask); } break; case AML_FIELD_UPDATE_WRITE_AS_ONES: /* Set positions outside the field to all ones */ merged_value |= ~mask; break; case AML_FIELD_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.field_flags & AML_FIELD_UPDATE_RULE_MASK))); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (mask), field_datum_byte_offset, obj_desc->common_field.access_byte_width, ACPI_FORMAT_UINT64 (field_value), ACPI_FORMAT_UINT64 (merged_value))); /* Write the merged value */ status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset, &merged_value, ACPI_WRITE); return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION: acpi_ex_get_buffer_datum * * PARAMETERS: Datum - Where the Datum is returned * Buffer - Raw field buffer * buffer_length - Entire length (used for big-endian only) * byte_granularity - 1/2/4/8 Granularity of the field * (aka Datum Size) * buffer_offset - Datum offset into the buffer * * RETURN: none * * DESCRIPTION: Get a datum from the buffer according to the buffer field * byte granularity * ******************************************************************************/voidacpi_ex_get_buffer_datum ( acpi_integer *datum, void *buffer, u32 buffer_length, u32 byte_granularity, u32 buffer_offset){ u32 index; ACPI_FUNCTION_TRACE_U32 ("ex_get_buffer_datum", byte_granularity); /* Get proper index into buffer (handles big/little endian) */ index = ACPI_BUFFER_INDEX (buffer_length, buffer_offset, byte_granularity); /* Move the requested number of bytes */ switch (byte_granularity) { case ACPI_FIELD_BYTE_GRANULARITY: *datum = ((u8 *) buffer) [index]; break; case ACPI_FIELD_WORD_GRANULARITY: ACPI_MOVE_16_TO_64 (datum, &(((u16 *) buffer) [index])); break; case ACPI_FIELD_DWORD_GRANULARITY: ACPI_MOVE_32_TO_64 (datum, &(((u32 *) buffer) [index])); break; case ACPI_FIELD_QWORD_GRANULARITY: ACPI_MOVE_64_TO_64 (datum, &(((u64 *) buffer) [index])); break; default: /* Should not get here */ break; } return_VOID;}/******************************************************************************* * * FUNCTION: acpi_ex_set_buffer_datum * * PARAMETERS: merged_datum - Value to store * Buffer - Receiving buffer * buffer_length - Entire length (used for big-endian only) * byte_granularity - 1/2/4/8 Granularity of the field * (aka Datum Size) * buffer_offset - Datum offset into the buffer * * RETURN: none * * DESCRIPTION: Store the merged datum to the buffer according to the * byte granularity * ******************************************************************************/voidacpi_ex_set_buffer_datum ( acpi_integer merged_datum, void *buffer, u32 buffer_length, u32 byte_granularity, u32 buffer_offset){ u32 index; ACPI_FUNCTION_TRACE_U32 ("ex_set_buffer_datum", byte_granularity); /* Get proper index into buffer (handles big/little endian) */ index = ACPI_BUFFER_INDEX (buffer_length, buffer_offset, byte_granularity); /* Move the requested number of bytes */ switch (byte_granularity) { case ACPI_FIELD_BYTE_GRANULARITY: ((u8 *) buffer) [index] = (u8) merged_datum; break; case ACPI_FIELD_WORD_GRANULARITY: ACPI_MOVE_64_TO_16 (&(((u16 *) buffer)[index]), &merged_datum); break; case ACPI_FIELD_DWORD_GRANULARITY: ACPI_MOVE_64_TO_32 (&(((u32 *) buffer)[index]), &merged_datum); break; case ACPI_FIELD_QWORD_GRANULARITY: ACPI_MOVE_64_TO_64 (&(((u64 *) buffer)[index]), &merged_datum); break; default: /* Should not get here */ break; } return_VOID;}/******************************************************************************* *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -