mirror of
https://github.com/acpica/acpica/
synced 2024-12-28 13:19:52 +03:00
Enable multi-byte EC transfers.
Previously, the maximum data size passed to the EC operation region handler was a single byte. Since there are often larger datums that need to be transfered, and the EC would like to lock these as a single transaction, this change enables transfers larger than a single byte. This may require changes to the host-OS Embedded Controller driver to enable 16/32/64 bit tranfers in addition to 8-bit transfers. Alexey Starikovskiy, Lin Ming
This commit is contained in:
parent
14aafc8b1b
commit
df3d422671
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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) */
|
||||
|
Loading…
Reference in New Issue
Block a user