📄 exfldio.c
字号:
AcpiUtGetRegionName (RgnDesc->Region.SpaceId), RgnDesc->Region.SpaceId, ObjDesc->CommonField.AccessByteWidth, ObjDesc->CommonField.BaseByteOffset, FieldDatumByteOffset, ACPI_CAST_PTR (void, Address))); /* Invoke the appropriate AddressSpace/OpRegion handler */ Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, Address, ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_IMPLEMENTED) { ACPI_ERROR ((AE_INFO, "Region %s(%X) not implemented", AcpiUtGetRegionName (RgnDesc->Region.SpaceId), RgnDesc->Region.SpaceId)); } else if (Status == AE_NOT_EXIST) { ACPI_ERROR ((AE_INFO, "Region %s(%X) has no handler", 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. * ******************************************************************************/static BOOLEANAcpiExRegisterOverflow ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_INTEGER Value){ if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE) { /* * The field is large enough to hold the maximum integer, so we can * never overflow it. */ return (FALSE); } if (Value >= ((ACPI_INTEGER) 1 << ObjDesc->CommonField.BitLength)) { /* * The Value is larger than the maximum value that can fit into * the register. */ return (TRUE); } /* The Value will fit into the field with no truncation */ 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) * ******************************************************************************/static ACPI_STATUSAcpiExFieldDatumIo ( ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, ACPI_INTEGER *Value, UINT32 ReadWrite){ ACPI_STATUS Status; ACPI_INTEGER LocalValue; ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset); if (ReadWrite == ACPI_READ) { if (!Value) { LocalValue = 0; /* To support reads without saving return value */ Value = &LocalValue; } /* Clear the entire return buffer first, [Very Important!] */ *Value = 0; } /* * The four types of fields are: * * BufferField - Read/write from/to a Buffer * RegionField - Read/write from/to a Operation Region. * BankField - Write to a Bank Register, then read/write from/to an * OperationRegion * IndexField - Write to an Index Register, then read/write from/to a * Data Register */ switch (ACPI_GET_OBJECT_TYPE (ObjDesc)) { case ACPI_TYPE_BUFFER_FIELD: /* * If the BufferField arguments have not been previously evaluated, * evaluate them now and save the results. */ 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. */ ACPI_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. */ ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer + ObjDesc->BufferField.BaseByteOffset + FieldDatumByteOffset, Value, ObjDesc->CommonField.AccessByteWidth); } Status = AE_OK; break; case ACPI_TYPE_LOCAL_BANK_FIELD: /* * Ensure that the BankValue is not beyond the capacity of * the register */ if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj, (ACPI_INTEGER) ObjDesc->BankField.Value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } /* * For BankFields, we must write the BankValue to the BankRegister * (itself a RegionField) before we can access the data. */ Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj, &ObjDesc->BankField.Value, sizeof (ObjDesc->BankField.Value)); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Now that the Bank has been selected, fall through to the * RegionField case and write the datum to the Operation Region */ /*lint -fallthrough */ case ACPI_TYPE_LOCAL_REGION_FIELD: /* * For simple RegionFields, we just directly access the owning * Operation Region. */ Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value, ReadWrite); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* * Ensure that the IndexValue is not beyond the capacity of * the register */ if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj, (ACPI_INTEGER) ObjDesc->IndexField.Value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } /* Write the index value to the IndexRegister (itself a RegionField) */ FieldDatumByteOffset += ObjDesc->IndexField.Value; ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Write to Index Register: Value %8.8X\n", FieldDatumByteOffset)); Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj, &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)); if (ReadWrite == ACPI_READ) { /* Read the datum from the DataRegister */ Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj, Value, sizeof (ACPI_INTEGER)); } else { /* Write the datum to the DataRegister */ Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj, Value, sizeof (ACPI_INTEGER)); } break; default: ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %X", ACPI_GET_OBJECT_TYPE (ObjDesc))); 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, Width %d\n", ACPI_FORMAT_UINT64 (*Value), ObjDesc->CommonField.AccessByteWidth)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", ACPI_FORMAT_UINT64 (*Value), ObjDesc->CommonField.AccessByteWidth)); } } return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiExWriteWithUpdateRule * * PARAMETERS: ObjDesc - Field to be written * Mask - bitmask within field datum * FieldValue - Value to write * FieldDatumByteOffset - Offset of datum within field * * RETURN: Status * * DESCRIPTION: Apply the field update rule to a field write * ******************************************************************************/ACPI_STATUSAcpiExWriteWithUpdateRule ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_INTEGER Mask, ACPI_INTEGER FieldValue, UINT32 FieldDatumByteOffset){ ACPI_STATUS Status = AE_OK; ACPI_INTEGER MergedValue; ACPI_INTEGER CurrentValue; ACPI_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_INTEGER_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 << (ACPI_MUL_8 (sizeof (Mask)) - ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 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); if (ACPI_FAILURE (Status)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -