aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/dev/acpica/exfldio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/exfldio.c')
-rw-r--r--sys/contrib/dev/acpica/exfldio.c196
1 files changed, 126 insertions, 70 deletions
diff --git a/sys/contrib/dev/acpica/exfldio.c b/sys/contrib/dev/acpica/exfldio.c
index efd1decdd464..1a8631bfafb9 100644
--- a/sys/contrib/dev/acpica/exfldio.c
+++ b/sys/contrib/dev/acpica/exfldio.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: exfldio - Aml Field I/O
- * $Revision: 1.116 $
+ * $Revision: 1.128 $
*
*****************************************************************************/
@@ -9,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -172,7 +172,7 @@ AcpiExSetupRegion (
ACPI_OPERAND_OBJECT *RgnDesc;
- ACPI_FUNCTION_TRACE_U32 ("ExSetupRegion", FieldDatumByteOffset);
+ ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
RgnDesc = ObjDesc->CommonField.RegionObj;
@@ -181,7 +181,7 @@ AcpiExSetupRegion (
if (ACPI_GET_OBJECT_TYPE (RgnDesc) != ACPI_TYPE_REGION)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
+ ACPI_ERROR ((AE_INFO, "Needed Region, found type %X (%s)",
ACPI_GET_OBJECT_TYPE (RgnDesc),
AcpiUtGetObjectTypeName (RgnDesc)));
@@ -201,6 +201,17 @@ AcpiExSetupRegion (
}
}
+ /* Exit if Address/Length have been disallowed by the host OS */
+
+ if (RgnDesc->Common.Flags & AOPOBJ_INVALID)
+ {
+ return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS);
+ }
+
+ /*
+ * Exit now for SMBus address space, it has a non-linear address space
+ * and the request cannot be directly validated
+ */
if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)
{
/* SMBus has a non-linear address space */
@@ -227,9 +238,10 @@ AcpiExSetupRegion (
* length of one field datum (access width) must fit within the region.
* (Region length is specified in bytes)
*/
- if (RgnDesc->Region.Length < (ObjDesc->CommonField.BaseByteOffset +
- FieldDatumByteOffset +
- ObjDesc->CommonField.AccessByteWidth))
+ if (RgnDesc->Region.Length <
+ (ObjDesc->CommonField.BaseByteOffset +
+ FieldDatumByteOffset +
+ ObjDesc->CommonField.AccessByteWidth))
{
if (AcpiGbl_EnableInterpreterSlack)
{
@@ -239,10 +251,10 @@ AcpiExSetupRegion (
* access width boundary.
*/
if (ACPI_ROUND_UP (RgnDesc->Region.Length,
- ObjDesc->CommonField.AccessByteWidth) >=
+ ObjDesc->CommonField.AccessByteWidth) >=
(ObjDesc->CommonField.BaseByteOffset +
- (ACPI_NATIVE_UINT) ObjDesc->CommonField.AccessByteWidth +
- FieldDatumByteOffset))
+ (ACPI_NATIVE_UINT) ObjDesc->CommonField.AccessByteWidth +
+ FieldDatumByteOffset))
{
return_ACPI_STATUS (AE_OK);
}
@@ -255,8 +267,8 @@ AcpiExSetupRegion (
* than the region itself. For example, a region of length one
* byte, and a field with Dword access specified.
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
+ ACPI_ERROR ((AE_INFO,
+ "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)",
AcpiUtGetNodeName (ObjDesc->CommonField.Node),
ObjDesc->CommonField.AccessByteWidth,
AcpiUtGetNodeName (RgnDesc->Region.Node),
@@ -267,8 +279,8 @@ AcpiExSetupRegion (
* Offset rounded up to next multiple of field width
* exceeds region length, indicate an 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",
+ ACPI_ERROR ((AE_INFO,
+ "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)",
AcpiUtGetNodeName (ObjDesc->CommonField.Node),
ObjDesc->CommonField.BaseByteOffset,
FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
@@ -312,7 +324,7 @@ AcpiExAccessRegion (
ACPI_PHYSICAL_ADDRESS Address;
- ACPI_FUNCTION_TRACE ("ExAccessRegion");
+ ACPI_FUNCTION_TRACE (ExAccessRegion);
/*
@@ -347,13 +359,13 @@ AcpiExAccessRegion (
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
- " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
+ " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
RgnDesc->Region.SpaceId,
ObjDesc->CommonField.AccessByteWidth,
ObjDesc->CommonField.BaseByteOffset,
FieldDatumByteOffset,
- ACPI_FORMAT_UINT64 (Address)));
+ (void *) Address));
/* Invoke the appropriate AddressSpace/OpRegion handler */
@@ -365,15 +377,15 @@ AcpiExAccessRegion (
{
if (Status == AE_NOT_IMPLEMENTED)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Region %s(%X) not implemented\n",
+ ACPI_ERROR ((AE_INFO,
+ "Region %s(%X) not implemented",
AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
RgnDesc->Region.SpaceId));
}
else if (Status == AE_NOT_EXIST)
{
- ACPI_REPORT_ERROR ((
- "Region %s(%X) has no handler\n",
+ ACPI_ERROR ((AE_INFO,
+ "Region %s(%X) has no handler",
AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
RgnDesc->Region.SpaceId));
}
@@ -459,7 +471,7 @@ AcpiExFieldDatumIo (
ACPI_INTEGER LocalValue;
- ACPI_FUNCTION_TRACE_U32 ("ExFieldDatumIo", FieldDatumByteOffset);
+ ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
if (ReadWrite == ACPI_READ)
@@ -522,9 +534,9 @@ AcpiExFieldDatumIo (
* Length is the field width in bytes.
*/
ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
- ObjDesc->BufferField.BaseByteOffset +
- FieldDatumByteOffset,
- Value, ObjDesc->CommonField.AccessByteWidth);
+ ObjDesc->BufferField.BaseByteOffset +
+ FieldDatumByteOffset,
+ Value, ObjDesc->CommonField.AccessByteWidth);
}
Status = AE_OK;
@@ -538,7 +550,7 @@ AcpiExFieldDatumIo (
* the register
*/
if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
- (ACPI_INTEGER) ObjDesc->BankField.Value))
+ (ACPI_INTEGER) ObjDesc->BankField.Value))
{
return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
}
@@ -548,8 +560,8 @@ AcpiExFieldDatumIo (
* (itself a RegionField) before we can access the data.
*/
Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
- &ObjDesc->BankField.Value,
- sizeof (ObjDesc->BankField.Value));
+ &ObjDesc->BankField.Value,
+ sizeof (ObjDesc->BankField.Value));
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
@@ -569,7 +581,7 @@ AcpiExFieldDatumIo (
* Operation Region.
*/
Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
- ReadWrite);
+ ReadWrite);
break;
@@ -581,7 +593,7 @@ AcpiExFieldDatumIo (
* the register
*/
if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
- (ACPI_INTEGER) ObjDesc->IndexField.Value))
+ (ACPI_INTEGER) ObjDesc->IndexField.Value))
{
return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
}
@@ -591,41 +603,40 @@ AcpiExFieldDatumIo (
FieldDatumByteOffset += ObjDesc->IndexField.Value;
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Write to Index Register: Value %8.8X\n",
- FieldDatumByteOffset));
+ "Write to Index Register: Value %8.8X\n",
+ FieldDatumByteOffset));
Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
- &FieldDatumByteOffset,
- sizeof (FieldDatumByteOffset));
+ &FieldDatumByteOffset,
+ sizeof (FieldDatumByteOffset));
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "I/O to Data Register: ValuePtr %p\n",
- Value));
+ "I/O to Data Register: ValuePtr %p\n", Value));
if (ReadWrite == ACPI_READ)
{
/* Read the datum from the DataRegister */
Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
- Value, sizeof (ACPI_INTEGER));
+ Value, sizeof (ACPI_INTEGER));
}
else
{
/* Write the datum to the DataRegister */
Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
- Value, sizeof (ACPI_INTEGER));
+ Value, sizeof (ACPI_INTEGER));
}
break;
default:
- ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
+ ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %X",
ACPI_GET_OBJECT_TYPE (ObjDesc)));
Status = AE_AML_INTERNAL;
break;
@@ -680,7 +691,7 @@ AcpiExWriteWithUpdateRule (
ACPI_INTEGER CurrentValue;
- ACPI_FUNCTION_TRACE_U32 ("ExWriteWithUpdateRule", Mask);
+ ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
/* Start with the new bits */
@@ -708,7 +719,7 @@ AcpiExWriteWithUpdateRule (
* the field, and merge with the new field value.
*/
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
- &CurrentValue, ACPI_READ);
+ &CurrentValue, ACPI_READ);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
@@ -734,8 +745,8 @@ AcpiExWriteWithUpdateRule (
default:
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "WriteWithUpdateRule: Unknown UpdateRule setting: %X\n",
+ ACPI_ERROR ((AE_INFO,
+ "Unknown UpdateRule value: %X",
(ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
}
@@ -752,7 +763,7 @@ AcpiExWriteWithUpdateRule (
/* Write the merged value */
Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
- &MergedValue, ACPI_WRITE);
+ &MergedValue, ACPI_WRITE);
return_ACPI_STATUS (Status);
}
@@ -789,16 +800,16 @@ AcpiExExtractFromField (
UINT32 i;
- ACPI_FUNCTION_TRACE ("ExExtractFromField");
+ ACPI_FUNCTION_TRACE (ExExtractFromField);
/* Validate target buffer and clear it */
- if (BufferLength < ACPI_ROUND_BITS_UP_TO_BYTES (
- ObjDesc->CommonField.BitLength))
+ if (BufferLength <
+ ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
+ ACPI_ERROR ((AE_INFO,
+ "Field size %X (bits) is too large for buffer (%X)",
ObjDesc->CommonField.BitLength, BufferLength));
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
@@ -832,17 +843,27 @@ AcpiExExtractFromField (
FieldOffset += ObjDesc->CommonField.AccessByteWidth;
Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
- &RawDatum, ACPI_READ);
+ &RawDatum, ACPI_READ);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
- /* Merge with previous datum if necessary */
-
- MergedDatum |= RawDatum <<
- (ObjDesc->CommonField.AccessBitWidth -
- ObjDesc->CommonField.StartFieldBitOffset);
+ /*
+ * Merge with previous datum if necessary.
+ *
+ * Note: Before the shift, check if the shift value will be larger than
+ * the integer size. If so, there is no need to perform the operation.
+ * 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)
+ {
+ MergedDatum |= RawDatum <<
+ (ObjDesc->CommonField.AccessBitWidth -
+ ObjDesc->CommonField.StartFieldBitOffset);
+ }
if (i == DatumCount)
{
@@ -853,7 +874,7 @@ AcpiExExtractFromField (
ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
- BufferLength - BufferOffset));
+ BufferLength - BufferOffset));
BufferOffset += ObjDesc->CommonField.AccessByteWidth;
MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
@@ -872,7 +893,7 @@ AcpiExExtractFromField (
ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
- BufferLength - BufferOffset));
+ BufferLength - BufferOffset));
return_ACPI_STATUS (AE_OK);
}
@@ -900,6 +921,7 @@ AcpiExInsertIntoField (
{
ACPI_STATUS Status;
ACPI_INTEGER Mask;
+ ACPI_INTEGER WidthMask;
ACPI_INTEGER MergedDatum;
ACPI_INTEGER RawDatum = 0;
UINT32 FieldOffset = 0;
@@ -910,26 +932,43 @@ AcpiExInsertIntoField (
UINT32 i;
- ACPI_FUNCTION_TRACE ("ExInsertIntoField");
+ ACPI_FUNCTION_TRACE (ExInsertIntoField);
/* Validate input buffer */
- if (BufferLength < ACPI_ROUND_BITS_UP_TO_BYTES (
- ObjDesc->CommonField.BitLength))
+ if (BufferLength <
+ ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Field size %X (bits) is too large for buffer (%X)\n",
+ ACPI_ERROR ((AE_INFO,
+ "Field size %X (bits) is too large for buffer (%X)",
ObjDesc->CommonField.BitLength, BufferLength));
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
}
+ /*
+ * 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)
+ {
+ WidthMask = ACPI_INTEGER_MAX;
+ }
+ else
+ {
+ WidthMask = ACPI_MASK_BITS_ABOVE (ObjDesc->CommonField.AccessBitWidth);
+ }
+
+ Mask = WidthMask &
+ ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
+
/* Compute the number of datums (access width data items) */
- Mask = ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
ObjDesc->CommonField.AccessBitWidth);
+
FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
ObjDesc->CommonField.StartFieldBitOffset,
ObjDesc->CommonField.AccessBitWidth);
@@ -938,7 +977,7 @@ AcpiExInsertIntoField (
ACPI_MEMCPY (&RawDatum, Buffer,
ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
- BufferLength - BufferOffset));
+ BufferLength - BufferOffset));
MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
@@ -956,13 +995,30 @@ AcpiExInsertIntoField (
return_ACPI_STATUS (Status);
}
- /* Start new output datum by merging with previous input datum */
-
FieldOffset += ObjDesc->CommonField.AccessByteWidth;
- MergedDatum = RawDatum >>
- (ObjDesc->CommonField.AccessBitWidth -
- ObjDesc->CommonField.StartFieldBitOffset);
- Mask = ACPI_INTEGER_MAX;
+
+ /*
+ * Start new output datum by merging with previous input datum
+ * if necessary.
+ *
+ * Note: Before the shift, check if the shift value will be larger than
+ * the integer size. If so, there is no need to perform the operation.
+ * 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)
+ {
+ MergedDatum = RawDatum >>
+ (ObjDesc->CommonField.AccessBitWidth -
+ ObjDesc->CommonField.StartFieldBitOffset);
+ }
+ else
+ {
+ MergedDatum = 0;
+ }
+
+ Mask = WidthMask;
if (i == DatumCount)
{