patch-2.4.23 linux-2.4.23/drivers/acpi/executer/exprep.c
Next file: linux-2.4.23/drivers/acpi/executer/exresnte.c
Previous file: linux-2.4.23/drivers/acpi/executer/exoparg1.c
Back to the patch index
Back to the overall index
- Lines: 265
- Date:
2003-11-28 10:26:19.000000000 -0800
- Orig file:
linux-2.4.22/drivers/acpi/executer/exprep.c
- Orig date:
2003-08-25 04:44:41.000000000 -0700
diff -urN linux-2.4.22/drivers/acpi/executer/exprep.c linux-2.4.23/drivers/acpi/executer/exprep.c
@@ -53,6 +53,133 @@
ACPI_MODULE_NAME ("exprep")
+#ifdef ACPI_UNDER_DEVELOPMENT
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ex_generate_access
+ *
+ * PARAMETERS: field_bit_offset - Start of field within parent region/buffer
+ * field_bit_length - Length of field in bits
+ * region_length - Length of parent in bytes
+ *
+ * RETURN: Field granularity (8, 16, 32 or 64) and
+ * byte_alignment (1, 2, 3, or 4)
+ *
+ * DESCRIPTION: Generate an optimal access width for fields defined with the
+ * any_acc keyword.
+ *
+ * NOTE: Need to have the region_length in order to check for boundary
+ * conditions (end-of-region). However, the region_length is a deferred
+ * operation. Therefore, to complete this implementation, the generation
+ * of this access width must be deferred until the region length has
+ * been evaluated.
+ *
+ ******************************************************************************/
+
+static u32
+acpi_ex_generate_access (
+ u32 field_bit_offset,
+ u32 field_bit_length,
+ u32 region_length)
+{
+ u32 field_byte_length;
+ u32 field_byte_offset;
+ u32 field_byte_end_offset;
+ u32 access_byte_width;
+ u32 field_start_offset;
+ u32 field_end_offset;
+ u32 minimum_access_width = 0xFFFFFFFF;
+ u32 minimum_accesses = 0xFFFFFFFF;
+ u32 accesses;
+
+
+ ACPI_FUNCTION_TRACE ("ex_generate_access");
+
+
+ /* Round Field start offset and length to "minimal" byte boundaries */
+
+ field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8));
+ field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length + field_bit_offset, 8));
+ field_byte_length = field_byte_end_offset - field_byte_offset;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Bit length %d, Bit offset %d\n",
+ field_bit_length, field_bit_offset));
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Byte Length %d, Byte Offset %d, End Offset %d\n",
+ field_byte_length, field_byte_offset, field_byte_end_offset));
+
+ /*
+ * Iterative search for the maximum access width that is both aligned
+ * and does not go beyond the end of the region
+ *
+ * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
+ */
+ for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) {
+ /*
+ * 1) Round end offset up to next access boundary and make sure that this
+ * does not go beyond the end of the parent region.
+ * 2) When the Access width is greater than the field_byte_length, we are done.
+ * (This does not optimize for the perfectly aligned case yet).
+ */
+ if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) {
+ field_start_offset = ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) /
+ access_byte_width;
+ field_end_offset = ACPI_ROUND_UP ((field_byte_length + field_byte_offset),
+ access_byte_width) / access_byte_width;
+ accesses = field_end_offset - field_start_offset;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "access_width %d end is within region\n", access_byte_width));
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Field Start %d, Field End %d -- requires %d accesses\n",
+ field_start_offset, field_end_offset, accesses));
+
+ /* Single access is optimal */
+
+ if (accesses <= 1) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Entire field can be accessed with one operation of size %d\n",
+ access_byte_width));
+ return_VALUE (access_byte_width);
+ }
+
+ /*
+ * Fits in the region, but requires more than one read/write.
+ * try the next wider access on next iteration
+ */
+ if (accesses < minimum_accesses) {
+ minimum_accesses = accesses;
+ minimum_access_width = access_byte_width;
+ }
+ }
+ else {
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "access_width %d end is NOT within region\n", access_byte_width));
+ if (access_byte_width == 1) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Field goes beyond end-of-region!\n"));
+ return_VALUE (0); /* Field does not fit in the region at all */
+ }
+
+ /* This width goes beyond the end-of-region, back off to previous access */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Backing off to previous optimal access width of %d\n",
+ minimum_access_width));
+ return_VALUE (minimum_access_width);
+ }
+ }
+
+ /* Could not read/write field with one operation, just use max access width */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Cannot access field in one operation, using width 8\n"));
+ return_VALUE (8);
+}
+#endif /* ACPI_UNDER_DEVELOPMENT */
+
+
/*******************************************************************************
*
* FUNCTION: acpi_ex_decode_field_access
@@ -74,12 +201,11 @@
u32 *return_byte_alignment)
{
u32 access;
- u8 byte_alignment;
- u8 bit_length;
-/* u32 Length; */
+ u32 byte_alignment;
+ u32 bit_length;
- ACPI_FUNCTION_NAME ("ex_decode_field_access");
+ ACPI_FUNCTION_TRACE ("ex_decode_field_access");
access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
@@ -87,41 +213,15 @@
switch (access) {
case AML_FIELD_ACCESS_ANY:
+#ifdef ACPI_UNDER_DEVELOPMENT
+ byte_alignment = acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.bit_length,
+ 0xFFFFFFFF /* Temp until we pass region_length as param */);
+ bit_length = byte_alignment * 8;
+#endif
+
byte_alignment = 1;
bit_length = 8;
-
-#if 0
- /*
- * TBD: optimize
- *
- * Any attempt to optimize the access size to the size of the field
- * must take into consideration the length of the region and take
- * care that an access to the field will not attempt to access
- * beyond the end of the region.
- */
-
- /* Use the length to set the access type */
-
- length = obj_desc->common_field.bit_length;
-
- if (length <= 8) {
- bit_length = 8;
- }
- else if (length <= 16) {
- bit_length = 16;
- }
- else if (length <= 32) {
- bit_length = 32;
- }
- else if (length <= 64) {
- bit_length = 64;
- }
- else {
- /* Larger than Qword - just use byte-size chunks */
-
- bit_length = 8;
- }
-#endif
break;
case AML_FIELD_ACCESS_BYTE:
@@ -151,7 +251,7 @@
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Unknown field access type %X\n",
access));
- return (0);
+ return_VALUE (0);
}
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
@@ -164,7 +264,7 @@
}
*return_byte_alignment = byte_alignment;
- return (bit_length);
+ return_VALUE (bit_length);
}
@@ -336,7 +436,7 @@
type = acpi_ns_get_type (info->region_node);
if (type != ACPI_TYPE_REGION) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Needed Region, found type %X %s\n",
+ "Needed Region, found type %X (%s)\n",
type, acpi_ut_get_type_name (type)));
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
@@ -372,7 +472,7 @@
acpi_ut_add_reference (obj_desc->field.region_obj);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "region_field: Bitoff=%X Off=%X Gran=%X Region %p\n",
+ "region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
obj_desc->field.access_byte_width, obj_desc->field.region_obj));
break;
@@ -390,7 +490,7 @@
acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Bank Field: bit_off=%X Off=%X Gran=%X Region %p bank_reg %p\n",
+ "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
obj_desc->bank_field.start_field_bit_offset,
obj_desc->bank_field.base_byte_offset,
obj_desc->field.access_byte_width,
@@ -417,9 +517,10 @@
acpi_ut_add_reference (obj_desc->index_field.index_obj);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n",
+ "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
obj_desc->index_field.start_field_bit_offset,
obj_desc->index_field.base_byte_offset,
+ obj_desc->index_field.value,
obj_desc->field.access_byte_width,
obj_desc->index_field.index_obj,
obj_desc->index_field.data_obj));
@@ -437,7 +538,7 @@
status = acpi_ns_attach_object (info->field_node, obj_desc,
acpi_ns_get_type (info->field_node));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set named_obj %p (%4.4s) val = %p\n",
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n",
info->field_node, info->field_node->name.ascii, obj_desc));
/* Remove local reference to the object */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)