void AcpiDmNamestring ( char *Name) { UINT32 SegCount; if (!Name) { return; } /* Handle all Scope Prefix operators */ while (ACPI_IS_ROOT_PREFIX (ACPI_GET8 (Name)) || ACPI_IS_PARENT_PREFIX (ACPI_GET8 (Name))) { /* Append prefix character */ AcpiOsPrintf ("%1c", ACPI_GET8 (Name)); Name++; } switch (ACPI_GET8 (Name)) { case 0: SegCount = 0; break; case AML_DUAL_NAME_PREFIX: SegCount = 2; Name++; break; case AML_MULTI_NAME_PREFIX_OP: SegCount = (UINT32) ACPI_GET8 (Name + 1); Name += 2; break; default: SegCount = 1; break; } while (SegCount) { /* Append Name segment */ AcpiDmDumpName (*ACPI_CAST_PTR (UINT32, Name)); SegCount--; if (SegCount) { /* Not last name, append dot separator */ AcpiOsPrintf ("."); } Name += ACPI_NAME_SIZE; } }
char * acpi_ps_get_next_namestring ( struct acpi_parse_state *parser_state) { u8 *start = parser_state->aml; u8 *end = parser_state->aml; ACPI_FUNCTION_TRACE ("ps_get_next_namestring"); /* Handle multiple prefix characters */ while (acpi_ps_is_prefix_char (ACPI_GET8 (end))) { /* Include prefix '\\' or '^' */ end++; } /* Decode the path */ switch (ACPI_GET8 (end)) { case 0: /* null_name */ if (end == start) { start = NULL; } end++; break; case AML_DUAL_NAME_PREFIX: /* Two name segments */ end += 1 + (2 * ACPI_NAME_SIZE); break; case AML_MULTI_NAME_PREFIX_OP: /* Multiple name segments, 4 chars each */ end += 2 + ((acpi_size) ACPI_GET8 (end + 1) * ACPI_NAME_SIZE); break; default: /* Single name segment */ end += ACPI_NAME_SIZE; break; } parser_state->aml = (u8*) end; return_PTR ((char *) start); }
u32 acpi_ps_get_next_package_length ( struct acpi_parse_state *parser_state) { u32 encoded_length; u32 length = 0; ACPI_FUNCTION_TRACE ("ps_get_next_package_length"); encoded_length = (u32) ACPI_GET8 (parser_state->aml); parser_state->aml++; switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ { case 0: /* 1-byte encoding (bits 0-5) */ length = (encoded_length & 0x3F); break; case 1: /* 2-byte encoding (next byte + bits 0-3) */ length = ((ACPI_GET8 (parser_state->aml) << 04) | (encoded_length & 0x0F)); parser_state->aml++; break; case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */ length = ((ACPI_GET8 (parser_state->aml + 1) << 12) | (ACPI_GET8 (parser_state->aml) << 04) | (encoded_length & 0x0F)); parser_state->aml += 2; break; case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */ length = ((ACPI_GET8 (parser_state->aml + 2) << 20) | (ACPI_GET8 (parser_state->aml + 1) << 12) | (ACPI_GET8 (parser_state->aml) << 04) | (encoded_length & 0x0F)); parser_state->aml += 3; break; default: /* Can't get here, only 2 bits / 4 cases */ break; } return_VALUE (length); }
UINT16 AcpiPsPeekOpcode ( ACPI_PARSE_STATE *ParserState) { UINT8 *Aml; UINT16 Opcode; Aml = ParserState->Aml; Opcode = (UINT16) ACPI_GET8 (Aml); if (Opcode == AML_EXTENDED_OP_PREFIX) { /* Extended opcode, get the second opcode byte */ Aml++; Opcode = (UINT16) ((Opcode << 8) | ACPI_GET8 (Aml)); } return (Opcode); }
static void AcpiRsDumpDescriptor ( void *Resource, ACPI_RSDUMP_INFO *Table) { UINT8 *Target = NULL; UINT8 *PreviousTarget; const char *Name; UINT8 Count; /* First table entry must contain the table length (# of table entries) */ Count = Table->Offset; while (Count) { PreviousTarget = Target; Target = ACPI_ADD_PTR (UINT8, Resource, Table->Offset); Name = Table->Name; switch (Table->Opcode) { case ACPI_RSD_TITLE: /* * Optional resource title */ if (Table->Name) { AcpiOsPrintf ("%s Resource\n", Name); } break; /* Strings */ case ACPI_RSD_LITERAL: AcpiRsOutString (Name, ACPI_CAST_PTR (char, Table->Pointer)); break; case ACPI_RSD_STRING: AcpiRsOutString (Name, ACPI_CAST_PTR (char, Target)); break; /* Data items, 8/16/32/64 bit */ case ACPI_RSD_UINT8: if (Table->Pointer) { AcpiRsOutString (Name, Table->Pointer [*Target]); } else { AcpiRsOutInteger8 (Name, ACPI_GET8 (Target)); } break; case ACPI_RSD_UINT16: AcpiRsOutInteger16 (Name, ACPI_GET16 (Target)); break; case ACPI_RSD_UINT32: AcpiRsOutInteger32 (Name, ACPI_GET32 (Target)); break; case ACPI_RSD_UINT64: AcpiRsOutInteger64 (Name, ACPI_GET64 (Target)); break; /* Flags: 1-bit and 2-bit flags supported */ case ACPI_RSD_1BITFLAG: AcpiRsOutString (Name, Table->Pointer [*Target & 0x01]); break; case ACPI_RSD_2BITFLAG: AcpiRsOutString (Name, Table->Pointer [*Target & 0x03]); break; case ACPI_RSD_3BITFLAG: AcpiRsOutString (Name, Table->Pointer [*Target & 0x07]); break; case ACPI_RSD_SHORTLIST: /* * Short byte list (single line output) for DMA and IRQ resources * Note: The list length is obtained from the previous table entry */ if (PreviousTarget) { AcpiRsOutTitle (Name); AcpiRsDumpShortByteList (*PreviousTarget, Target); } break; case ACPI_RSD_SHORTLISTX: /* * Short byte list (single line output) for GPIO vendor data * Note: The list length is obtained from the previous table entry */ if (PreviousTarget) { AcpiRsOutTitle (Name); AcpiRsDumpShortByteList (*PreviousTarget, *(ACPI_CAST_INDIRECT_PTR (UINT8, Target))); } break; case ACPI_RSD_LONGLIST: /* * Long byte list for Vendor resource data * Note: The list length is obtained from the previous table entry */ if (PreviousTarget) { AcpiRsDumpByteList (ACPI_GET16 (PreviousTarget), Target); } break; case ACPI_RSD_DWORDLIST: /* * Dword list for Extended Interrupt resources * Note: The list length is obtained from the previous table entry */ if (PreviousTarget) { AcpiRsDumpDwordList (*PreviousTarget, ACPI_CAST_PTR (UINT32, Target)); } break; case ACPI_RSD_WORDLIST: /* * Word list for GPIO Pin Table * Note: The list length is obtained from the previous table entry */ if (PreviousTarget) { AcpiRsDumpWordList (*PreviousTarget, *(ACPI_CAST_INDIRECT_PTR (UINT16, Target))); } break; case ACPI_RSD_ADDRESS: /* * Common flags for all Address resources */ AcpiRsDumpAddressCommon (ACPI_CAST_PTR ( ACPI_RESOURCE_DATA, Target)); break; case ACPI_RSD_SOURCE: /* * Optional ResourceSource for Address resources */ AcpiRsDumpResourceSource (ACPI_CAST_PTR ( ACPI_RESOURCE_SOURCE, Target)); break; case ACPI_RSD_LABEL: /* * ResourceLabel */ AcpiRsDumpResourceLabel ("Resource Label", ACPI_CAST_PTR ( ACPI_RESOURCE_LABEL, Target)); break; case ACPI_RSD_SOURCE_LABEL: /* * ResourceSourceLabel */ AcpiRsDumpResourceLabel ("Resource Source Label", ACPI_CAST_PTR ( ACPI_RESOURCE_LABEL, Target)); break; default: AcpiOsPrintf ("**** Invalid table opcode [%X] ****\n", Table->Opcode); return; } Table++; Count--; } }
static void acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) { u8 *target = NULL; u8 *previous_target; char *name; u8 count; /* First table entry must contain the table length (# of table entries) */ count = table->offset; while (count) { previous_target = target; target = ACPI_ADD_PTR(u8, resource, table->offset); name = table->name; switch (table->opcode) { case ACPI_RSD_TITLE: /* * Optional resource title */ if (table->name) { acpi_os_printf("%s Resource\n", name); } break; /* Strings */ case ACPI_RSD_LITERAL: acpi_rs_out_string(name, ACPI_CAST_PTR(char, table->pointer)); break; case ACPI_RSD_STRING: acpi_rs_out_string(name, ACPI_CAST_PTR(char, target)); break; /* Data items, 8/16/32/64 bit */ case ACPI_RSD_UINT8: if (table->pointer) { acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer [*target])); } else { acpi_rs_out_integer8(name, ACPI_GET8(target)); } break; case ACPI_RSD_UINT16: acpi_rs_out_integer16(name, ACPI_GET16(target)); break; case ACPI_RSD_UINT32: acpi_rs_out_integer32(name, ACPI_GET32(target)); break; case ACPI_RSD_UINT64: acpi_rs_out_integer64(name, ACPI_GET64(target)); break; /* Flags: 1-bit and 2-bit flags supported */ case ACPI_RSD_1BITFLAG: acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & 0x01])); break; case ACPI_RSD_2BITFLAG: acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & 0x03])); break; case ACPI_RSD_3BITFLAG: acpi_rs_out_string(name, ACPI_CAST_PTR(char, table-> pointer[*target & 0x07])); break; case ACPI_RSD_SHORTLIST: /* * Short byte list (single line output) for DMA and IRQ resources * Note: The list length is obtained from the previous table entry */ if (previous_target) { acpi_rs_out_title(name); acpi_rs_dump_short_byte_list(*previous_target, target); } break; case ACPI_RSD_SHORTLISTX: /* * Short byte list (single line output) for GPIO vendor data * Note: The list length is obtained from the previous table entry */ if (previous_target) { acpi_rs_out_title(name); acpi_rs_dump_short_byte_list(*previous_target, * (ACPI_CAST_INDIRECT_PTR (u8, target))); } break; case ACPI_RSD_LONGLIST: /* * Long byte list for Vendor resource data * Note: The list length is obtained from the previous table entry */ if (previous_target) { acpi_rs_dump_byte_list(ACPI_GET16 (previous_target), target); } break; case ACPI_RSD_DWORDLIST: /* * Dword list for Extended Interrupt resources * Note: The list length is obtained from the previous table entry */ if (previous_target) { acpi_rs_dump_dword_list(*previous_target, ACPI_CAST_PTR(u32, target)); } break; case ACPI_RSD_WORDLIST: /* * Word list for GPIO Pin Table * Note: The list length is obtained from the previous table entry */ if (previous_target) { acpi_rs_dump_word_list(*previous_target, *(ACPI_CAST_INDIRECT_PTR (u16, target))); } break; case ACPI_RSD_ADDRESS: /* * Common flags for all Address resources */ acpi_rs_dump_address_common(ACPI_CAST_PTR (union acpi_resource_data, target)); break; case ACPI_RSD_SOURCE: /* * Optional resource_source for Address resources */ acpi_rs_dump_resource_source(ACPI_CAST_PTR (struct acpi_resource_source, target)); break; default: acpi_os_printf("**** Invalid table opcode [%X] ****\n", table->opcode); return; }
/******************************************************************************* * * FUNCTION: acpi_ex_system_memory_space_handler * * PARAMETERS: Function - Read or Write operation * Address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) * Value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region * * RETURN: Status * * DESCRIPTION: Handler for the System Memory address space (Op Region) * ******************************************************************************/ acpi_status acpi_ex_system_memory_space_handler(u32 function, acpi_physical_address address, u32 bit_width, u64 *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; void *logical_addr_ptr = NULL; struct acpi_mem_space_context *mem_info = region_context; u32 length; acpi_size map_length; acpi_size page_boundary_map_length; #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED u32 remainder; #endif ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); /* Validate and translate the bit width */ switch (bit_width) { case 8: length = 1; break; case 16: length = 2; break; case 32: length = 4; break; case 64: length = 8; break; default: ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u", bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. */ (void)acpi_ut_short_divide((u64) address, length, NULL, &remainder); if (remainder != 0) { return_ACPI_STATUS(AE_AML_ALIGNMENT); } #endif /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR * 2) Address beyond the current mapping? */ if ((address < mem_info->mapped_physical_address) || (((u64) address + length) > ((u64) mem_info->mapped_physical_address + mem_info->mapped_length))) { /* * The request cannot be resolved by the current memory mapping; * Delete the existing mapping and create a new one. */ if (mem_info->mapped_length) { /* Valid mapping, delete it */ acpi_os_unmap_memory(mem_info->mapped_logical_address, mem_info->mapped_length); } /* * Attempt to map from the requested address to the end of the region. * However, we will never map more than one page, nor will we cross * a page boundary. */ map_length = (acpi_size) ((mem_info->address + mem_info->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 */ page_boundary_map_length = ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address; if (!page_boundary_map_length) { page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE; } if (map_length > page_boundary_map_length) { map_length = page_boundary_map_length; } /* Create a new mapping starting at the address given */ mem_info->mapped_logical_address = acpi_os_map_memory((acpi_physical_address) address, map_length); if (!mem_info->mapped_logical_address) { ACPI_ERROR((AE_INFO, "Could not map memory at 0x%8.8X%8.8X, size %u", ACPI_FORMAT_NATIVE_UINT(address), (u32) map_length)); mem_info->mapped_length = 0; return_ACPI_STATUS(AE_NO_MEMORY); } /* Save the physical address and mapping size */ mem_info->mapped_physical_address = address; mem_info->mapped_length = map_length; } /* * Generate a logical pointer corresponding to the address we want to * access */ logical_addr_ptr = mem_info->mapped_logical_address + ((u64) address - (u64) mem_info->mapped_physical_address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", bit_width, function, ACPI_FORMAT_NATIVE_UINT(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: *value = 0; switch (bit_width) { case 8: *value = (u64) ACPI_GET8(logical_addr_ptr); break; case 16: *value = (u64) ACPI_GET16(logical_addr_ptr); break; case 32: *value = (u64) ACPI_GET32(logical_addr_ptr); break; case 64: *value = (u64) ACPI_GET64(logical_addr_ptr); break; default: /* bit_width was already validated */ break; } break; case ACPI_WRITE: switch (bit_width) { case 8: ACPI_SET8(logical_addr_ptr) = (u8) * value; break; case 16: ACPI_SET16(logical_addr_ptr) = (u16) * value; break; case 32: ACPI_SET32(logical_addr_ptr) = (u32) * value; break; case 64: ACPI_SET64(logical_addr_ptr) = (u64) * value; break; default: /* bit_width was already validated */ break; } break; default: status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS(status); }
ACPI_STATUS AcpiExSystemMemorySpaceHandler ( UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext) { ACPI_STATUS Status = AE_OK; void *LogicalAddrPtr = NULL; ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext; UINT32 Length; ACPI_SIZE MapLength; ACPI_SIZE PageBoundaryMapLength; #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED UINT32 Remainder; #endif ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler); /* Validate and translate the bit width */ switch (BitWidth) { case 8: Length = 1; break; case 16: Length = 2; break; case 32: Length = 4; break; case 64: Length = 8; break; default: ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u", BitWidth)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. */ (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder); if (Remainder != 0) { return_ACPI_STATUS (AE_AML_ALIGNMENT); } #endif /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR * 2) Address beyond the current mapping? */ if ((Address < MemInfo->MappedPhysicalAddress) || (((UINT64) Address + Length) > ((UINT64) MemInfo->MappedPhysicalAddress + MemInfo->MappedLength))) { /* * The request cannot be resolved by the current memory mapping; * Delete the existing mapping and create a new one. */ if (MemInfo->MappedLength) { /* Valid mapping, delete it */ AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress, MemInfo->MappedLength); } /* * October 2009: Attempt to map from the requested address to the * end of the region. However, we will never map more than one * page, nor will we cross a page boundary. */ 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: *Value = 0; switch (BitWidth) { case 8: *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr); break; case 16: *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr); break; case 32: *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr); break; case 64: *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr); break; default: /* BitWidth was already validated */ break; } break; case ACPI_WRITE: switch (BitWidth) { case 8: ACPI_SET8 (LogicalAddrPtr, *Value); break; case 16: ACPI_SET16 (LogicalAddrPtr, *Value); break; case 32: ACPI_SET32 (LogicalAddrPtr, *Value); break; case 64: ACPI_SET64 (LogicalAddrPtr, *Value); break; default: /* BitWidth was already validated */ break; } break; default: Status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS (Status); }
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state *parser_state) { u32 aml_offset = (u32) ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); union acpi_parse_object *field; u16 opcode; u32 name; ACPI_FUNCTION_TRACE("ps_get_next_field"); /* Determine field type */ switch (ACPI_GET8(parser_state->aml)) { default: opcode = AML_INT_NAMEDFIELD_OP; break; case 0x00: opcode = AML_INT_RESERVEDFIELD_OP; parser_state->aml++; break; case 0x01: opcode = AML_INT_ACCESSFIELD_OP; parser_state->aml++; break; } /* Allocate a new field op */ field = acpi_ps_alloc_op(opcode); if (!field) { return_PTR(NULL); } field->common.aml_offset = aml_offset; /* Decode the field type */ switch (opcode) { case AML_INT_NAMEDFIELD_OP: /* Get the 4-character name */ ACPI_MOVE_32_TO_32(&name, parser_state->aml); acpi_ps_set_name(field, name); parser_state->aml += ACPI_NAME_SIZE; /* Get the length which is encoded as a package length */ field->common.value.size = acpi_ps_get_next_package_length(parser_state); break; case AML_INT_RESERVEDFIELD_OP: /* Get the length which is encoded as a package length */ field->common.value.size = acpi_ps_get_next_package_length(parser_state); break; case AML_INT_ACCESSFIELD_OP: /* * Get access_type and access_attrib and merge into the field Op * access_type is first operand, access_attribute is second */ field->common.value.integer = (ACPI_GET8(parser_state->aml) << 8); parser_state->aml++; field->common.value.integer |= ACPI_GET8(parser_state->aml); parser_state->aml++; break; default: /* Opcode was set in previous switch */ break; } return_PTR(field); }
void acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, u32 arg_type, union acpi_parse_object *arg) { ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type); switch (arg_type) { case ARGP_BYTEDATA: acpi_ps_init_op(arg, AML_BYTE_OP); arg->common.value.integer = (u32) ACPI_GET8(parser_state->aml); parser_state->aml++; break; case ARGP_WORDDATA: acpi_ps_init_op(arg, AML_WORD_OP); /* Get 2 bytes from the AML stream */ ACPI_MOVE_16_TO_32(&arg->common.value.integer, parser_state->aml); parser_state->aml += 2; break; case ARGP_DWORDDATA: acpi_ps_init_op(arg, AML_DWORD_OP); /* Get 4 bytes from the AML stream */ ACPI_MOVE_32_TO_32(&arg->common.value.integer, parser_state->aml); parser_state->aml += 4; break; case ARGP_QWORDDATA: acpi_ps_init_op(arg, AML_QWORD_OP); /* Get 8 bytes from the AML stream */ ACPI_MOVE_64_TO_64(&arg->common.value.integer, parser_state->aml); parser_state->aml += 8; break; case ARGP_CHARLIST: acpi_ps_init_op(arg, AML_STRING_OP); arg->common.value.string = (char *)parser_state->aml; while (ACPI_GET8(parser_state->aml) != '\0') { parser_state->aml++; } parser_state->aml++; break; case ARGP_NAME: case ARGP_NAMESTRING: acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); arg->common.value.name = acpi_ps_get_next_namestring(parser_state); break; default: ACPI_REPORT_ERROR(("Invalid arg_type %X\n", arg_type)); break; } return_VOID; }
/******************************************************************************* * * FUNCTION: acpi_ex_system_memory_space_handler * * PARAMETERS: Function - Read or Write operation * Address - Where in the space to read or write * bit_width - Field width in bits (8, 16, or 32) * Value - Pointer to in or out value * handler_context - Pointer to Handler's context * region_context - Pointer to context specific to the * accessed region * * RETURN: Status * * DESCRIPTION: Handler for the System Memory address space (Op Region) * ******************************************************************************/ acpi_status acpi_ex_system_memory_space_handler(u32 function, acpi_physical_address address, u32 bit_width, acpi_integer * value, void *handler_context, void *region_context) { acpi_status status = AE_OK; void *logical_addr_ptr = NULL; struct acpi_mem_space_context *mem_info = region_context; u32 length; acpi_size window_size; #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED u32 remainder; #endif ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); /* Validate and translate the bit width */ switch (bit_width) { case 8: length = 1; break; case 16: length = 2; break; case 32: length = 4; break; case 64: length = 8; break; default: ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d", bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. */ (void)acpi_ut_short_divide((acpi_integer) address, length, NULL, &remainder); if (remainder != 0) { return_ACPI_STATUS(AE_AML_ALIGNMENT); } #endif /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR * 2) Address beyond the current mapping? */ if ((address < mem_info->mapped_physical_address) || (((acpi_integer) address + length) > ((acpi_integer) mem_info-> mapped_physical_address + mem_info->mapped_length))) { /* * The request cannot be resolved by the current memory mapping; * Delete the existing mapping and create a new one. */ if (mem_info->mapped_length) { /* Valid mapping, delete it */ acpi_os_unmap_memory(mem_info->mapped_logical_address, mem_info->mapped_length); } /* * Don't attempt to map memory beyond the end of the region, and * constrain the maximum mapping size to something reasonable. */ window_size = (acpi_size) ((mem_info->address + mem_info->length) - address); if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) { window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE; } /* Create a new mapping starting at the address given */ mem_info->mapped_logical_address = acpi_os_map_memory((acpi_native_uint) address, window_size); if (!mem_info->mapped_logical_address) { ACPI_ERROR((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", ACPI_FORMAT_UINT64(address), (u32) window_size)); mem_info->mapped_length = 0; return_ACPI_STATUS(AE_NO_MEMORY); } /* Save the physical address and mapping size */ mem_info->mapped_physical_address = address; mem_info->mapped_length = window_size; } /* * Generate a logical pointer corresponding to the address we want to * access */ logical_addr_ptr = mem_info->mapped_logical_address + ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", bit_width, 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: *value = 0; switch (bit_width) { case 8: *value = (acpi_integer) ACPI_GET8(logical_addr_ptr); break; case 16: *value = (acpi_integer) ACPI_GET16(logical_addr_ptr); break; case 32: *value = (acpi_integer) ACPI_GET32(logical_addr_ptr); break; case 64: *value = (acpi_integer) ACPI_GET64(logical_addr_ptr); break; default: /* bit_width was already validated */ break; } break; case ACPI_WRITE: switch (bit_width) { case 8: ACPI_SET8(logical_addr_ptr) = (u8) * value; break; case 16: ACPI_SET16(logical_addr_ptr) = (u16) * value; break; case 32: ACPI_SET32(logical_addr_ptr) = (u32) * value; break; case 64: ACPI_SET64(logical_addr_ptr) = (u64) * value; break; default: /* bit_width was already validated */ break; } break; default: status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS(status); }
ACPI_STATUS AcpiExSystemMemorySpaceHandler ( UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, ACPI_INTEGER *Value, void *HandlerContext, void *RegionContext) { ACPI_STATUS Status = AE_OK; void *LogicalAddrPtr = NULL; ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext; UINT32 Length; ACPI_SIZE WindowSize; #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED UINT32 Remainder; #endif ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler); /* Validate and translate the bit width */ switch (BitWidth) { case 8: Length = 1; break; case 16: Length = 2; break; case 32: Length = 4; break; case 64: Length = 8; break; default: ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %d", BitWidth)); return_ACPI_STATUS (AE_AML_OPERAND_VALUE); } #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED /* * Hardware does not support non-aligned data transfers, we must verify * the request. */ (void) AcpiUtShortDivide ((ACPI_INTEGER) Address, Length, NULL, &Remainder); if (Remainder != 0) { return_ACPI_STATUS (AE_AML_ALIGNMENT); } #endif /* * Does the request fit into the cached memory mapping? * Is 1) Address below the current mapping? OR * 2) Address beyond the current mapping? */ if ((Address < MemInfo->MappedPhysicalAddress) || (((ACPI_INTEGER) Address + Length) > ((ACPI_INTEGER) MemInfo->MappedPhysicalAddress + MemInfo->MappedLength))) { /* * The request cannot be resolved by the current memory mapping; * Delete the existing mapping and create a new one. */ if (MemInfo->MappedLength) { /* Valid mapping, delete it */ AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress, MemInfo->MappedLength); } /* * Don't attempt to map memory beyond the end of the region, and * constrain the maximum mapping size to something reasonable. */ WindowSize = (ACPI_SIZE) ((MemInfo->Address + MemInfo->Length) - Address); if (WindowSize > ACPI_SYSMEM_REGION_WINDOW_SIZE) { WindowSize = ACPI_SYSMEM_REGION_WINDOW_SIZE; } /* Create a new mapping starting at the address given */ MemInfo->MappedLogicalAddress = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) Address, WindowSize); if (!MemInfo->MappedLogicalAddress) { ACPI_ERROR ((AE_INFO, "Could not map memory at %8.8X%8.8X, size %X", ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) WindowSize)); MemInfo->MappedLength = 0; return_ACPI_STATUS (AE_NO_MEMORY); } /* Save the physical address and mapping size */ MemInfo->MappedPhysicalAddress = Address; MemInfo->MappedLength = WindowSize; } /* * Generate a logical pointer corresponding to the address we want to * access */ LogicalAddrPtr = MemInfo->MappedLogicalAddress + ((ACPI_INTEGER) Address - (ACPI_INTEGER) MemInfo->MappedPhysicalAddress); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (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: *Value = 0; switch (BitWidth) { case 8: *Value = (ACPI_INTEGER) ACPI_GET8 (LogicalAddrPtr); break; case 16: *Value = (ACPI_INTEGER) ACPI_GET16 (LogicalAddrPtr); break; case 32: *Value = (ACPI_INTEGER) ACPI_GET32 (LogicalAddrPtr); break; case 64: *Value = (ACPI_INTEGER) ACPI_GET64 (LogicalAddrPtr); break; default: /* BitWidth was already validated */ break; } break; case ACPI_WRITE: switch (BitWidth) { case 8: ACPI_SET8 (LogicalAddrPtr) = (UINT8) *Value; break; case 16: ACPI_SET16 (LogicalAddrPtr) = (UINT16) *Value; break; case 32: ACPI_SET32 ( LogicalAddrPtr) = (UINT32) *Value; break; case 64: ACPI_SET64 (LogicalAddrPtr) = (UINT64) *Value; break; default: /* BitWidth was already validated */ break; } break; default: Status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS (Status); }