acpi_status
acpi_ex_system_io_space_handler(u32 function,
acpi_physical_address address,
u32 bit_width,
u64 *value,
void *handler_context, void *region_context)
{
acpi_status status = AE_OK;
u32 value32;
ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
bit_width, function,
ACPI_FORMAT_NATIVE_UINT(address)));
/* Decode the function parameter */
switch (function) {
case ACPI_READ:
status = acpi_hw_read_port((acpi_io_address) address,
&value32, bit_width);
*value = value32;
break;
case ACPI_WRITE:
status = acpi_hw_write_port((acpi_io_address) address,
(u32) * value, bit_width);
break;
default:
status = AE_BAD_PARAMETER;
break;
}
return_ACPI_STATUS(status);
}
开发者ID:03199618,项目名称:linux,代码行数:41,代码来源:exregion.c
示例3: AcpiDsEvalRegionOperands
ACPI_STATUS
AcpiDsEvalRegionOperands (
ACPI_WALK_STATE *WalkState,
ACPI_PARSE_OBJECT *Op)
{
ACPI_STATUS Status;
ACPI_OPERAND_OBJECT *ObjDesc;
ACPI_OPERAND_OBJECT *OperandDesc;
ACPI_NAMESPACE_NODE *Node;
ACPI_PARSE_OBJECT *NextOp;
ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op);
/*
* This is where we evaluate the address and length fields of the
* OpRegion declaration
*/
Node = Op->Common.Node;
/* NextOp points to the op that holds the SpaceID */
NextOp = Op->Common.Value.Arg;
/* NextOp points to address op */
NextOp = NextOp->Common.Next;
/* Evaluate/create the address and length operands */
Status = AcpiDsCreateOperands (WalkState, NextOp);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
/* Resolve the length and address operands to numbers */
Status = AcpiExResolveOperands (Op->Common.AmlOpcode,
ACPI_WALK_OPERANDS, WalkState);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
ObjDesc = AcpiNsGetAttachedObject (Node);
if (!ObjDesc)
{
return_ACPI_STATUS (AE_NOT_EXIST);
}
/*
* Get the length operand and save it
* (at Top of stack)
*/
OperandDesc = WalkState->Operands[WalkState->NumOperands - 1];
ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value;
AcpiUtRemoveReference (OperandDesc);
/*
* Get the address and save it
* (at top of stack - 1)
*/
OperandDesc = WalkState->Operands[WalkState->NumOperands - 2];
ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS)
OperandDesc->Integer.Value;
AcpiUtRemoveReference (OperandDesc);
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
ObjDesc,
ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address),
ObjDesc->Region.Length));
/* Now the address and length are valid for this opregion */
ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID;
return_ACPI_STATUS (Status);
}
//.........这里部分代码省略.........
/* Dump some of the buffer */
if (obj_desc->buffer.length > 0) {
acpi_os_printf(" =");
for (i = 0;
(i < obj_desc->buffer.length
&& i < 12); i++) {
acpi_os_printf(" %.2hX",
obj_desc->buffer.
pointer[i]);
}
}
acpi_os_printf("\n");
} else {
acpi_os_printf("[Length not yet evaluated]\n");
}
break;
case ACPI_TYPE_STRING:
acpi_os_printf("Len %.2X ", obj_desc->string.length);
acpi_ut_print_string(obj_desc->string.pointer, 32);
acpi_os_printf("\n");
break;
case ACPI_TYPE_REGION:
acpi_os_printf("[%s]",
acpi_ut_get_region_name(obj_desc->region.
space_id));
if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
ACPI_FORMAT_NATIVE_UINT
(obj_desc->region.address),
obj_desc->region.length);
} else {
acpi_os_printf
(" [Address/Length not yet evaluated]\n");
}
break;
case ACPI_TYPE_LOCAL_REFERENCE:
acpi_os_printf("[%s]\n",
acpi_ps_get_opcode_name(obj_desc->
reference.
opcode));
break;
case ACPI_TYPE_BUFFER_FIELD:
if (obj_desc->buffer_field.buffer_obj &&
obj_desc->buffer_field.buffer_obj->buffer.node) {
acpi_os_printf("Buf [%4.4s]",
acpi_ut_get_node_name(obj_desc->
buffer_field.
buffer_obj->
buffer.
node));
}
break;
case ACPI_TYPE_LOCAL_REGION_FIELD:
acpi_os_printf("Rgn [%4.4s]",
开发者ID:PyroOS,项目名称:Pyro,代码行数:67,代码来源:nsdump.c
示例5: AcpiEvAddressSpaceDispatch
//.........这里部分代码省略.........
Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
Context, &RegionContext);
/* Re-enter the interpreter */
AcpiExEnterInterpreter ();
/* Check for failure of the Region Setup */
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
"During region initialization: [%s]",
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
return_ACPI_STATUS (Status);
}
/* Region initialization may have been completed by RegionSetup */
if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
{
RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
/*
* Save the returned context for use in all accesses to
* the handler for this particular region
*/
if (!(RegionObj2->Extra.RegionContext))
{
RegionObj2->Extra.RegionContext = RegionContext;
}
}
}
/* We have everything we need, we can invoke the address space handler */
Handler = HandlerDesc->AddressSpace.Handler;
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
&RegionObj->Region.Handler->AddressSpace, Handler,
ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
/*
* Special handling for GenericSerialBus and GeneralPurposeIo:
* There are three extra parameters that must be passed to the
* handler via the context:
* 1) Connection buffer, a resource template from Connection() op.
* 2) Length of the above buffer.
* 3) Actual access length from the AccessAs() op.
*/
if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) ||
(RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) &&
Context &&
FieldObj)
{
/* Get the Connection (ResourceTemplate) buffer */
Context->Connection = FieldObj->Field.ResourceBuffer;
Context->Length = FieldObj->Field.ResourceLength;
Context->AccessLength = FieldObj->Field.AccessLength;
}
if (!(HandlerDesc->AddressSpace.HandlerFlags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
* know what it will do, so we can't hold the lock on the intepreter.
*/
AcpiExExitInterpreter();
}
/* Call the handler */
Status = Handler (Function,
(RegionObj->Region.Address + RegionOffset), BitWidth, Value,
Context, RegionObj2->Extra.RegionContext);
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
}
if (!(HandlerDesc->AddressSpace.HandlerFlags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
AcpiExEnterInterpreter ();
}
return_ACPI_STATUS (Status);
}
//.........这里部分代码省略.........
/*
* 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) {
//.........这里部分代码省略.........
"No init routine for region(%p) [%s]",
region_obj,
acpi_ut_get_region_name(region_obj->region.
space_id)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
* We must exit the interpreter because the region setup will
* potentially execute control methods (for example, the _REG method
* for this region)
*/
acpi_ex_exit_interpreter();
status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
handler_desc->address_space.context,
®ion_context);
/* Re-enter the interpreter */
acpi_ex_enter_interpreter();
/* Check for failure of the Region Setup */
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"During region initialization: [%s]",
acpi_ut_get_region_name(region_obj->
region.
space_id)));
return_ACPI_STATUS(status);
}
/* Region initialization may have been completed by region_setup */
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
if (region_obj2->extra.region_context) {
/* The handler for this region was already installed */
ACPI_FREE(region_context);
} else {
/*
* Save the returned context for use in all accesses to
* this particular region
*/
region_obj2->extra.region_context =
region_context;
}
}
}
/* We have everything we need, we can invoke the address space handler */
handler = handler_desc->address_space.handler;
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
®ion_obj->region.handler->address_space, handler,
ACPI_FORMAT_NATIVE_UINT(region_obj->region.address +
region_offset),
acpi_ut_get_region_name(region_obj->region.
space_id)));
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
* know what it will do, so we can't hold the lock on the intepreter.
*/
acpi_ex_exit_interpreter();
}
/* Call the handler */
status = handler(function,
(region_obj->region.address + region_offset),
bit_width, value, handler_desc->address_space.context,
region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
acpi_ut_get_region_name(region_obj->region.
space_id)));
}
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
acpi_ex_enter_interpreter();
}
return_ACPI_STATUS(status);
}
//.........这里部分代码省略.........
((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_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 (
(ACPI_PHYSICAL_ADDRESS) Address, MapLength);
if (!MemInfo->MappedLogicalAddress)
{
ACPI_ERROR ((AE_INFO,
"Could not map memory at 0x%8.8X%8.8X, size %u",
ACPI_FORMAT_NATIVE_UINT (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_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:
//.........这里部分代码省略.........
/* No initialization routine, exit with error */
ACPI_ERROR ((AE_INFO,
"No init routine for region(%p) [%s]",
RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
return_ACPI_STATUS (AE_NOT_EXIST);
}
/*
* We must exit the interpreter because the region setup will
* potentially execute control methods (for example, the _REG method
* for this region)
*/
AcpiExExitInterpreter ();
Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
HandlerDesc->AddressSpace.Context, &RegionContext);
/* Re-enter the interpreter */
AcpiExEnterInterpreter ();
/* Check for failure of the Region Setup */
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
"During region initialization: [%s]",
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
return_ACPI_STATUS (Status);
}
/* Region initialization may have been completed by RegionSetup */
if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
{
RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
if (RegionObj2->Extra.RegionContext)
{
/* The handler for this region was already installed */
ACPI_FREE (RegionContext);
}
else
{
/*
* Save the returned context for use in all accesses to
* this particular region
*/
RegionObj2->Extra.RegionContext = RegionContext;
}
}
}
/* We have everything we need, we can invoke the address space handler */
Handler = HandlerDesc->AddressSpace.Handler;
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
&RegionObj->Region.Handler->AddressSpace, Handler,
ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
if (!(HandlerDesc->AddressSpace.HandlerFlags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
* know what it will do, so we can't hold the lock on the intepreter.
*/
AcpiExExitInterpreter();
}
/* Call the handler */
Status = Handler (Function,
(RegionObj->Region.Address + RegionOffset), BitWidth, Value,
HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
}
if (!(HandlerDesc->AddressSpace.HandlerFlags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
{
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
AcpiExEnterInterpreter ();
}
return_ACPI_STATUS (Status);
}
acpi_status
acpi_ds_eval_table_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;
struct acpi_namespace_node *node;
union acpi_parse_object *next_op;
u32 table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
/*
* This is where we evaluate the signature_string and oem_iDString
* and oem_table_iDString of the data_table_region declaration
*/
node = op->common.node;
/* next_op points to signature_string op */
next_op = op->common.value.arg;
/*
* Evaluate/create the signature_string and oem_iDString
* and oem_table_iDString operands
*/
status = acpi_ds_create_operands(walk_state, next_op);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Resolve the signature_string and oem_iDString
* and oem_table_iDString operands
*/
status = acpi_ex_resolve_operands(op->common.aml_opcode,
ACPI_WALK_OPERANDS, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
operand = &walk_state->operands[0];
/* Find the ACPI table */
status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer,
operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ut_remove_reference(operand[0]);
acpi_ut_remove_reference(operand[1]);
acpi_ut_remove_reference(operand[2]);
status = acpi_get_table_by_index(table_index, &table);
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);
}
obj_desc->region.address =
(acpi_physical_address) ACPI_TO_INTEGER(table);
obj_desc->region.length = table->length;
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
obj_desc,
ACPI_FORMAT_NATIVE_UINT(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_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_NATIVE_UINT(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);
}
//.........这里部分代码省略.........
{
/*
* 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:
//.........这里部分代码省略.........
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_physical_address) 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_NATIVE_UINT(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_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.
*/
//.........这里部分代码省略.........
region.
space_id)));
return_ACPI_STATUS(status);
}
/* Region initialization may have been completed by region_setup */
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
/*
* Save the returned context for use in all accesses to
* the handler for this particular region
*/
if (!(region_obj2->extra.region_context)) {
region_obj2->extra.region_context =
region_context;
}
}
}
/* We have everything we need, we can invoke the address space handler */
handler = handler_desc->address_space.handler;
address = (region_obj->region.address + region_offset);
/*
* Special handling for generic_serial_bus and general_purpose_io:
* There are three extra parameters that must be passed to the
* handler via the context:
* 1) Connection buffer, a resource template from Connection() op
* 2) Length of the above buffer
* 3) Actual access length from the access_as() op
*
* In addition, for general_purpose_io, the Address and bit_width fields
* are defined as follows:
* 1) Address is the pin number index of the field (bit offset from
* the previous Connection)
* 2) bit_width is the actual bit length of the field (number of pins)
*/
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
context && field_obj) {
/* Get the Connection (resource_template) buffer */
context->connection = field_obj->field.resource_buffer;
context->length = field_obj->field.resource_length;
context->access_length = field_obj->field.access_length;
}
if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
context && field_obj) {
/* Get the Connection (resource_template) buffer */
context->connection = field_obj->field.resource_buffer;
context->length = field_obj->field.resource_length;
context->access_length = field_obj->field.access_length;
address = field_obj->field.pin_number_index;
bit_width = field_obj->field.bit_length;
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
®ion_obj->region.handler->address_space, handler,
ACPI_FORMAT_NATIVE_UINT(address),
acpi_ut_get_region_name(region_obj->region.
space_id)));
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
* know what it will do, so we can't hold the lock on the intepreter.
*/
acpi_ex_exit_interpreter();
}
/* Call the handler */
status = handler(function, address, bit_width, value, context,
region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
acpi_ut_get_region_name(region_obj->region.
space_id)));
}
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
acpi_ex_enter_interpreter();
}
return_ACPI_STATUS(status);
}
请发表评论