From 89cfbf859b7ca4088e77c428f27c376a0fbddc02 Mon Sep 17 00:00:00 2001 From: Robert Moore Date: Wed, 4 Aug 2010 14:20:18 -0700 Subject: [PATCH] Revert "Revert "Enable multi-byte EC transfers."" This reverts commit f23b9c7d4928dca89d0e93f0683caf094c4a74d0. The problem with this change was determined to be a problem with the FreeBSD host OSL (OS services layer), not with this patch itself. Therefore, re-introducing this change into the main ACPICA code. See ACPICA bugzilla 863. --- source/components/executer/exfldio.c | 90 +++++++++++++++++---------- source/components/executer/exprep.c | 91 +++++++++++++++++----------- source/include/acobject.h | 1 - 3 files changed, 113 insertions(+), 69 deletions(-) diff --git a/source/components/executer/exfldio.c b/source/components/executer/exfldio.c index 3276bc418..5ba1b44c5 100644 --- a/source/components/executer/exfldio.c +++ b/source/components/executer/exfldio.c @@ -202,8 +202,8 @@ AcpiExSetupRegion ( } /* - * 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 (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI) @@ -233,8 +233,7 @@ AcpiExSetupRegion ( * (Region length is specified in bytes) */ if (RgnDesc->Region.Length < - (ObjDesc->CommonField.BaseByteOffset + - FieldDatumByteOffset + + (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset + ObjDesc->CommonField.AccessByteWidth)) { if (AcpiGbl_EnableInterpreterSlack) @@ -794,6 +793,7 @@ AcpiExExtractFromField ( UINT32 BufferTailBits; UINT32 DatumCount; UINT32 FieldDatumCount; + UINT32 AccessBitWidth; UINT32 i; @@ -803,7 +803,7 @@ AcpiExExtractFromField ( /* Validate target buffer and clear it */ if (BufferLength < - ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength)) + ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength)) { ACPI_ERROR ((AE_INFO, "Field size %u (bits) is too large for buffer (%u)", @@ -811,17 +811,37 @@ AcpiExExtractFromField ( return_ACPI_STATUS (AE_BUFFER_OVERFLOW); } + ACPI_MEMSET (Buffer, 0, BufferLength); + AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth); + + /* Handle the simple case here */ + + if ((ObjDesc->CommonField.StartFieldBitOffset == 0) && + (ObjDesc->CommonField.BitLength == AccessBitWidth)) + { + Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ); + return_ACPI_STATUS (Status); + } + +/* TBD: Move to common setup code */ + + /* Field algorithm is limited to sizeof(UINT64), truncate if needed */ + + if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64)) + { + ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64); + AccessBitWidth = sizeof (UINT64) * 8; + } /* Compute the number of datums (access width data items) */ DatumCount = ACPI_ROUND_UP_TO ( - ObjDesc->CommonField.BitLength, - ObjDesc->CommonField.AccessBitWidth); + ObjDesc->CommonField.BitLength, AccessBitWidth); + FieldDatumCount = ACPI_ROUND_UP_TO ( - ObjDesc->CommonField.BitLength + - ObjDesc->CommonField.StartFieldBitOffset, - ObjDesc->CommonField.AccessBitWidth); + ObjDesc->CommonField.BitLength + + ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth); /* Priming read from the field */ @@ -854,12 +874,11 @@ AcpiExExtractFromField ( * This avoids the differences in behavior between different compilers * concerning shift values larger than the target data width. */ - if ((ObjDesc->CommonField.AccessBitWidth - - ObjDesc->CommonField.StartFieldBitOffset) < ACPI_INTEGER_BIT_SIZE) + if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset < + ACPI_INTEGER_BIT_SIZE) { MergedDatum |= RawDatum << - (ObjDesc->CommonField.AccessBitWidth - - ObjDesc->CommonField.StartFieldBitOffset); + (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset); } if (i == DatumCount) @@ -879,8 +898,7 @@ AcpiExExtractFromField ( /* Mask off any extra bits in the last datum */ - BufferTailBits = ObjDesc->CommonField.BitLength % - ObjDesc->CommonField.AccessBitWidth; + BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth; if (BufferTailBits) { MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits); @@ -916,6 +934,7 @@ AcpiExInsertIntoField ( void *Buffer, UINT32 BufferLength) { + void *NewBuffer; ACPI_STATUS Status; UINT64 Mask; UINT64 WidthMask; @@ -926,9 +945,9 @@ AcpiExInsertIntoField ( UINT32 BufferTailBits; UINT32 DatumCount; UINT32 FieldDatumCount; - UINT32 i; + UINT32 AccessBitWidth; UINT32 RequiredLength; - void *NewBuffer; + UINT32 i; ACPI_FUNCTION_TRACE (ExInsertIntoField); @@ -965,31 +984,41 @@ AcpiExInsertIntoField ( BufferLength = RequiredLength; } +/* TBD: Move to common setup code */ + + /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */ + if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64)) + { + ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64); + } + + AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth); + /* * Create the bitmasks used for bit insertion. * Note: This if/else is used to bypass compiler differences with the * shift operator */ - if (ObjDesc->CommonField.AccessBitWidth == ACPI_INTEGER_BIT_SIZE) + if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE) { WidthMask = ACPI_UINT64_MAX; } else { - WidthMask = ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.AccessBitWidth); + WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth); } Mask = WidthMask & - ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset); + ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset); /* Compute the number of datums (access width data items) */ DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength, - ObjDesc->CommonField.AccessBitWidth); + AccessBitWidth); FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength + - ObjDesc->CommonField.StartFieldBitOffset, - ObjDesc->CommonField.AccessBitWidth); + ObjDesc->CommonField.StartFieldBitOffset, + AccessBitWidth); /* Get initial Datum from the input buffer */ @@ -1024,12 +1053,11 @@ AcpiExInsertIntoField ( * This avoids the differences in behavior between different compilers * concerning shift values larger than the target data width. */ - if ((ObjDesc->CommonField.AccessBitWidth - - ObjDesc->CommonField.StartFieldBitOffset) < ACPI_INTEGER_BIT_SIZE) + if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) < + ACPI_INTEGER_BIT_SIZE) { MergedDatum = RawDatum >> - (ObjDesc->CommonField.AccessBitWidth - - ObjDesc->CommonField.StartFieldBitOffset); + (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset); } else { @@ -1048,15 +1076,15 @@ AcpiExInsertIntoField ( BufferOffset += ObjDesc->CommonField.AccessByteWidth; ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset, ACPI_MIN(ObjDesc->CommonField.AccessByteWidth, - BufferLength - BufferOffset)); + BufferLength - BufferOffset)); + MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset; } /* Mask off any extra bits in the last datum */ BufferTailBits = (ObjDesc->CommonField.BitLength + - ObjDesc->CommonField.StartFieldBitOffset) % - ObjDesc->CommonField.AccessBitWidth; + ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth; if (BufferTailBits) { Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits); diff --git a/source/components/executer/exprep.c b/source/components/executer/exprep.c index b1c97164a..624140497 100644 --- a/source/components/executer/exprep.c +++ b/source/components/executer/exprep.c @@ -193,12 +193,12 @@ AcpiExGenerateAccess ( FieldByteLength = FieldByteEndOffset - FieldByteOffset; ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Bit length %u, Bit offset %u\n", - FieldBitLength, FieldBitOffset)); + "Bit length %u, Bit offset %u\n", + FieldBitLength, FieldBitOffset)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Byte Length %u, Byte Offset %u, End Offset %u\n", - FieldByteLength, FieldByteOffset, FieldByteEndOffset)); + "Byte Length %u, Byte Offset %u, End Offset %u\n", + FieldByteLength, FieldByteOffset, FieldByteEndOffset)); /* * Iterative search for the maximum access width that is both aligned @@ -228,11 +228,11 @@ AcpiExGenerateAccess ( Accesses = FieldEndOffset - FieldStartOffset; ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "AccessWidth %u end is within region\n", AccessByteWidth)); + "AccessWidth %u end is within region\n", AccessByteWidth)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Field Start %u, Field End %u -- requires %u accesses\n", - FieldStartOffset, FieldEndOffset, Accesses)); + "Field Start %u, Field End %u -- requires %u accesses\n", + FieldStartOffset, FieldEndOffset, Accesses)); /* Single access is optimal */ @@ -261,7 +261,7 @@ AcpiExGenerateAccess ( if (AccessByteWidth == 1) { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Field goes beyond end-of-region!\n")); + "Field goes beyond end-of-region!\n")); /* Field does not fit in the region at all */ @@ -273,8 +273,8 @@ AcpiExGenerateAccess ( * previous access */ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Backing off to previous optimal access width of %u\n", - MinimumAccessWidth)); + "Backing off to previous optimal access width of %u\n", + MinimumAccessWidth)); return_VALUE (MinimumAccessWidth); } } @@ -284,7 +284,7 @@ AcpiExGenerateAccess ( * just use max access width */ ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Cannot access field in one operation, using width 8\n")); + "Cannot access field in one operation, using width 8\n")); return_VALUE (8); } #endif /* ACPI_UNDER_DEVELOPMENT */ @@ -444,18 +444,16 @@ AcpiExPrepCommonFieldObject ( * the same (equivalent) as the ByteAlignment. */ AccessBitWidth = AcpiExDecodeFieldAccess (ObjDesc, FieldFlags, - &ByteAlignment); + &ByteAlignment); if (!AccessBitWidth) { return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } - /* Setup width (access granularity) fields */ + /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */ ObjDesc->CommonField.AccessByteWidth = (UINT8) - ACPI_DIV_8 (AccessBitWidth); /* 1, 2, 4, 8 */ - - ObjDesc->CommonField.AccessBitWidth = (UINT8) AccessBitWidth; + ACPI_DIV_8 (AccessBitWidth); /* * BaseByteOffset is the address of the start of the field within the @@ -468,9 +466,9 @@ AcpiExPrepCommonFieldObject ( * region or buffer. */ NearestByteAddress = - ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition); + ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition); ObjDesc->CommonField.BaseByteOffset = (UINT32) - ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment); + ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment); /* * StartFieldBitOffset is the offset of the first bit of the field within @@ -502,8 +500,9 @@ AcpiExPrepFieldValue ( { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *SecondDesc = NULL; - UINT32 Type; ACPI_STATUS Status; + UINT32 AccessByteWidth; + UINT32 Type; ACPI_FUNCTION_TRACE (ExPrepFieldValue); @@ -522,8 +521,7 @@ AcpiExPrepFieldValue ( Type = AcpiNsGetType (Info->RegionNode); if (Type != ACPI_TYPE_REGION) { - ACPI_ERROR ((AE_INFO, - "Needed Region, found type 0x%X (%s)", + ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)", Type, AcpiUtGetTypeName (Type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); @@ -541,8 +539,9 @@ AcpiExPrepFieldValue ( /* Initialize areas of the object that are common to all fields */ ObjDesc->CommonField.Node = Info->FieldNode; - Status = AcpiExPrepCommonFieldObject (ObjDesc, Info->FieldFlags, - Info->Attribute, Info->FieldBitPosition, Info->FieldBitLength); + Status = AcpiExPrepCommonFieldObject (ObjDesc, + Info->FieldFlags, Info->Attribute, + Info->FieldBitPosition, Info->FieldBitLength); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); @@ -557,6 +556,22 @@ AcpiExPrepFieldValue ( ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); + /* Allow full data read from EC address space */ + + if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && + (ObjDesc->CommonField.BitLength > 8)) + { + AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->CommonField.BitLength); + + /* Maximum byte width supported is 255 */ + + if (AccessByteWidth < 256) + { + ObjDesc->CommonField.AccessByteWidth = (UINT8) AccessByteWidth; + } + } + /* An additional reference for the container */ AcpiUtAddReference (ObjDesc->Field.RegionObj); @@ -570,11 +585,11 @@ AcpiExPrepFieldValue ( case ACPI_TYPE_LOCAL_BANK_FIELD: - ObjDesc->BankField.Value = Info->BankValue; - ObjDesc->BankField.RegionObj = AcpiNsGetAttachedObject ( - Info->RegionNode); - ObjDesc->BankField.BankObj = AcpiNsGetAttachedObject ( - Info->RegisterNode); + ObjDesc->BankField.Value = Info->BankValue; + ObjDesc->BankField.RegionObj = + AcpiNsGetAttachedObject (Info->RegionNode); + ObjDesc->BankField.BankObj = + AcpiNsGetAttachedObject (Info->RegisterNode); /* An additional reference for the attached objects */ @@ -594,9 +609,11 @@ AcpiExPrepFieldValue ( * opcode and operands -- since the BankValue * operands must be evaluated. */ - SecondDesc = ObjDesc->Common.NextObject; - SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Info->DataRegisterNode)->Named.Data; - SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Info->DataRegisterNode)->Named.Length; + SecondDesc = ObjDesc->Common.NextObject; + SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, + Info->DataRegisterNode)->Named.Data; + SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, + Info->DataRegisterNode)->Named.Length; break; @@ -605,10 +622,10 @@ AcpiExPrepFieldValue ( /* Get the Index and Data registers */ - ObjDesc->IndexField.IndexObj = AcpiNsGetAttachedObject ( - Info->RegisterNode); - ObjDesc->IndexField.DataObj = AcpiNsGetAttachedObject ( - Info->DataRegisterNode); + ObjDesc->IndexField.IndexObj = + AcpiNsGetAttachedObject (Info->RegisterNode); + ObjDesc->IndexField.DataObj = + AcpiNsGetAttachedObject (Info->DataRegisterNode); if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj) { @@ -663,10 +680,10 @@ AcpiExPrepFieldValue ( * preserving the current type of that NamedObj. */ Status = AcpiNsAttachObject (Info->FieldNode, ObjDesc, - AcpiNsGetType (Info->FieldNode)); + AcpiNsGetType (Info->FieldNode)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n", - Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc)); + Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc)); /* Remove local reference to the object */ diff --git a/source/include/acobject.h b/source/include/acobject.h index 29f8b623c..ebb656a1b 100644 --- a/source/include/acobject.h +++ b/source/include/acobject.h @@ -386,7 +386,6 @@ typedef struct acpi_object_thermal_zone UINT32 BaseByteOffset; /* Byte offset within containing object */\ UINT32 Value; /* Value to store into the Bank or Index register */\ UINT8 StartFieldBitOffset;/* Bit offset within first field datum (0-63) */\ - UINT8 AccessBitWidth; /* Read/Write size in bits (8-64) */ typedef struct acpi_object_field_common /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */