//.........这里部分代码省略.........
switch (obj_desc->common.type) {
case ACPI_TYPE_INTEGER:
/* No conversion necessary */
*result_desc = obj_desc;
return_ACPI_STATUS(AE_OK);
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
/* Note: Takes advantage of common buffer/string fields */
pointer = obj_desc->buffer.pointer;
count = obj_desc->buffer.length;
break;
default:
return_ACPI_STATUS(AE_TYPE);
}
/*
* Convert the buffer/string to an integer. Note that both buffers and
* strings are treated as raw data - we don't convert ascii to hex for
* strings.
*
* There are two terminating conditions for the loop:
* 1) The size of an integer has been reached, or
* 2) The end of the buffer or string has been reached
*/
result = 0;
/* String conversion is different than Buffer conversion */
switch (obj_desc->common.type) {
case ACPI_TYPE_STRING:
/*
* Convert string to an integer - for most cases, the string must be
* hexadecimal as per the ACPI specification. The only exception (as
* of ACPI 3.0) is that the to_integer() operator allows both decimal
* and hexadecimal strings (hex prefixed with "0x").
*/
status = acpi_ut_strtoul64((char *)pointer, flags, &result);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
break;
case ACPI_TYPE_BUFFER:
/* Check for zero-length buffer */
if (!count) {
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
/* Transfer no more than an integer's worth of data */
if (count > acpi_gbl_integer_byte_width) {
count = acpi_gbl_integer_byte_width;
}
/*
* Convert buffer to an integer - we simply grab enough raw data
* from the buffer to fill an integer
*/
for (i = 0; i < count; i++) {
/*
* Get next byte and shift it into the Result.
* Little endian is used, meaning that the first byte of the buffer
* is the LSB of the integer
*/
result |= (((u64) pointer[i]) << (i * 8));
}
break;
default:
/* No other types can get here */
break;
}
/* Create a new integer */
return_desc = acpi_ut_create_integer_object(result);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(result)));
/* Save the Result */
acpi_ex_truncate_for32bit_table(return_desc);
*result_desc = return_desc;
return_ACPI_STATUS(AE_OK);
}
//.........这里部分代码省略.........
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
/* Note: Takes advantage of common buffer/string fields */
Pointer = ObjDesc->Buffer.Pointer;
Count = ObjDesc->Buffer.Length;
break;
default:
return_ACPI_STATUS (AE_TYPE);
}
/*
* Convert the buffer/string to an integer. Note that both buffers and
* strings are treated as raw data - we don't convert ascii to hex for
* strings.
*
* There are two terminating conditions for the loop:
* 1) The size of an integer has been reached, or
* 2) The end of the buffer or string has been reached
*/
Result = 0;
/* String conversion is different than Buffer conversion */
switch (ObjDesc->Common.Type)
{
case ACPI_TYPE_STRING:
/*
* Convert string to an integer - for most cases, the string must be
* hexadecimal as per the ACPI specification. The only exception (as
* of ACPI 3.0) is that the ToInteger() operator allows both decimal
* and hexadecimal strings (hex prefixed with "0x").
*/
Status = AcpiUtStrtoul64 ((char *) Pointer, Flags, &Result);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
break;
case ACPI_TYPE_BUFFER:
/* Check for zero-length buffer */
if (!Count)
{
return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
}
/* Transfer no more than an integer's worth of data */
if (Count > AcpiGbl_IntegerByteWidth)
{
Count = AcpiGbl_IntegerByteWidth;
}
/*
* Convert buffer to an integer - we simply grab enough raw data
* from the buffer to fill an integer
*/
for (i = 0; i < Count; i++)
{
/*
* Get next byte and shift it into the Result.
* Little endian is used, meaning that the first byte of the buffer
* is the LSB of the integer
*/
Result |= (((UINT64) Pointer[i]) << (i * 8));
}
break;
default:
/* No other types can get here */
break;
}
/* Create a new integer */
ReturnDesc = AcpiUtCreateIntegerObject (Result);
if (!ReturnDesc)
{
return_ACPI_STATUS (AE_NO_MEMORY);
}
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
ACPI_FORMAT_UINT64 (Result)));
/* Save the Result */
(void) AcpiExTruncateFor32bitTable (ReturnDesc);
*ResultDesc = ReturnDesc;
return_ACPI_STATUS (AE_OK);
}
//.........这里部分代码省略.........
/* Truncate value if we are executing from a 32-bit ACPI table */
#ifndef ACPI_NO_METHOD_EXECUTION
(void) AcpiExTruncateFor32bitTable (ObjDesc);
#endif
break;
case AML_REVISION_OP:
ObjDesc->Integer.Value = ACPI_CA_VERSION;
break;
default:
ACPI_ERROR ((AE_INFO,
"Unknown constant opcode 0x%X", Opcode));
Status = AE_AML_OPERAND_TYPE;
break;
}
break;
case AML_TYPE_LITERAL:
ObjDesc->Integer.Value = Op->Common.Value.Integer;
#ifndef ACPI_NO_METHOD_EXECUTION
if (AcpiExTruncateFor32bitTable (ObjDesc))
{
/* Warn if we found a 64-bit constant in a 32-bit table */
ACPI_WARNING ((AE_INFO,
"Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
(UINT32) ObjDesc->Integer.Value));
}
#endif
break;
default:
ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
OpInfo->Type));
Status = AE_AML_OPERAND_TYPE;
break;
}
break;
case ACPI_TYPE_STRING:
ObjDesc->String.Pointer = Op->Common.Value.String;
ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Op->Common.Value.String);
/*
* The string is contained in the ACPI table, don't ever try
* to delete it
*/
ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
break;
case ACPI_TYPE_METHOD:
break;
case ACPI_TYPE_LOCAL_REFERENCE:
switch (OpInfo->Type)
ACPI_STATUS
AcpiExOpcode_6A_0T_1R (
ACPI_WALK_STATE *WalkState)
{
ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
ACPI_STATUS Status = AE_OK;
UINT64 Index;
ACPI_OPERAND_OBJECT *ThisElement;
ACPI_FUNCTION_TRACE_STR (ExOpcode_6A_0T_1R,
AcpiPsGetOpcodeName (WalkState->Opcode));
switch (WalkState->Opcode)
{
case AML_MATCH_OP:
/*
* Match (SearchPkg[0], MatchOp1[1], MatchObj1[2],
* MatchOp2[3], MatchObj2[4], StartIndex[5])
*/
/* Validate both Match Term Operators (MTR, MEQ, etc.) */
if ((Operand[1]->Integer.Value > MAX_MATCH_OPERATOR) ||
(Operand[3]->Integer.Value > MAX_MATCH_OPERATOR))
{
ACPI_ERROR ((AE_INFO, "Match operator out of range"));
Status = AE_AML_OPERAND_VALUE;
goto Cleanup;
}
/* Get the package StartIndex, validate against the package length */
Index = Operand[5]->Integer.Value;
if (Index >= Operand[0]->Package.Count)
{
ACPI_ERROR ((AE_INFO,
"Index (0x%8.8X%8.8X) beyond package end (0x%X)",
ACPI_FORMAT_UINT64 (Index), Operand[0]->Package.Count));
Status = AE_AML_PACKAGE_LIMIT;
goto Cleanup;
}
/* Create an integer for the return value */
/* Default return value is ACPI_UINT64_MAX if no match found */
ReturnDesc = AcpiUtCreateIntegerObject (ACPI_UINT64_MAX);
if (!ReturnDesc)
{
Status = AE_NO_MEMORY;
goto Cleanup;
}
/*
* Examine each element until a match is found. Both match conditions
* must be satisfied for a match to occur. Within the loop,
* "continue" signifies that the current element does not match
* and the next should be examined.
*
* Upon finding a match, the loop will terminate via "break" at
* the bottom. If it terminates "normally", MatchValue will be
* ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
* match was found.
*/
for ( ; Index < Operand[0]->Package.Count; Index++)
{
/* Get the current package element */
ThisElement = Operand[0]->Package.Elements[Index];
/* Treat any uninitialized (NULL) elements as non-matching */
if (!ThisElement)
{
continue;
}
/*
* Both match conditions must be satisfied. Execution of a continue
* (proceed to next iteration of enclosing for loop) signifies a
* non-match.
*/
if (!AcpiExDoMatch ((UINT32) Operand[1]->Integer.Value,
ThisElement, Operand[2]))
{
continue;
}
if (!AcpiExDoMatch ((UINT32) Operand[3]->Integer.Value,
ThisElement, Operand[4]))
{
continue;
}
/* Match found: Index is the return value */
ReturnDesc->Integer.Value = Index;
//.........这里部分代码省略.........
//.........这里部分代码省略.........
MapLength = (ACPI_SIZE)
((MemInfo->Address + MemInfo->Length) - Address);
/*
* If mapping the entire remaining portion of the region will cross
* a page boundary, just map up to the page boundary, do not cross.
* On some systems, crossing a page boundary while mapping regions
* can cause warnings if the pages have different attributes
* due to resource management.
*
* This has the added benefit of constraining a single mapping to
* one page, which is similar to the original code that used a 4k
* maximum window.
*/
PageBoundaryMapLength = (ACPI_SIZE)
(ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address);
if (PageBoundaryMapLength == 0)
{
PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE;
}
if (MapLength > PageBoundaryMapLength)
{
MapLength = PageBoundaryMapLength;
}
/* Create a new mapping starting at the address given */
MemInfo->MappedLogicalAddress = AcpiOsMapMemory (Address, MapLength);
if (!MemInfo->MappedLogicalAddress)
{
ACPI_ERROR ((AE_INFO,
"Could not map memory at 0x%8.8X%8.8X, size %u",
ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength));
MemInfo->MappedLength = 0;
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Save the physical address and mapping size */
MemInfo->MappedPhysicalAddress = Address;
MemInfo->MappedLength = MapLength;
}
/*
* Generate a logical pointer corresponding to the address we want to
* access
*/
LogicalAddrPtr = MemInfo->MappedLogicalAddress +
((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress);
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
/*
* Perform the memory read or write
*
* Note: For machines that do not support non-aligned transfers, the target
* address was checked for alignment above. We do not attempt to break the
* transfer up into smaller (byte-size) chunks because the AML specifically
* asked for a transfer width that the hardware may require.
*/
switch (Function)
{
case ACPI_READ:
static void acpi_tb_validate_fadt(void)
{
char *name;
struct acpi_generic_address *address64;
u8 length;
u32 i;
/*
* Check for FACS and DSDT address mismatches. An address mismatch between
* the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
* DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
*/
if (acpi_gbl_FADT.facs &&
(acpi_gbl_FADT.Xfacs != (u64)acpi_gbl_FADT.facs)) {
ACPI_BIOS_WARNING((AE_INFO,
"32/64X FACS address mismatch in FADT - "
"0x%8.8X/0x%8.8X%8.8X, using 32",
acpi_gbl_FADT.facs,
ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs)));
acpi_gbl_FADT.Xfacs = (u64)acpi_gbl_FADT.facs;
}
if (acpi_gbl_FADT.dsdt &&
(acpi_gbl_FADT.Xdsdt != (u64)acpi_gbl_FADT.dsdt)) {
ACPI_BIOS_WARNING((AE_INFO,
"32/64X DSDT address mismatch in FADT - "
"0x%8.8X/0x%8.8X%8.8X, using 32",
acpi_gbl_FADT.dsdt,
ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt)));
acpi_gbl_FADT.Xdsdt = (u64)acpi_gbl_FADT.dsdt;
}
/* If Hardware Reduced flag is set, we are all done */
if (acpi_gbl_reduced_hardware) {
return;
}
/* Examine all of the 64-bit extended address fields (X fields) */
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
/*
* Generate pointer to the 64-bit address, get the register
* length (width) and the register name
*/
address64 = ACPI_ADD_PTR(struct acpi_generic_address,
&acpi_gbl_FADT,
fadt_info_table[i].address64);
length =
*ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
fadt_info_table[i].length);
name = fadt_info_table[i].name;
/*
* For each extended field, check for length mismatch between the
* legacy length field and the corresponding 64-bit X length field.
*/
if (address64->address &&
(address64->bit_width != ACPI_MUL_8(length))) {
ACPI_BIOS_WARNING((AE_INFO,
"32/64X length mismatch in FADT/%s: %u/%u",
name, ACPI_MUL_8(length),
address64->bit_width));
}
if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
/*
* Field is required (Pm1a_event, Pm1a_control, pm_timer).
* Both the address and length must be non-zero.
*/
if (!address64->address || !length) {
ACPI_BIOS_ERROR((AE_INFO,
"Required FADT field %s has zero address and/or length: "
"0x%8.8X%8.8X/0x%X",
name,
ACPI_FORMAT_UINT64(address64->
address),
length));
}
} else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) {
/*
* Field is optional (Pm2_control, GPE0, GPE1) AND has its own
* length field. If present, both the address and length must
* be valid.
*/
if ((address64->address && !length) ||
(!address64->address && length)) {
ACPI_BIOS_WARNING((AE_INFO,
"Optional FADT field %s has zero address or length: "
"0x%8.8X%8.8X/0x%X",
name,
ACPI_FORMAT_UINT64
(address64->address),
length));
}
}
}
}
开发者ID:AiWinters,项目名称:linux,代码行数:100,代码来源:tbfadt.c
示例7: AcpiDsEvalTableRegionOperands
ACPI_STATUS
AcpiDsEvalTableRegionOperands (
ACPI_WALK_STATE *WalkState,
ACPI_PARSE_OBJECT *Op)
{
ACPI_STATUS Status;
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_OPERAND_OBJECT **Operand;
ACPI_NAMESPACE_NODE *Node;
ACPI_PARSE_OBJECT *NextOp;
ACPI_TABLE_HEADER *Table;
UINT32 TableIndex;
ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op);
/*
* This is where we evaluate the Signature string, OemId string,
* and OemTableId string of the Data Table Region declaration
*/
Node = Op->Common.Node;
/* NextOp points to Signature string op */
NextOp = Op->Common.Value.Arg;
/*
* Evaluate/create the Signature string, OemId string,
* and OemTableId string operands
*/
Status = AcpiDsCreateOperands (WalkState, NextOp);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
Operand = &WalkState->Operands[0];
/*
* Resolve the Signature string, OemId string,
* and OemTableId string operands
*/
Status = AcpiExResolveOperands (
Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState);
if (ACPI_FAILURE (Status))
{
goto Cleanup;
}
/* Find the ACPI table */
Status = AcpiTbFindTable (
Operand[0]->String.Pointer,
Operand[1]->String.Pointer,
Operand[2]->String.Pointer, &TableIndex);
if (ACPI_FAILURE (Status))
{
if (Status == AE_NOT_FOUND)
{
ACPI_ERROR ((AE_INFO,
"ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
Operand[0]->String.Pointer,
Operand[1]->String.Pointer,
Operand[2]->String.Pointer));
}
goto Cleanup;
}
Status = AcpiGetTableByIndex (TableIndex, &Table);
if (ACPI_FAILURE (Status))
{
goto Cleanup;
}
ObjDesc = AcpiNsGetAttachedObject (Node);
if (!ObjDesc)
{
Status = AE_NOT_EXIST;
goto Cleanup;
}
ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table);
ObjDesc->Region.Length = Table->Length;
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
ObjDesc, ACPI_FORMAT_UINT64 (ObjDesc->Region.Address),
ObjDesc->Region.Length));
/* Now the address and length are valid for this opregion */
ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID;
Cleanup:
AcpiUtRemoveReference (Operand[0]);
AcpiUtRemoveReference (Operand[1]);
AcpiUtRemoveReference (Operand[2]);
return_ACPI_STATUS (Status);
}
acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
union acpi_parse_object *op)
{
acpi_status status;
union acpi_operand_object *obj_desc;
union acpi_operand_object *operand_desc;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
/*
* This is where we evaluate the address and length fields of the
* op_region declaration
*/
node = op->common.node;
/* next_op points to the op that holds the space_ID */
next_op = op->common.value.arg;
/* next_op points to address op */
next_op = next_op->common.next;
/* Evaluate/create the address and length operands */
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Resolve the length and address operands to numbers */
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
* Get the length operand and save it
* (at Top of stack)
*/
operand_desc = walk_state->operands[walk_state->num_operands - 1];
obj_desc->region.length = (u32) operand_desc->integer.value;
acpi_ut_remove_reference(operand_desc);
/*
* Get the address and save it
* (at top of stack - 1)
*/
operand_desc = walk_state->operands[walk_state->num_operands - 2];
obj_desc->region.address = (acpi_physical_address)
operand_desc->integer.value;
acpi_ut_remove_reference(operand_desc);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_UINT64(obj_desc->region.address),
obj_desc->region.length));
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
return_ACPI_STATUS(status);
}
acpi_status
acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
u64 mask,
u64 field_value, u32 field_datum_byte_offset)
{
acpi_status status = AE_OK;
u64 merged_value;
u64 current_value;
ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
/* Start with the new bits */
merged_value = field_value;
/* If the mask is all ones, we don't need to worry about the update rule */
if (mask != ACPI_UINT64_MAX) {
/* Decode the update rule */
switch (obj_desc->common_field.
field_flags & 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(obj_desc->common_field.
access_byte_width))) != 0) {
/*
* Read the current contents of the byte/word/dword containing
* the field, and merge with the new field value.
*/
status =
acpi_ex_field_datum_io(obj_desc,
field_datum_byte_offset,
¤t_value,
ACPI_READ);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
merged_value |= (current_value & ~mask);
}
break;
case AML_FIELD_UPDATE_WRITE_AS_ONES:
/* Set positions outside the field to all ones */
merged_value |= ~mask;
break;
case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
/* Set positions outside the field to all zeros */
merged_value &= mask;
break;
default:
ACPI_ERROR((AE_INFO,
"Unknown UpdateRule value: 0x%X",
(obj_desc->common_field.
field_flags &
AML_FIELD_UPDATE_RULE_MASK)));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
}
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),
field_datum_byte_offset,
obj_desc->common_field.access_byte_width,
ACPI_FORMAT_UINT64(field_value),
ACPI_FORMAT_UINT64(merged_value)));
/* Write the merged value */
status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
&merged_value, ACPI_WRITE);
return_ACPI_STATUS(status);
}
开发者ID:0-T-0,项目名称:ps4-linux,代码行数:88,代码来源:exfldio.c
示例13: acpi_ex_field_datum_io
//.........这里部分代码省略.........
value));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Now that the Bank has been selected, fall through to the
* region_field case and write the datum to the Operation Region
*/
/*lint -fallthrough */
case ACPI_TYPE_LOCAL_REGION_FIELD:
/*
* For simple region_fields, we just directly access the owning
* Operation Region.
*/
status =
acpi_ex_access_region(obj_desc, field_datum_byte_offset,
value, read_write);
break;
case ACPI_TYPE_LOCAL_INDEX_FIELD:
/*
* Ensure that the index_value is not beyond the capacity of
* the register
*/
if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
(u64) obj_desc->index_field.
value)) {
return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
}
/* Write the index value to the index_register (itself a region_field) */
field_datum_byte_offset += obj_desc->index_field.value;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Write to Index Register: Value %8.8X\n",
field_datum_byte_offset));
status =
acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
&field_datum_byte_offset,
sizeof(field_datum_byte_offset));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (read_write == ACPI_READ) {
/* Read the datum from the data_register */
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Read from Data Register\n"));
status =
acpi_ex_extract_from_field(obj_desc->index_field.
data_obj, value,
sizeof(u64));
} else {
/* Write the datum to the data_register */
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Write to Data Register: Value %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(*value)));
status =
acpi_ex_insert_into_field(obj_desc->index_field.
data_obj, value,
sizeof(u64));
}
break;
default:
ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u",
obj_desc->common.type));
status = AE_AML_INTERNAL;
break;
}
if (ACPI_SUCCESS(status)) {
if (read_write == ACPI_READ) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Value Read %8.8X%8.8X, Width %u\n",
ACPI_FORMAT_UINT64(*value),
obj_desc->common_field.
access_byte_width));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Value Written %8.8X%8.8X, Width %u\n",
ACPI_FORMAT_UINT64(*value),
obj_desc->common_field.
access_byte_width));
}
}
return_ACPI_STATUS(status);
}
acpi_status
acpi_ex_access_region(union acpi_operand_object *obj_desc,
u32 field_datum_byte_offset, u64 *value, u32 function)
{
acpi_status status;
union acpi_operand_object *rgn_desc;
u32 region_offset;
ACPI_FUNCTION_TRACE(ex_access_region);
/*
* Ensure that the region operands are fully evaluated and verify
* the validity of the request
*/
status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
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
*/
rgn_desc = obj_desc->common_field.region_obj;
region_offset =
obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
if ((function & ACPI_IO_MASK) == ACPI_READ) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
" Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
acpi_ut_get_region_name(rgn_desc->region.
space_id),
rgn_desc->region.space_id,
obj_desc->common_field.access_byte_width,
obj_desc->common_field.base_byte_offset,
field_datum_byte_offset,
ACPI_FORMAT_UINT64(rgn_desc->region.address +
region_offset)));
/* Invoke the appropriate address_space/op_region handler */
status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
function, region_offset,
ACPI_MUL_8(obj_desc->
common_field.
access_byte_width),
value);
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_IMPLEMENTED) {
ACPI_ERROR((AE_INFO,
"Region %s (ID=%u) not implemented",
acpi_ut_get_region_name(rgn_desc->region.
space_id),
rgn_desc->region.space_id));
} else if (status == AE_NOT_EXIST) {
ACPI_ERROR((AE_INFO,
"Region %s (ID=%u) has no handler",
acpi_ut_get_region_name(rgn_desc->region.
space_id),
rgn_desc->region.space_id));
}
}
return_ACPI_STATUS(status);
}
开发者ID:0-T-0,项目名称:ps4-linux,代码行数:74,代码来源:exfldio.c
示例15: AcpiExOpcode_1A_1T_1R
//.........这里部分代码省略.........
Digit >>= 4;
/* Next power of 10 */
PowerOfTen *= 10;
}
break;
case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */
ReturnDesc->Integer.Value = 0;
Digit = Operand[0]->Integer.Value;
/* Each BCD digit is one nybble wide */
for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
{
(void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32);
/*
* Insert the BCD digit that resides in the
* remainder from above
*/
ReturnDesc->Integer.Value |=
(((UINT64) Temp32) << ACPI_MUL_4 (i));
}
/* Overflow if there is any data left in Digit */
if (Digit > 0)
{
ACPI_ERROR ((AE_INFO,
"Integer too large to convert to BCD: 0x%8.8X%8.8X",
ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value)));
Status = AE_AML_NUMERIC_OVERFLOW;
goto Cleanup;
}
break;
case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */
/*
* This op is a little strange because the internal return value is
* different than the return value stored in the result descriptor
* (There are really two return values)
*/
if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode)
{
/*
* This means that the object does not exist in the namespace,
* return FALSE
*/
ReturnDesc->Integer.Value = 0;
goto Cleanup;
}
/* Get the object reference, store it, and remove our reference */
Status = AcpiExGetObjectReference (Operand[0],
&ReturnDesc2, WalkState);
if (ACPI_FAILURE (Status))
{
goto Cleanup;
}
Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState);
AcpiUtRemoveReference (ReturnDesc2);
请发表评论