|
@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Exit now for SMBus or IPMI address space, it has a non-linear address space
|
|
|
- * and the request cannot be directly validated
|
|
|
+ * Exit now for SMBus or IPMI address space, it has a non-linear
|
|
|
+ * address space and the request cannot be directly validated
|
|
|
*/
|
|
|
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
|
|
|
rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
|
|
@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
|
|
|
* (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.base_byte_offset + field_datum_byte_offset +
|
|
|
obj_desc->common_field.access_byte_width)) {
|
|
|
if (acpi_gbl_enable_interpreter_slack) {
|
|
|
/*
|
|
@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
|
|
|
u32 buffer_tail_bits;
|
|
|
u32 datum_count;
|
|
|
u32 field_datum_count;
|
|
|
+ u32 access_bit_width;
|
|
|
u32 i;
|
|
|
|
|
|
ACPI_FUNCTION_TRACE(ex_extract_from_field);
|
|
@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
|
|
|
|
|
|
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
|
|
|
}
|
|
|
+
|
|
|
ACPI_MEMSET(buffer, 0, buffer_length);
|
|
|
+ access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
|
|
|
+
|
|
|
+ /* Handle the simple case here */
|
|
|
+
|
|
|
+ if ((obj_desc->common_field.start_field_bit_offset == 0) &&
|
|
|
+ (obj_desc->common_field.bit_length == access_bit_width)) {
|
|
|
+ status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
|
|
|
+ return_ACPI_STATUS(status);
|
|
|
+ }
|
|
|
+
|
|
|
+/* TBD: Move to common setup code */
|
|
|
+
|
|
|
+ /* Field algorithm is limited to sizeof(u64), truncate if needed */
|
|
|
+
|
|
|
+ if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
|
|
|
+ obj_desc->common_field.access_byte_width = sizeof(u64);
|
|
|
+ access_bit_width = sizeof(u64) * 8;
|
|
|
+ }
|
|
|
|
|
|
/* Compute the number of datums (access width data items) */
|
|
|
|
|
|
- datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
|
|
|
- obj_desc->common_field.access_bit_width);
|
|
|
+ datum_count =
|
|
|
+ ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
|
|
|
+ access_bit_width);
|
|
|
+
|
|
|
field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
|
|
|
obj_desc->common_field.
|
|
|
start_field_bit_offset,
|
|
|
- obj_desc->common_field.
|
|
|
access_bit_width);
|
|
|
|
|
|
/* Priming read from the field */
|
|
@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
|
|
|
* This avoids the differences in behavior between different compilers
|
|
|
* concerning shift values larger than the target data width.
|
|
|
*/
|
|
|
- if ((obj_desc->common_field.access_bit_width -
|
|
|
- obj_desc->common_field.start_field_bit_offset) <
|
|
|
+ if (access_bit_width -
|
|
|
+ obj_desc->common_field.start_field_bit_offset <
|
|
|
ACPI_INTEGER_BIT_SIZE) {
|
|
|
merged_datum |=
|
|
|
- raw_datum << (obj_desc->common_field.
|
|
|
- access_bit_width -
|
|
|
+ raw_datum << (access_bit_width -
|
|
|
obj_desc->common_field.
|
|
|
start_field_bit_offset);
|
|
|
}
|
|
@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
|
|
|
|
|
|
/* Mask off any extra bits in the last datum */
|
|
|
|
|
|
- buffer_tail_bits = obj_desc->common_field.bit_length %
|
|
|
- obj_desc->common_field.access_bit_width;
|
|
|
+ buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
|
|
|
if (buffer_tail_bits) {
|
|
|
merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
|
|
|
}
|
|
@@ -798,6 +816,7 @@ acpi_status
|
|
|
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
void *buffer, u32 buffer_length)
|
|
|
{
|
|
|
+ void *new_buffer;
|
|
|
acpi_status status;
|
|
|
u64 mask;
|
|
|
u64 width_mask;
|
|
@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
u32 buffer_tail_bits;
|
|
|
u32 datum_count;
|
|
|
u32 field_datum_count;
|
|
|
- u32 i;
|
|
|
+ u32 access_bit_width;
|
|
|
u32 required_length;
|
|
|
- void *new_buffer;
|
|
|
+ u32 i;
|
|
|
|
|
|
ACPI_FUNCTION_TRACE(ex_insert_into_field);
|
|
|
|
|
@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
buffer_length = required_length;
|
|
|
}
|
|
|
|
|
|
+/* TBD: Move to common setup code */
|
|
|
+
|
|
|
+ /* Algo is limited to sizeof(u64), so cut the access_byte_width */
|
|
|
+ if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
|
|
|
+ obj_desc->common_field.access_byte_width = sizeof(u64);
|
|
|
+ }
|
|
|
+
|
|
|
+ access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
|
|
|
+
|
|
|
/*
|
|
|
* Create the bitmasks used for bit insertion.
|
|
|
* Note: This if/else is used to bypass compiler differences with the
|
|
|
* shift operator
|
|
|
*/
|
|
|
- if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
|
|
|
+ if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
|
|
|
width_mask = ACPI_UINT64_MAX;
|
|
|
} else {
|
|
|
- width_mask =
|
|
|
- ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
|
|
|
- access_bit_width);
|
|
|
+ width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
|
|
|
}
|
|
|
|
|
|
mask = width_mask &
|
|
@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
/* Compute the number of datums (access width data items) */
|
|
|
|
|
|
datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
|
|
|
- obj_desc->common_field.access_bit_width);
|
|
|
+ access_bit_width);
|
|
|
|
|
|
field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
|
|
|
obj_desc->common_field.
|
|
|
start_field_bit_offset,
|
|
|
- obj_desc->common_field.
|
|
|
access_bit_width);
|
|
|
|
|
|
/* Get initial Datum from the input buffer */
|
|
@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
* This avoids the differences in behavior between different compilers
|
|
|
* concerning shift values larger than the target data width.
|
|
|
*/
|
|
|
- if ((obj_desc->common_field.access_bit_width -
|
|
|
+ if ((access_bit_width -
|
|
|
obj_desc->common_field.start_field_bit_offset) <
|
|
|
ACPI_INTEGER_BIT_SIZE) {
|
|
|
merged_datum =
|
|
|
- raw_datum >> (obj_desc->common_field.
|
|
|
- access_bit_width -
|
|
|
+ raw_datum >> (access_bit_width -
|
|
|
obj_desc->common_field.
|
|
|
start_field_bit_offset);
|
|
|
} else {
|
|
@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
|
|
|
ACPI_MIN(obj_desc->common_field.access_byte_width,
|
|
|
buffer_length - buffer_offset));
|
|
|
+
|
|
|
merged_datum |=
|
|
|
raw_datum << obj_desc->common_field.start_field_bit_offset;
|
|
|
}
|
|
@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
|
|
|
|
|
|
buffer_tail_bits = (obj_desc->common_field.bit_length +
|
|
|
obj_desc->common_field.start_field_bit_offset) %
|
|
|
- obj_desc->common_field.access_bit_width;
|
|
|
+ access_bit_width;
|
|
|
if (buffer_tail_bits) {
|
|
|
mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
|
|
|
}
|