Local change: Allow access to the field if it is within the region
size rounded up to a multiple of the access byte width. This overcomes "off-by-one" programming errors in the AML often found in Toshiba laptops.
This commit is contained in:
parent
d46f5d8f89
commit
328a52e248
@ -1,7 +1,7 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* Module Name: exfldio - Aml Field I/O
|
* Module Name: exfldio - Aml Field I/O
|
||||||
* $Revision: 96 $
|
* $Revision: 100 $
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -139,7 +139,8 @@
|
|||||||
* RETURN: Status
|
* RETURN: Status
|
||||||
*
|
*
|
||||||
* DESCRIPTION: Common processing for AcpiExExtractFromField and
|
* DESCRIPTION: Common processing for AcpiExExtractFromField and
|
||||||
* AcpiExInsertIntoField. Initialize the
|
* AcpiExInsertIntoField. Initialize the Region if necessary and
|
||||||
|
* validate the request.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
@ -172,7 +173,7 @@ AcpiExSetupRegion (
|
|||||||
* If the Region Address and Length have not been previously evaluated,
|
* If the Region Address and Length have not been previously evaluated,
|
||||||
* evaluate them now and save the results.
|
* evaluate them now and save the results.
|
||||||
*/
|
*/
|
||||||
if (!(RgnDesc->Region.Flags & AOPOBJ_DATA_VALID))
|
if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
|
||||||
{
|
{
|
||||||
Status = AcpiDsGetRegionArguments (RgnDesc);
|
Status = AcpiDsGetRegionArguments (RgnDesc);
|
||||||
if (ACPI_FAILURE (Status))
|
if (ACPI_FAILURE (Status))
|
||||||
@ -188,6 +189,20 @@ AcpiExSetupRegion (
|
|||||||
return_ACPI_STATUS (AE_OK);
|
return_ACPI_STATUS (AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ACPI_UNDER_DEVELOPMENT
|
||||||
|
/*
|
||||||
|
* If the Field access is AnyAcc, we can now compute the optimal
|
||||||
|
* access (because we know know the length of the parent region)
|
||||||
|
*/
|
||||||
|
if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
|
||||||
|
{
|
||||||
|
if (ACPI_FAILURE (Status))
|
||||||
|
{
|
||||||
|
return_ACPI_STATUS (Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate the request. The entire request from the byte offset for a
|
* Validate the request. The entire request from the byte offset for a
|
||||||
* length of one field datum (access width) must fit within the region.
|
* length of one field datum (access width) must fit within the region.
|
||||||
@ -206,8 +221,9 @@ AcpiExSetupRegion (
|
|||||||
*/
|
*/
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||||
"Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
|
"Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
|
||||||
ObjDesc->CommonField.Node->Name.Ascii, ObjDesc->CommonField.AccessByteWidth,
|
AcpiUtGetNodeName (ObjDesc->CommonField.Node),
|
||||||
RgnDesc->Region.Node->Name.Ascii, RgnDesc->Region.Length));
|
ObjDesc->CommonField.AccessByteWidth,
|
||||||
|
AcpiUtGetNodeName (RgnDesc->Region.Node), RgnDesc->Region.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -216,9 +232,10 @@ AcpiExSetupRegion (
|
|||||||
*/
|
*/
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||||
"Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
|
"Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
|
||||||
ObjDesc->CommonField.Node->Name.Ascii, ObjDesc->CommonField.BaseByteOffset,
|
AcpiUtGetNodeName (ObjDesc->CommonField.Node),
|
||||||
|
ObjDesc->CommonField.BaseByteOffset,
|
||||||
FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
|
FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
|
||||||
RgnDesc->Region.Node->Name.Ascii, RgnDesc->Region.Length));
|
AcpiUtGetNodeName (RgnDesc->Region.Node), RgnDesc->Region.Length));
|
||||||
|
|
||||||
#ifndef ACPICA_PEDANTIC
|
#ifndef ACPICA_PEDANTIC
|
||||||
{
|
{
|
||||||
@ -311,13 +328,13 @@ AcpiExAccessRegion (
|
|||||||
}
|
}
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
|
||||||
" Region[%s-%X] Access %X Base:Off %X:%X at %8.8X%8.8X\n",
|
" Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
|
||||||
AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
|
AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
|
||||||
RgnDesc->Region.SpaceId,
|
RgnDesc->Region.SpaceId,
|
||||||
ObjDesc->CommonField.AccessByteWidth,
|
ObjDesc->CommonField.AccessByteWidth,
|
||||||
ObjDesc->CommonField.BaseByteOffset,
|
ObjDesc->CommonField.BaseByteOffset,
|
||||||
FieldDatumByteOffset,
|
FieldDatumByteOffset,
|
||||||
ACPI_HIDWORD (Address), ACPI_LODWORD (Address)));
|
ACPI_FORMAT_UINT64 (Address)));
|
||||||
|
|
||||||
/* Invoke the appropriate AddressSpace/OpRegion handler */
|
/* Invoke the appropriate AddressSpace/OpRegion handler */
|
||||||
|
|
||||||
@ -589,13 +606,15 @@ AcpiExFieldDatumIo (
|
|||||||
{
|
{
|
||||||
if (ReadWrite == ACPI_READ)
|
if (ReadWrite == ACPI_READ)
|
||||||
{
|
{
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read=%8.8X%8.8X\n",
|
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n",
|
||||||
ACPI_HIDWORD (*Value), ACPI_LODWORD (*Value)));
|
ACPI_FORMAT_UINT64 (*Value),
|
||||||
|
ObjDesc->CommonField.AccessByteWidth));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written=%8.8X%8.8X\n",
|
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n",
|
||||||
ACPI_HIDWORD (*Value), ACPI_LODWORD (*Value)));
|
ACPI_FORMAT_UINT64 (*Value),
|
||||||
|
ObjDesc->CommonField.AccessByteWidth));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,6 +676,11 @@ AcpiExWriteWithUpdateRule (
|
|||||||
*/
|
*/
|
||||||
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
||||||
&CurrentValue, ACPI_READ);
|
&CurrentValue, ACPI_READ);
|
||||||
|
if (ACPI_FAILURE (Status))
|
||||||
|
{
|
||||||
|
return_ACPI_STATUS (Status);
|
||||||
|
}
|
||||||
|
|
||||||
MergedValue |= (CurrentValue & ~Mask);
|
MergedValue |= (CurrentValue & ~Mask);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -676,6 +700,7 @@ AcpiExWriteWithUpdateRule (
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||||
"WriteWithUpdateRule: Unknown UpdateRule setting: %X\n",
|
"WriteWithUpdateRule: Unknown UpdateRule setting: %X\n",
|
||||||
(ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
|
(ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
|
||||||
@ -683,18 +708,19 @@ AcpiExWriteWithUpdateRule (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||||
|
"Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
|
||||||
|
ACPI_FORMAT_UINT64 (Mask),
|
||||||
|
FieldDatumByteOffset,
|
||||||
|
ObjDesc->CommonField.AccessByteWidth,
|
||||||
|
ACPI_FORMAT_UINT64 (FieldValue),
|
||||||
|
ACPI_FORMAT_UINT64 (MergedValue)));
|
||||||
|
|
||||||
/* Write the merged value */
|
/* Write the merged value */
|
||||||
|
|
||||||
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
||||||
&MergedValue, ACPI_WRITE);
|
&MergedValue, ACPI_WRITE);
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
|
||||||
"Mask %8.8X%8.8X DatumOffset %X Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
|
|
||||||
ACPI_HIDWORD (Mask), ACPI_LODWORD (Mask),
|
|
||||||
FieldDatumByteOffset,
|
|
||||||
ACPI_HIDWORD (FieldValue), ACPI_LODWORD (FieldValue),
|
|
||||||
ACPI_HIDWORD (MergedValue),ACPI_LODWORD (MergedValue)));
|
|
||||||
|
|
||||||
return_ACPI_STATUS (Status);
|
return_ACPI_STATUS (Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,7 +754,7 @@ AcpiExGetBufferDatum (
|
|||||||
UINT32 Index;
|
UINT32 Index;
|
||||||
|
|
||||||
|
|
||||||
ACPI_FUNCTION_ENTRY ();
|
ACPI_FUNCTION_TRACE_U32 ("ExGetBufferDatum", ByteGranularity);
|
||||||
|
|
||||||
|
|
||||||
/* Get proper index into buffer (handles big/little endian) */
|
/* Get proper index into buffer (handles big/little endian) */
|
||||||
@ -763,6 +789,8 @@ AcpiExGetBufferDatum (
|
|||||||
/* Should not get here */
|
/* Should not get here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -794,7 +822,8 @@ AcpiExSetBufferDatum (
|
|||||||
{
|
{
|
||||||
UINT32 Index;
|
UINT32 Index;
|
||||||
|
|
||||||
ACPI_FUNCTION_ENTRY ();
|
|
||||||
|
ACPI_FUNCTION_TRACE_U32 ("ExSetBufferDatum", ByteGranularity);
|
||||||
|
|
||||||
|
|
||||||
/* Get proper index into buffer (handles big/little endian) */
|
/* Get proper index into buffer (handles big/little endian) */
|
||||||
@ -829,6 +858,8 @@ AcpiExSetBufferDatum (
|
|||||||
/* Should not get here */
|
/* Should not get here */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -853,12 +884,13 @@ AcpiExExtractFromField (
|
|||||||
{
|
{
|
||||||
ACPI_STATUS Status;
|
ACPI_STATUS Status;
|
||||||
UINT32 FieldDatumByteOffset;
|
UINT32 FieldDatumByteOffset;
|
||||||
UINT32 DatumOffset;
|
UINT32 BufferDatumOffset;
|
||||||
ACPI_INTEGER PreviousRawDatum;
|
ACPI_INTEGER PreviousRawDatum = 0;
|
||||||
ACPI_INTEGER ThisRawDatum = 0;
|
ACPI_INTEGER ThisRawDatum = 0;
|
||||||
ACPI_INTEGER MergedDatum = 0;
|
ACPI_INTEGER MergedDatum = 0;
|
||||||
UINT32 ByteFieldLength;
|
UINT32 ByteFieldLength;
|
||||||
UINT32 DatumCount;
|
UINT32 DatumCount;
|
||||||
|
UINT32 i;
|
||||||
|
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE ("ExExtractFromField");
|
ACPI_FUNCTION_TRACE ("ExExtractFromField");
|
||||||
@ -882,83 +914,80 @@ AcpiExExtractFromField (
|
|||||||
DatumCount = ACPI_ROUND_UP_TO (ByteFieldLength,
|
DatumCount = ACPI_ROUND_UP_TO (ByteFieldLength,
|
||||||
ObjDesc->CommonField.AccessByteWidth);
|
ObjDesc->CommonField.AccessByteWidth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the field is not aligned on a datum boundary and does not
|
||||||
|
* fit within a single datum, we must read an extra datum.
|
||||||
|
*
|
||||||
|
* We could just split the aligned and non-aligned cases since the
|
||||||
|
* aligned case is so very simple, but this would require more code.
|
||||||
|
*/
|
||||||
|
if ((ObjDesc->CommonField.EndFieldValidBits != 0) &&
|
||||||
|
(!(ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM)))
|
||||||
|
{
|
||||||
|
DatumCount++;
|
||||||
|
}
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||||
"ByteLen=%X, DatumLen=%X, ByteGran=%X\n",
|
"ByteLen %X, DatumLen %X, ByteGran %X\n",
|
||||||
ByteFieldLength, DatumCount,ObjDesc->CommonField.AccessByteWidth));
|
ByteFieldLength, DatumCount,ObjDesc->CommonField.AccessByteWidth));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the caller's buffer (the whole buffer length as given)
|
* Clear the caller's buffer (the whole buffer length as given)
|
||||||
* This is very important, especially in the cases where a byte is read,
|
* This is very important, especially in the cases where the buffer
|
||||||
* but the buffer is really a UINT32 (4 bytes).
|
* is longer than the size of the field.
|
||||||
*/
|
*/
|
||||||
ACPI_MEMSET (Buffer, 0, BufferLength);
|
ACPI_MEMSET (Buffer, 0, BufferLength);
|
||||||
|
|
||||||
/* Read the first raw datum to prime the loop */
|
|
||||||
|
|
||||||
FieldDatumByteOffset = 0;
|
FieldDatumByteOffset = 0;
|
||||||
DatumOffset= 0;
|
BufferDatumOffset= 0;
|
||||||
|
|
||||||
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
/* Read the entire field */
|
||||||
&PreviousRawDatum, ACPI_READ);
|
|
||||||
if (ACPI_FAILURE (Status))
|
for (i = 0; i < DatumCount; i++)
|
||||||
{
|
{
|
||||||
return_ACPI_STATUS (Status);
|
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
||||||
}
|
&ThisRawDatum, ACPI_READ);
|
||||||
|
if (ACPI_FAILURE (Status))
|
||||||
|
|
||||||
/* We might actually be done if the request fits in one datum */
|
|
||||||
|
|
||||||
if ((DatumCount == 1) &&
|
|
||||||
(ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM))
|
|
||||||
{
|
|
||||||
/* 1) Shift the valid data bits down to start at bit 0 */
|
|
||||||
|
|
||||||
MergedDatum = (PreviousRawDatum >> ObjDesc->CommonField.StartFieldBitOffset);
|
|
||||||
|
|
||||||
/* 2) Mask off any upper unused bits (bits not part of the field) */
|
|
||||||
|
|
||||||
if (ObjDesc->CommonField.EndBufferValidBits)
|
|
||||||
{
|
{
|
||||||
MergedDatum &= ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.EndBufferValidBits);
|
return_ACPI_STATUS (Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the datum to the caller buffer */
|
/* We might actually be done if the request fits in one datum */
|
||||||
|
|
||||||
AcpiExSetBufferDatum (MergedDatum, Buffer, BufferLength,
|
if ((DatumCount == 1) &&
|
||||||
ObjDesc->CommonField.AccessByteWidth, DatumOffset);
|
(ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM))
|
||||||
|
{
|
||||||
|
/* 1) Shift the valid data bits down to start at bit 0 */
|
||||||
|
|
||||||
return_ACPI_STATUS (AE_OK);
|
MergedDatum = (ThisRawDatum >> ObjDesc->CommonField.StartFieldBitOffset);
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 2) Mask off any upper unused bits (bits not part of the field) */
|
||||||
|
|
||||||
/* We need to get more raw data to complete one or more field data */
|
if (ObjDesc->CommonField.EndBufferValidBits)
|
||||||
|
{
|
||||||
|
MergedDatum &= ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.EndBufferValidBits);
|
||||||
|
}
|
||||||
|
|
||||||
while (DatumOffset < DatumCount)
|
/* Store the datum to the caller buffer */
|
||||||
{
|
|
||||||
FieldDatumByteOffset += ObjDesc->CommonField.AccessByteWidth;
|
|
||||||
|
|
||||||
/*
|
AcpiExSetBufferDatum (MergedDatum, Buffer, BufferLength,
|
||||||
* If the field is aligned on a byte boundary, we don't want
|
ObjDesc->CommonField.AccessByteWidth, BufferDatumOffset);
|
||||||
* to perform a final read, since this would potentially read
|
|
||||||
* past the end of the region.
|
return_ACPI_STATUS (AE_OK);
|
||||||
*
|
}
|
||||||
* We could just split the aligned and non-aligned cases since the
|
|
||||||
* aligned case is so very simple, but this would require more code.
|
/* Special handling for the last datum to ignore extra bits */
|
||||||
*/
|
|
||||||
if ((ObjDesc->CommonField.StartFieldBitOffset != 0) ||
|
if ((i >= (DatumCount -1)) &&
|
||||||
((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
|
(ObjDesc->CommonField.EndFieldValidBits))
|
||||||
(DatumOffset < (DatumCount -1))))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Get the next raw datum, it contains some or all bits
|
* This is the last iteration of the loop. We need to clear
|
||||||
* of the current field datum
|
* any unused bits (bits that are not part of this field) before
|
||||||
|
* we store the final merged datum into the caller buffer.
|
||||||
*/
|
*/
|
||||||
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
ThisRawDatum &=
|
||||||
&ThisRawDatum, ACPI_READ);
|
ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.EndFieldValidBits);
|
||||||
if (ACPI_FAILURE (Status))
|
|
||||||
{
|
|
||||||
return_ACPI_STATUS (Status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -968,51 +997,51 @@ AcpiExExtractFromField (
|
|||||||
{
|
{
|
||||||
/* Field is not skewed and we can just copy the datum */
|
/* Field is not skewed and we can just copy the datum */
|
||||||
|
|
||||||
MergedDatum = PreviousRawDatum;
|
AcpiExSetBufferDatum (ThisRawDatum, Buffer, BufferLength,
|
||||||
|
ObjDesc->CommonField.AccessByteWidth, BufferDatumOffset);
|
||||||
|
BufferDatumOffset++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/* Not aligned -- on the first iteration, just save the datum */
|
||||||
* Put together the appropriate bits of the two raw data to make a
|
|
||||||
* single complete field datum
|
|
||||||
*
|
|
||||||
* 1) Normalize the first datum down to bit 0
|
|
||||||
*/
|
|
||||||
MergedDatum = (PreviousRawDatum >> ObjDesc->CommonField.StartFieldBitOffset);
|
|
||||||
|
|
||||||
/* 2) Insert the second datum "above" the first datum */
|
if (i != 0)
|
||||||
|
|
||||||
MergedDatum |= (ThisRawDatum << ObjDesc->CommonField.DatumValidBits);
|
|
||||||
|
|
||||||
if ((DatumOffset >= (DatumCount -1)))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is the last iteration of the loop. We need to clear
|
* Put together the appropriate bits of the two raw data to make a
|
||||||
* any unused bits (bits that are not part of this field) that
|
* single complete field datum
|
||||||
* came from the last raw datum before we store the final
|
*
|
||||||
* merged datum into the caller buffer.
|
* 1) Normalize the first datum down to bit 0
|
||||||
*/
|
*/
|
||||||
if (ObjDesc->CommonField.EndBufferValidBits)
|
MergedDatum = (PreviousRawDatum >> ObjDesc->CommonField.StartFieldBitOffset);
|
||||||
{
|
|
||||||
MergedDatum &=
|
/* 2) Insert the second datum "above" the first datum */
|
||||||
ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.EndBufferValidBits);
|
|
||||||
}
|
MergedDatum |= (ThisRawDatum << ObjDesc->CommonField.DatumValidBits);
|
||||||
|
|
||||||
|
AcpiExSetBufferDatum (MergedDatum, Buffer, BufferLength,
|
||||||
|
ObjDesc->CommonField.AccessByteWidth, BufferDatumOffset);
|
||||||
|
BufferDatumOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the raw datum that was just acquired since it may contain bits
|
||||||
|
* of the *next* field datum
|
||||||
|
*/
|
||||||
|
PreviousRawDatum = ThisRawDatum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
FieldDatumByteOffset += ObjDesc->CommonField.AccessByteWidth;
|
||||||
* Store the merged field datum in the caller's buffer, according to
|
}
|
||||||
* the granularity of the field (size of each datum).
|
|
||||||
*/
|
|
||||||
AcpiExSetBufferDatum (MergedDatum, Buffer, BufferLength,
|
|
||||||
ObjDesc->CommonField.AccessByteWidth, DatumOffset);
|
|
||||||
|
|
||||||
/*
|
/* For non-aligned case, there is one last datum to insert */
|
||||||
* Save the raw datum that was just acquired since it may contain bits
|
|
||||||
* of the *next* field datum. Update offsets
|
if (ObjDesc->CommonField.StartFieldBitOffset != 0)
|
||||||
*/
|
{
|
||||||
PreviousRawDatum = ThisRawDatum;
|
MergedDatum = (ThisRawDatum >> ObjDesc->CommonField.StartFieldBitOffset);
|
||||||
DatumOffset++;
|
|
||||||
|
AcpiExSetBufferDatum (MergedDatum, Buffer, BufferLength,
|
||||||
|
ObjDesc->CommonField.AccessByteWidth, BufferDatumOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_ACPI_STATUS (AE_OK);
|
return_ACPI_STATUS (AE_OK);
|
||||||
@ -1058,21 +1087,28 @@ AcpiExInsertIntoField (
|
|||||||
* larger than the field, this typically happens when an integer is
|
* larger than the field, this typically happens when an integer is
|
||||||
* written to a field that is actually smaller than an integer.
|
* written to a field that is actually smaller than an integer.
|
||||||
*/
|
*/
|
||||||
ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength);
|
ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES (
|
||||||
|
ObjDesc->CommonField.BitLength);
|
||||||
if (BufferLength < ByteFieldLength)
|
if (BufferLength < ByteFieldLength)
|
||||||
{
|
{
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Buffer length %X too small for field %X\n",
|
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||||
|
"Buffer length %X too small for field %X\n",
|
||||||
BufferLength, ByteFieldLength));
|
BufferLength, ByteFieldLength));
|
||||||
|
|
||||||
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
|
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES (
|
||||||
|
ObjDesc->CommonField.StartFieldBitOffset +
|
||||||
|
ObjDesc->CommonField.BitLength);
|
||||||
|
|
||||||
/* Convert byte count to datum count, round up if necessary */
|
/* Convert byte count to datum count, round up if necessary */
|
||||||
|
|
||||||
DatumCount = ACPI_ROUND_UP_TO (ByteFieldLength, ObjDesc->CommonField.AccessByteWidth);
|
DatumCount = ACPI_ROUND_UP_TO (ByteFieldLength,
|
||||||
|
ObjDesc->CommonField.AccessByteWidth);
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||||
"ByteLen=%X, DatumLen=%X, ByteGran=%X\n",
|
"Bytes %X, Datums %X, ByteGran %X\n",
|
||||||
ByteFieldLength, DatumCount, ObjDesc->CommonField.AccessByteWidth));
|
ByteFieldLength, DatumCount, ObjDesc->CommonField.AccessByteWidth));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1125,6 +1161,10 @@ AcpiExInsertIntoField (
|
|||||||
return_ACPI_STATUS (Status);
|
return_ACPI_STATUS (Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We just wrote the first datum */
|
||||||
|
|
||||||
|
DatumOffset++;
|
||||||
|
|
||||||
/* If the entire field fits within one datum, we are done. */
|
/* If the entire field fits within one datum, we are done. */
|
||||||
|
|
||||||
if ((DatumCount == 1) &&
|
if ((DatumCount == 1) &&
|
||||||
@ -1146,7 +1186,6 @@ AcpiExInsertIntoField (
|
|||||||
*/
|
*/
|
||||||
while (DatumOffset < DatumCount)
|
while (DatumOffset < DatumCount)
|
||||||
{
|
{
|
||||||
DatumOffset++;
|
|
||||||
FieldDatumByteOffset += ObjDesc->CommonField.AccessByteWidth;
|
FieldDatumByteOffset += ObjDesc->CommonField.AccessByteWidth;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1180,37 +1219,37 @@ AcpiExInsertIntoField (
|
|||||||
* a datum boundary. Update Rule must be applied to the bits outside
|
* a datum boundary. Update Rule must be applied to the bits outside
|
||||||
* the field.
|
* the field.
|
||||||
*/
|
*/
|
||||||
if (DatumOffset == DatumCount)
|
DatumOffset++;
|
||||||
|
if ((DatumOffset == DatumCount) &&
|
||||||
|
(ObjDesc->CommonField.EndFieldValidBits))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If there are dangling non-aligned bits, perform one more merged write
|
* If there are dangling non-aligned bits, perform one more merged write
|
||||||
* Else - field is aligned at the end, no need for any more writes
|
* Else - field is aligned at the end, no need for any more writes
|
||||||
*/
|
*/
|
||||||
if (ObjDesc->CommonField.EndFieldValidBits)
|
|
||||||
|
/*
|
||||||
|
* Part3:
|
||||||
|
* This is the last datum and the field does not end on a datum boundary.
|
||||||
|
* Build the partial datum and write with the update rule.
|
||||||
|
*
|
||||||
|
* Mask off the unused bits above (after) the end-of-field
|
||||||
|
*/
|
||||||
|
Mask = ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.EndFieldValidBits);
|
||||||
|
MergedDatum &= Mask;
|
||||||
|
|
||||||
|
/* Write the last datum with the update rule */
|
||||||
|
|
||||||
|
Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, MergedDatum,
|
||||||
|
FieldDatumByteOffset);
|
||||||
|
if (ACPI_FAILURE (Status))
|
||||||
{
|
{
|
||||||
/*
|
return_ACPI_STATUS (Status);
|
||||||
* Part3:
|
|
||||||
* This is the last datum and the field does not end on a datum boundary.
|
|
||||||
* Build the partial datum and write with the update rule.
|
|
||||||
*
|
|
||||||
* Mask off the unused bits above (after) the end-of-field
|
|
||||||
*/
|
|
||||||
Mask = ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.EndFieldValidBits);
|
|
||||||
MergedDatum &= Mask;
|
|
||||||
|
|
||||||
/* Write the last datum with the update rule */
|
|
||||||
|
|
||||||
Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, MergedDatum,
|
|
||||||
FieldDatumByteOffset);
|
|
||||||
if (ACPI_FAILURE (Status))
|
|
||||||
{
|
|
||||||
return_ACPI_STATUS (Status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Normal case -- write the completed datum */
|
/* Normal (aligned) case -- write the completed datum */
|
||||||
|
|
||||||
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
|
||||||
&MergedDatum, ACPI_WRITE);
|
&MergedDatum, ACPI_WRITE);
|
||||||
|
Loading…
Reference in New Issue
Block a user