diff options
Diffstat (limited to 'sys/contrib/dev/acpica/exfldio.c')
-rw-r--r-- | sys/contrib/dev/acpica/exfldio.c | 729 |
1 files changed, 415 insertions, 314 deletions
diff --git a/sys/contrib/dev/acpica/exfldio.c b/sys/contrib/dev/acpica/exfldio.c index c10b336..7e60ea8 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: 66 $ + * $Revision: 75 $ * *****************************************************************************/ @@ -132,20 +132,21 @@ /******************************************************************************* * - * FUNCTION: AcpiExSetupField + * FUNCTION: AcpiExSetupRegion * - * PARAMETERS: *ObjDesc - Field to be read or written - * FieldDatumByteOffset - Current offset into the field + * PARAMETERS: *ObjDesc - Field to be read or written + * FieldDatumByteOffset - Byte offset of this datum within the + * parent field * * RETURN: Status * * DESCRIPTION: Common processing for AcpiExExtractFromField and - * AcpiExInsertIntoField + * AcpiExInsertIntoField. Initialize the * ******************************************************************************/ ACPI_STATUS -AcpiExSetupField ( +AcpiExSetupRegion ( ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset) { @@ -153,7 +154,7 @@ AcpiExSetupField ( ACPI_OPERAND_OBJECT *RgnDesc; - FUNCTION_TRACE_U32 ("ExSetupField", FieldDatumByteOffset); + FUNCTION_TRACE_U32 ("ExSetupRegion", FieldDatumByteOffset); RgnDesc = ObjDesc->CommonField.RegionObj; @@ -171,7 +172,6 @@ AcpiExSetupField ( */ if (!(RgnDesc->Region.Flags & AOPOBJ_DATA_VALID)) { - Status = AcpiDsGetRegionArguments (RgnDesc); if (ACPI_FAILURE (Status)) { @@ -184,9 +184,9 @@ AcpiExSetupField ( * 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 (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth) { @@ -205,7 +205,7 @@ AcpiExSetupField ( * exceeds region length, indicate an error */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Field base+offset+width %X+%X+%X exceeds region size (%X bytes) field=%p region=%p\n", + "Field Base+Offset+Width %X+%X+%X exceeds region size (%X bytes) field=%p region=%p\n", ObjDesc->CommonField.BaseByteOffset, FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth, RgnDesc->Region.Length, ObjDesc, RgnDesc)); @@ -219,121 +219,427 @@ AcpiExSetupField ( /******************************************************************************* * - * FUNCTION: AcpiExReadFieldDatum + * FUNCTION: AcpiExAccessRegion * - * PARAMETERS: *ObjDesc - Field to be read - * *Value - Where to store value (must be 32 bits) + * PARAMETERS: *ObjDesc - Field to be read + * FieldDatumByteOffset - Byte offset of this datum within the + * parent field + * *Value - Where to store value (must be 32 bits) + * ReadWrite - Read or Write flag * * RETURN: Status * - * DESCRIPTION: Retrieve the value of the given field + * DESCRIPTION: Read or Write a single field datum to an Operation Region. * ******************************************************************************/ ACPI_STATUS -AcpiExReadFieldDatum ( +AcpiExAccessRegion ( ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, - UINT32 *Value) + ACPI_INTEGER *Value, + UINT32 ReadWrite) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *RgnDesc; ACPI_PHYSICAL_ADDRESS Address; - UINT32 LocalValue; - FUNCTION_TRACE_U32 ("ExReadFieldDatum", FieldDatumByteOffset); + FUNCTION_TRACE ("AcpiExAccessRegion"); - if (!Value) + /* + * The physical address of this field datum is: + * + * 1) The base of the region, plus + * 2) The base offset of the field, plus + * 3) The current offset into the field + */ + RgnDesc = ObjDesc->CommonField.RegionObj; + Address = RgnDesc->Region.Address + + ObjDesc->CommonField.BaseByteOffset + + FieldDatumByteOffset; + + if (ReadWrite == ACPI_READ) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); + } + else { - LocalValue = 0; - Value = &LocalValue; /* support reads without saving value */ + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]")); } - /* Clear the entire return buffer first, [Very Important!] */ + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD, + " Region[%s-%X] Width %X Base:Off %X:%X at %8.8X%8.8X\n", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId, + ObjDesc->CommonField.AccessBitWidth, + ObjDesc->CommonField.BaseByteOffset, + FieldDatumByteOffset, + HIDWORD (Address), LODWORD (Address))); - *Value = 0; + /* Invoke the appropriate AddressSpace/OpRegion handler */ + + Status = AcpiEvAddressSpaceDispatch (RgnDesc, ReadWrite, + Address, ObjDesc->CommonField.AccessBitWidth, Value); + + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_IMPLEMENTED) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Region %s(%X) not implemented\n", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId)); + } + + else if (Status == AE_NOT_EXIST) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Region %s(%X) has no handler\n", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId)); + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExRegisterOverflow + * + * PARAMETERS: *ObjDesc - Register(Field) to be written + * Value - Value to be stored + * + * RETURN: TRUE if value overflows the field, FALSE otherwise + * + * DESCRIPTION: Check if a value is out of range of the field being written. + * Used to check if the values written to Index and Bank registers + * are out of range. Normally, the value is simply truncated + * to fit the field, but this case is most likely a serious + * coding error in the ASL. + * + ******************************************************************************/ + +BOOLEAN +AcpiExRegisterOverflow ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_INTEGER Value) +{ /* - * BufferFields - Read from a Buffer - * Other Fields - Read from a Operation Region. + * Is the Value larger than the maximum value that can fit into + * the field? + */ + if (Value >= (ACPI_INTEGER) (1 << ObjDesc->CommonField.BitLength)) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExFieldDatumIo + * + * PARAMETERS: *ObjDesc - Field to be read + * FieldDatumByteOffset - Byte offset of this datum within the + * parent field + * *Value - Where to store value (must be 64 bits) + * ReadWrite - Read or Write flag + * + * RETURN: Status + * + * DESCRIPTION: Read or Write a single datum of a field. The FieldType is + * demultiplexed here to handle the different types of fields + * (BufferField, RegionField, IndexField, BankField) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExFieldDatumIo ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 FieldDatumByteOffset, + ACPI_INTEGER *Value, + UINT32 ReadWrite) +{ + ACPI_STATUS Status; + ACPI_INTEGER LocalValue; + + + FUNCTION_TRACE_U32 ("ExFieldDatumIo", FieldDatumByteOffset); + + + if (ReadWrite == ACPI_READ) + { + if (!Value) + { + LocalValue = 0; + Value = &LocalValue; /* To support reads without saving return value */ + } + + /* Clear the entire return buffer first, [Very Important!] */ + + *Value = 0; + } + + /* + * The four types of fields are: + * + * BufferFields - Read/write from/to a Buffer + * RegionFields - Read/write from/to a Operation Region. + * BankFields - Write to a Bank Register, then read/write from/to an OpRegion + * IndexFields - Write to an Index Register, then read/write from/to a Data Register */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_BUFFER_FIELD: - /* - * For BufferFields, we only need to copy the data from the - * source buffer. Length is the field width in bytes. + * If the BufferField arguments have not been previously evaluated, + * evaluate them now and save the results. */ - MEMCPY (Value, (ObjDesc->BufferField.BufferObj)->Buffer.Pointer - + ObjDesc->BufferField.BaseByteOffset + FieldDatumByteOffset, - ObjDesc->CommonField.AccessByteWidth); + if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) + { + Status = AcpiDsGetBufferFieldArguments (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + if (ReadWrite == ACPI_READ) + { + /* + * Copy the data from the source buffer. + * Length is the field width in bytes. + */ + MEMCPY (Value, (ObjDesc->BufferField.BufferObj)->Buffer.Pointer + + ObjDesc->BufferField.BaseByteOffset + + FieldDatumByteOffset, + ObjDesc->CommonField.AccessByteWidth); + } + else + { + /* + * Copy the data to the target buffer. + * Length is the field width in bytes. + */ + MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer + + ObjDesc->BufferField.BaseByteOffset + + FieldDatumByteOffset, + Value, ObjDesc->CommonField.AccessByteWidth); + } + Status = AE_OK; break; - case INTERNAL_TYPE_REGION_FIELD: case INTERNAL_TYPE_BANK_FIELD: + /* Ensure that the BankValue is not beyond the capacity of the register */ + + if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj, + ObjDesc->BankField.Value)) + { + return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); + } + /* - * For other fields, we need to go through an Operation Region - * (Only types that will get here are RegionFields and BankFields) + * For BankFields, we must write the BankValue to the BankRegister + * (itself a RegionField) before we can access the data. */ - Status = AcpiExSetupField (ObjDesc, FieldDatumByteOffset); + Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj, + &ObjDesc->BankField.Value, + sizeof (ObjDesc->BankField.Value)); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* - * The physical address of this field datum is: - * - * 1) The base of the region, plus - * 2) The base offset of the field, plus - * 3) The current offset into the field + * Now that the Bank has been selected, fall through to the + * RegionField case and write the datum to the Operation Region */ - RgnDesc = ObjDesc->CommonField.RegionObj; - Address = RgnDesc->Region.Address + ObjDesc->CommonField.BaseByteOffset + - FieldDatumByteOffset; - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Region %s(%X) width %X base:off %X:%X at %8.8X%8.8X\n", - AcpiUtGetRegionName (RgnDesc->Region.SpaceId), - RgnDesc->Region.SpaceId, ObjDesc->CommonField.AccessBitWidth, - ObjDesc->CommonField.BaseByteOffset, FieldDatumByteOffset, - HIDWORD(Address), LODWORD(Address))); + /* No break; ! */ - /* Invoke the appropriate AddressSpace/OpRegion handler */ - Status = AcpiEvAddressSpaceDispatch (RgnDesc, ACPI_READ_ADR_SPACE, - Address, ObjDesc->CommonField.AccessBitWidth, Value); - if (Status == AE_NOT_IMPLEMENTED) + case INTERNAL_TYPE_REGION_FIELD: + /* + * For simple RegionFields, we just directly access the owning + * Operation Region. + */ + Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset); + if (ACPI_FAILURE (Status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) not implemented\n", - AcpiUtGetRegionName (RgnDesc->Region.SpaceId), - RgnDesc->Region.SpaceId)); + return_ACPI_STATUS (Status); } - else if (Status == AE_NOT_EXIST) + Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value, + ReadWrite); + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + + /* Ensure that the IndexValue is not beyond the capacity of the register */ + + if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj, + ObjDesc->IndexField.Value)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) has no handler\n", - AcpiUtGetRegionName (RgnDesc->Region.SpaceId), - RgnDesc->Region.SpaceId)); + return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); + } + + /* Write the index value to the IndexRegister (itself a RegionField) */ + + Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj, + &ObjDesc->IndexField.Value, + sizeof (ObjDesc->IndexField.Value)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (ReadWrite == ACPI_READ) + { + /* Read the datum from the DataRegister */ + + Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj, + Value, ObjDesc->CommonField.AccessByteWidth); + } + else + { + /* Write the datum to the Data register */ + + Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj, + Value, ObjDesc->CommonField.AccessByteWidth); } break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n", + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n", ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type))); Status = AE_AML_INTERNAL; break; } + if (ACPI_SUCCESS (Status)) + { + if (ReadWrite == ACPI_READ) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read=%8.8X%8.8X\n", + HIDWORD(*Value), LODWORD(*Value))); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written=%8.8X%8.8X\n", + HIDWORD(*Value), LODWORD(*Value))); + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteWithUpdateRule + * + * PARAMETERS: *ObjDesc - Field to be set + * Value - Value to store + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteWithUpdateRule ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_INTEGER Mask, + ACPI_INTEGER FieldValue, + UINT32 FieldDatumByteOffset) +{ + ACPI_STATUS Status = AE_OK; + ACPI_INTEGER MergedValue; + ACPI_INTEGER CurrentValue; + + + FUNCTION_TRACE_U32 ("ExWriteWithUpdateRule", Mask); + + + /* Start with the new bits */ + + MergedValue = FieldValue; + + /* If the mask is all ones, we don't need to worry about the update rule */ + + if (Mask != ACPI_UINT32_MAX) + { + /* Decode the update rule */ + + switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK) + { + case AML_FIELD_UPDATE_PRESERVE: + /* + * Check if update rule needs to be applied (not if mask is all + * ones) The left shift drops the bits we want to ignore. + */ + if ((~Mask << (sizeof (Mask) * 8 - + ObjDesc->CommonField.AccessBitWidth)) != 0) + { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &CurrentValue, ACPI_READ); + MergedValue |= (CurrentValue & ~Mask); + } + break; + + case AML_FIELD_UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + MergedValue |= ~Mask; + break; + + case AML_FIELD_UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + MergedValue &= Mask; + break; + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "WriteWithUpdateRule: Unknown UpdateRule setting: %x\n", + (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK))); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + break; + } + } + + /* Write the merged value */ + + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &MergedValue, ACPI_WRITE); - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Returned value=%08X \n", *Value)); + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Mask %8.8X%8.8X DatumOffset %X Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", + HIDWORD(Mask), LODWORD(Mask), + FieldDatumByteOffset, + HIDWORD(FieldValue), LODWORD(FieldValue), + HIDWORD(MergedValue),LODWORD(MergedValue))); return_ACPI_STATUS (Status); } @@ -343,22 +649,22 @@ AcpiExReadFieldDatum ( * * FUNCTION: AcpiExGetBufferDatum * - * PARAMETERS: MergedDatum - Value to store - * Buffer - Receiving buffer - * ByteGranularity - 1/2/4 Granularity of the field + * PARAMETERS: Datum - Where the Datum is returned + * Buffer - Raw field buffer + * ByteGranularity - 1/2/4/8 Granularity of the field * (aka Datum Size) * Offset - Datum offset into the buffer * * RETURN: none * - * DESCRIPTION: Store the merged datum to the buffer according to the + * DESCRIPTION: Get a datum from the buffer according to the buffer field * byte granularity * ******************************************************************************/ -static void +void AcpiExGetBufferDatum( - UINT32 *Datum, + ACPI_INTEGER *Datum, void *Buffer, UINT32 ByteGranularity, UINT32 Offset) @@ -380,6 +686,10 @@ AcpiExGetBufferDatum( case ACPI_FIELD_DWORD_GRANULARITY: MOVE_UNALIGNED32_TO_32 (Datum, &(((UINT32 *) Buffer) [Offset])); break; + + case ACPI_FIELD_QWORD_GRANULARITY: + MOVE_UNALIGNED64_TO_64 (Datum, &(((UINT64 *) Buffer) [Offset])); + break; } } @@ -390,7 +700,7 @@ AcpiExGetBufferDatum( * * PARAMETERS: MergedDatum - Value to store * Buffer - Receiving buffer - * ByteGranularity - 1/2/4 Granularity of the field + * ByteGranularity - 1/2/4/8 Granularity of the field * (aka Datum Size) * Offset - Datum offset into the buffer * @@ -401,9 +711,9 @@ AcpiExGetBufferDatum( * ******************************************************************************/ -static void +void AcpiExSetBufferDatum ( - UINT32 MergedDatum, + ACPI_INTEGER MergedDatum, void *Buffer, UINT32 ByteGranularity, UINT32 Offset) @@ -425,6 +735,10 @@ AcpiExSetBufferDatum ( case ACPI_FIELD_DWORD_GRANULARITY: MOVE_UNALIGNED32_TO_32 (&(((UINT32 *) Buffer)[Offset]), &MergedDatum); break; + + case ACPI_FIELD_QWORD_GRANULARITY: + MOVE_UNALIGNED64_TO_64 (&(((UINT64 *) Buffer)[Offset]), &MergedDatum); + break; } } @@ -451,9 +765,9 @@ AcpiExExtractFromField ( ACPI_STATUS Status; UINT32 FieldDatumByteOffset; UINT32 DatumOffset; - UINT32 PreviousRawDatum; - UINT32 ThisRawDatum = 0; - UINT32 MergedDatum = 0; + ACPI_INTEGER PreviousRawDatum; + ACPI_INTEGER ThisRawDatum = 0; + ACPI_INTEGER MergedDatum = 0; UINT32 ByteFieldLength; UINT32 DatumCount; @@ -467,7 +781,8 @@ AcpiExExtractFromField ( ByteFieldLength = ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength); if (ByteFieldLength > BufferLength) { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Field size %X (bytes) too large for buffer (%X)\n", + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Field size %X (bytes) too large for buffer (%X)\n", ByteFieldLength, BufferLength)); return_ACPI_STATUS (AE_BUFFER_OVERFLOW); @@ -475,7 +790,8 @@ AcpiExExtractFromField ( /* Convert field byte count to datum count, round up if necessary */ - DatumCount = ROUND_UP_TO (ByteFieldLength, ObjDesc->CommonField.AccessByteWidth); + DatumCount = ROUND_UP_TO (ByteFieldLength, + ObjDesc->CommonField.AccessByteWidth); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ByteLen=%x, DatumLen=%x, BitGran=%x, ByteGran=%x\n", @@ -494,7 +810,8 @@ AcpiExExtractFromField ( FieldDatumByteOffset = 0; DatumOffset= 0; - Status = AcpiExReadFieldDatum (ObjDesc, FieldDatumByteOffset, &PreviousRawDatum); + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &PreviousRawDatum, ACPI_READ); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); @@ -504,7 +821,7 @@ AcpiExExtractFromField ( /* We might actually be done if the request fits in one datum */ if ((DatumCount == 1) && - (ObjDesc->CommonField.AccessFlags & AFIELD_SINGLE_DATUM)) + (ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM)) { /* 1) Shift the valid data bits down to start at bit 0 */ @@ -537,18 +854,19 @@ AcpiExExtractFromField ( * to perform a final read, since this would potentially read * past the end of the region. * - * TBD: [Investigate] It may make more sense to just split the aligned - * and non-aligned cases since the aligned case is so very simple, + * 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.StartFieldBitOffset != 0) || - ((ObjDesc->CommonField.StartFieldBitOffset == 0) && + if ((ObjDesc->CommonField.StartFieldBitOffset != 0) || + ((ObjDesc->CommonField.StartFieldBitOffset == 0) && (DatumOffset < (DatumCount -1)))) { /* * Get the next raw datum, it contains some or all bits * of the current field datum */ - Status = AcpiExReadFieldDatum (ObjDesc, FieldDatumByteOffset, &ThisRawDatum); + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &ThisRawDatum, ACPI_READ); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); @@ -564,7 +882,6 @@ AcpiExExtractFromField ( MergedDatum = PreviousRawDatum; } - else { /* @@ -599,8 +916,8 @@ AcpiExExtractFromField ( * Store the merged field datum in the caller's buffer, according to * the granularity of the field (size of each datum). */ - AcpiExSetBufferDatum (MergedDatum, Buffer, ObjDesc->CommonField.AccessByteWidth, - DatumOffset); + AcpiExSetBufferDatum (MergedDatum, Buffer, + ObjDesc->CommonField.AccessByteWidth, DatumOffset); /* * Save the raw datum that was just acquired since it may contain bits @@ -616,218 +933,6 @@ AcpiExExtractFromField ( /******************************************************************************* * - * FUNCTION: AcpiExWriteFieldDatum - * - * PARAMETERS: *ObjDesc - Field to be set - * Value - Value to store - * - * RETURN: Status - * - * DESCRIPTION: Store the value into the given field - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiExWriteFieldDatum ( - ACPI_OPERAND_OBJECT *ObjDesc, - UINT32 FieldDatumByteOffset, - UINT32 Value) -{ - ACPI_STATUS Status = AE_OK; - ACPI_OPERAND_OBJECT *RgnDesc = NULL; - ACPI_PHYSICAL_ADDRESS Address; - - - FUNCTION_TRACE_U32 ("ExWriteFieldDatum", FieldDatumByteOffset); - - - /* - * BufferFields - Read from a Buffer - * Other Fields - Read from a Operation Region. - */ - switch (ObjDesc->Common.Type) - { - case ACPI_TYPE_BUFFER_FIELD: - - /* - * For BufferFields, we only need to copy the data to the - * target buffer. Length is the field width in bytes. - */ - MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer - + ObjDesc->BufferField.BaseByteOffset + FieldDatumByteOffset, - &Value, ObjDesc->CommonField.AccessByteWidth); - Status = AE_OK; - break; - - - case INTERNAL_TYPE_REGION_FIELD: - case INTERNAL_TYPE_BANK_FIELD: - - /* - * For other fields, we need to go through an Operation Region - * (Only types that will get here are RegionFields and BankFields) - */ - Status = AcpiExSetupField (ObjDesc, FieldDatumByteOffset); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* - * The physical address of this field datum is: - * - * 1) The base of the region, plus - * 2) The base offset of the field, plus - * 3) The current offset into the field - */ - RgnDesc = ObjDesc->CommonField.RegionObj; - Address = RgnDesc->Region.Address + - ObjDesc->CommonField.BaseByteOffset + - FieldDatumByteOffset; - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Store %X in Region %s(%X) at %8.8X%8.8X width %X\n", - Value, AcpiUtGetRegionName (RgnDesc->Region.SpaceId), - RgnDesc->Region.SpaceId, HIDWORD(Address), LODWORD(Address), - ObjDesc->CommonField.AccessBitWidth)); - - /* Invoke the appropriate AddressSpace/OpRegion handler */ - - Status = AcpiEvAddressSpaceDispatch (RgnDesc, ACPI_WRITE_ADR_SPACE, - Address, ObjDesc->CommonField.AccessBitWidth, &Value); - - if (Status == AE_NOT_IMPLEMENTED) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "**** Region type %s(%X) not implemented\n", - AcpiUtGetRegionName (RgnDesc->Region.SpaceId), - RgnDesc->Region.SpaceId)); - } - - else if (Status == AE_NOT_EXIST) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "**** Region type %s(%X) does not have a handler\n", - AcpiUtGetRegionName (RgnDesc->Region.SpaceId), - RgnDesc->Region.SpaceId)); - } - - break; - - - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, wrong source type - %s\n", - ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type))); - Status = AE_AML_INTERNAL; - break; - } - - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value written=%08X \n", Value)); - return_ACPI_STATUS (Status); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiExWriteFieldDatumWithUpdateRule - * - * PARAMETERS: *ObjDesc - Field to be set - * Value - Value to store - * - * RETURN: Status - * - * DESCRIPTION: Apply the field update rule to a field write - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiExWriteFieldDatumWithUpdateRule ( - ACPI_OPERAND_OBJECT *ObjDesc, - UINT32 Mask, - UINT32 FieldValue, - UINT32 FieldDatumByteOffset) -{ - ACPI_STATUS Status = AE_OK; - UINT32 MergedValue; - UINT32 CurrentValue; - - - FUNCTION_TRACE ("ExWriteFieldDatumWithUpdateRule"); - - - /* Start with the new bits */ - - MergedValue = FieldValue; - - /* If the mask is all ones, we don't need to worry about the update rule */ - - if (Mask != ACPI_UINT32_MAX) - { - /* Decode the update rule */ - - switch (ObjDesc->CommonField.UpdateRule) - { - case UPDATE_PRESERVE: - /* - * Check if update rule needs to be applied (not if mask is all - * ones) The left shift drops the bits we want to ignore. - */ - if ((~Mask << (sizeof (Mask) * 8 - - ObjDesc->CommonField.AccessBitWidth)) != 0) - { - /* - * Read the current contents of the byte/word/dword containing - * the field, and merge with the new field value. - */ - Status = AcpiExReadFieldDatum (ObjDesc, FieldDatumByteOffset, - &CurrentValue); - MergedValue |= (CurrentValue & ~Mask); - } - break; - - - case UPDATE_WRITE_AS_ONES: - - /* Set positions outside the field to all ones */ - - MergedValue |= ~Mask; - break; - - - case UPDATE_WRITE_AS_ZEROS: - - /* Set positions outside the field to all zeros */ - - MergedValue &= Mask; - break; - - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "WriteWithUpdateRule: Unknown UpdateRule setting: %x\n", - ObjDesc->CommonField.UpdateRule)); - return_ACPI_STATUS (AE_AML_OPERAND_VALUE); - break; - } - } - - - /* Write the merged value */ - - Status = AcpiExWriteFieldDatum (ObjDesc, FieldDatumByteOffset, - MergedValue); - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Mask %X DatumOffset %X Value %X, MergedValue %X\n", - Mask, FieldDatumByteOffset, FieldValue, MergedValue)); - - return_ACPI_STATUS (Status); -} - - -/******************************************************************************* - * * FUNCTION: AcpiExInsertIntoField * * PARAMETERS: *ObjDesc - Field to be set @@ -848,10 +953,10 @@ AcpiExInsertIntoField ( ACPI_STATUS Status; UINT32 FieldDatumByteOffset; UINT32 DatumOffset; - UINT32 Mask; - UINT32 MergedDatum; - UINT32 PreviousRawDatum; - UINT32 ThisRawDatum; + ACPI_INTEGER Mask; + ACPI_INTEGER MergedDatum; + ACPI_INTEGER PreviousRawDatum; + ACPI_INTEGER ThisRawDatum; UINT32 ByteFieldLength; UINT32 DatumCount; @@ -871,8 +976,6 @@ AcpiExInsertIntoField ( ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer length %X too small for field %X\n", BufferLength, ByteFieldLength)); - /* TBD: Need a better error code */ - return_ACPI_STATUS (AE_BUFFER_OVERFLOW); } @@ -913,7 +1016,7 @@ AcpiExInsertIntoField ( /* If the field fits in one datum, may need to mask upper bits */ - if ((ObjDesc->CommonField.AccessFlags & AFIELD_SINGLE_DATUM) && + if ((ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM) && ObjDesc->CommonField.EndFieldValidBits) { /* There are bits above the field, mask them off also */ @@ -928,7 +1031,7 @@ AcpiExInsertIntoField ( /* Apply the update rule (if necessary) and write the datum to the field */ - Status = AcpiExWriteFieldDatumWithUpdateRule (ObjDesc, Mask, MergedDatum, + Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, MergedDatum, FieldDatumByteOffset); if (ACPI_FAILURE (Status)) { @@ -938,7 +1041,7 @@ AcpiExInsertIntoField ( /* If the entire field fits within one datum, we are done. */ if ((DatumCount == 1) && - (ObjDesc->CommonField.AccessFlags & AFIELD_SINGLE_DATUM)) + (ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM)) { return_ACPI_STATUS (AE_OK); } @@ -978,7 +1081,6 @@ AcpiExInsertIntoField ( (PreviousRawDatum >> ObjDesc->CommonField.DatumValidBits) | (ThisRawDatum << ObjDesc->CommonField.StartFieldBitOffset); } - else { /* Field began aligned on datum boundary */ @@ -1011,21 +1113,20 @@ AcpiExInsertIntoField ( /* Write the last datum with the update rule */ - Status = AcpiExWriteFieldDatumWithUpdateRule (ObjDesc, Mask, - MergedDatum, FieldDatumByteOffset); + Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask, MergedDatum, + FieldDatumByteOffset); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } } - else { /* Normal case -- write the completed datum */ - Status = AcpiExWriteFieldDatum (ObjDesc, - FieldDatumByteOffset, MergedDatum); + Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset, + &MergedDatum, ACPI_WRITE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); |