summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/acpica/exprep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/exprep.c')
-rw-r--r--sys/contrib/dev/acpica/exprep.c206
1 files changed, 154 insertions, 52 deletions
diff --git a/sys/contrib/dev/acpica/exprep.c b/sys/contrib/dev/acpica/exprep.c
index 6071e0d..6ed7cd4 100644
--- a/sys/contrib/dev/acpica/exprep.c
+++ b/sys/contrib/dev/acpica/exprep.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
- * $Revision: 122 $
+ * $Revision: 125 $
*
*****************************************************************************/
@@ -127,6 +127,139 @@
ACPI_MODULE_NAME ("exprep")
+#ifdef ACPI_UNDER_DEVELOPMENT
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiExGenerateAccess
+ *
+ * PARAMETERS: FieldBitOffset - Start of field within parent region/buffer
+ * FieldBitLength - Length of field in bits
+ * RegionLength - Length of parent in bytes
+ *
+ * RETURN: Field granularity (8, 16, 32 or 64) and
+ * ByteAlignment (1, 2, 3, or 4)
+ *
+ * DESCRIPTION: Generate an optimal access width for fields defined with the
+ * AnyAcc keyword.
+ *
+ * NOTE: Need to have the RegionLength in order to check for boundary
+ * conditions (end-of-region). However, the RegionLength 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 UINT32
+AcpiExGenerateAccess (
+ UINT32 FieldBitOffset,
+ UINT32 FieldBitLength,
+ UINT32 RegionLength)
+{
+ UINT32 FieldByteLength;
+ UINT32 FieldByteOffset;
+ UINT32 FieldByteEndOffset;
+ UINT32 AccessByteWidth;
+ UINT32 FieldStartOffset;
+ UINT32 FieldEndOffset;
+ UINT32 MinimumAccessWidth = 0xFFFFFFFF;
+ UINT32 MinimumAccesses = 0xFFFFFFFF;
+ UINT32 Accesses;
+
+
+ ACPI_FUNCTION_TRACE ("ExGenerateAccess");
+
+
+ /* Round Field start offset and length to "minimal" byte boundaries */
+
+ FieldByteOffset = ACPI_DIV_8 (ACPI_ROUND_DOWN (FieldBitOffset, 8));
+ FieldByteEndOffset = ACPI_DIV_8 (ACPI_ROUND_UP (FieldBitLength + FieldBitOffset, 8));
+ FieldByteLength = FieldByteEndOffset - FieldByteOffset;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Bit length %d, Bit offset %d\n",
+ FieldBitLength, FieldBitOffset));
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Byte Length %d, Byte Offset %d, End Offset %d\n",
+ FieldByteLength, FieldByteOffset, FieldByteEndOffset));
+
+ /*
+ * Iterative search for the maximum access width that is both aligned
+ * and does not go beyond the end of the region
+ *
+ * Start at ByteAcc and work upwards to QwordAcc max. (1,2,4,8 bytes)
+ */
+ for (AccessByteWidth = 1; AccessByteWidth <= 8; AccessByteWidth <<= 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 FieldByteLength, we are done.
+ * (This does not optimize for the perfectly aligned case yet).
+ */
+ if (ACPI_ROUND_UP (FieldByteEndOffset, AccessByteWidth) <= RegionLength)
+ {
+ FieldStartOffset = ACPI_ROUND_DOWN (FieldByteOffset, AccessByteWidth) /
+ AccessByteWidth;
+ FieldEndOffset = ACPI_ROUND_UP ((FieldByteLength + FieldByteOffset),
+ AccessByteWidth) / AccessByteWidth;
+ Accesses = FieldEndOffset - FieldStartOffset;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "AccessWidth %d end is within region\n", AccessByteWidth));
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "Field Start %d, Field End %d -- requires %d accesses\n",
+ FieldStartOffset, FieldEndOffset, 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",
+ AccessByteWidth));
+ return_VALUE (AccessByteWidth);
+ }
+
+ /*
+ * Fits in the region, but requires more than one read/write.
+ * try the next wider access on next iteration
+ */
+ if (Accesses < MinimumAccesses)
+ {
+ MinimumAccesses = Accesses;
+ MinimumAccessWidth = AccessByteWidth;
+ }
+ }
+ else
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+ "AccessWidth %d end is NOT within region\n", AccessByteWidth));
+ if (AccessByteWidth == 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",
+ MinimumAccessWidth));
+ return_VALUE (MinimumAccessWidth);
+ }
+ }
+
+ /* 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: AcpiExDecodeFieldAccess
@@ -148,12 +281,11 @@ AcpiExDecodeFieldAccess (
UINT32 *ReturnByteAlignment)
{
UINT32 Access;
- UINT8 ByteAlignment;
- UINT8 BitLength;
-/* UINT32 Length; */
+ UINT32 ByteAlignment;
+ UINT32 BitLength;
- ACPI_FUNCTION_NAME ("ExDecodeFieldAccess");
+ ACPI_FUNCTION_TRACE ("ExDecodeFieldAccess");
Access = (FieldFlags & AML_FIELD_ACCESS_TYPE_MASK);
@@ -162,46 +294,15 @@ AcpiExDecodeFieldAccess (
{
case AML_FIELD_ACCESS_ANY:
+#ifdef ACPI_UNDER_DEVELOPMENT
+ ByteAlignment = AcpiExGenerateAccess (ObjDesc->CommonField.StartFieldBitOffset,
+ ObjDesc->CommonField.BitLength,
+ 0xFFFFFFFF /* Temp until we pass RegionLength as param */);
+ BitLength = ByteAlignment * 8;
+#endif
+
ByteAlignment = 1;
BitLength = 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 = ObjDesc->CommonField.BitLength;
-
- if (Length <= 8)
- {
- BitLength = 8;
- }
- else if (Length <= 16)
- {
- BitLength = 16;
- }
- else if (Length <= 32)
- {
- BitLength = 32;
- }
- else if (Length <= 64)
- {
- BitLength = 64;
- }
- else
- {
- /* Larger than Qword - just use byte-size chunks */
-
- BitLength = 8;
- }
-#endif
break;
case AML_FIELD_ACCESS_BYTE:
@@ -231,7 +332,7 @@ AcpiExDecodeFieldAccess (
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Unknown field access type %X\n",
Access));
- return (0);
+ return_VALUE (0);
}
if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD)
@@ -245,7 +346,7 @@ AcpiExDecodeFieldAccess (
}
*ReturnByteAlignment = ByteAlignment;
- return (BitLength);
+ return_VALUE (BitLength);
}
@@ -333,7 +434,7 @@ AcpiExPrepCommonFieldObject (
*/
NearestByteAddress =
ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition);
- ObjDesc->CommonField.BaseByteOffset =
+ ObjDesc->CommonField.BaseByteOffset = (UINT32)
ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment);
/*
@@ -422,7 +523,7 @@ AcpiExPrepFieldValue (
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, AcpiUtGetTypeName (Type)));
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
@@ -461,7 +562,7 @@ AcpiExPrepFieldValue (
AcpiUtAddReference (ObjDesc->Field.RegionObj);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "RegionField: Bitoff=%X Off=%X Gran=%X Region %p\n",
+ "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
ObjDesc->Field.StartFieldBitOffset, ObjDesc->Field.BaseByteOffset,
ObjDesc->Field.AccessByteWidth, ObjDesc->Field.RegionObj));
break;
@@ -479,7 +580,7 @@ AcpiExPrepFieldValue (
AcpiUtAddReference (ObjDesc->BankField.BankObj);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Bank Field: BitOff=%X Off=%X Gran=%X Region %p BankReg %p\n",
+ "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
ObjDesc->BankField.StartFieldBitOffset,
ObjDesc->BankField.BaseByteOffset,
ObjDesc->Field.AccessByteWidth,
@@ -507,9 +608,10 @@ AcpiExPrepFieldValue (
AcpiUtAddReference (ObjDesc->IndexField.IndexObj);
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "IndexField: bitoff=%X off=%X gran=%X Index %p Data %p\n",
+ "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
ObjDesc->IndexField.StartFieldBitOffset,
ObjDesc->IndexField.BaseByteOffset,
+ ObjDesc->IndexField.Value,
ObjDesc->Field.AccessByteWidth,
ObjDesc->IndexField.IndexObj,
ObjDesc->IndexField.DataObj));
@@ -527,8 +629,8 @@ AcpiExPrepFieldValue (
Status = AcpiNsAttachObject (Info->FieldNode, ObjDesc,
AcpiNsGetType (Info->FieldNode));
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set NamedObj %p (%4.4s) val = %p\n",
- Info->FieldNode, Info->FieldNode->Name.Ascii, ObjDesc));
+ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n",
+ Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc));
/* Remove local reference to the object */
OpenPOWER on IntegriCloud