Commit 9ce81784 authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPI 5.0: Implement Connection() and AccessAs() changes

Support within the interpreter and operation region dispatch.
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent ffef6827
...@@ -162,6 +162,7 @@ acpi_status acpi_ev_initialize_op_regions(void); ...@@ -162,6 +162,7 @@ acpi_status acpi_ev_initialize_op_regions(void);
acpi_status acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *field_obj,
u32 function, u32 function,
u32 region_offset, u32 bit_width, u64 *value); u32 region_offset, u32 bit_width, u64 *value);
......
...@@ -53,7 +53,7 @@ typedef u32 acpi_mutex_handle; ...@@ -53,7 +53,7 @@ typedef u32 acpi_mutex_handle;
/* Total number of aml opcodes defined */ /* Total number of aml opcodes defined */
#define AML_NUM_OPCODES 0x7F #define AML_NUM_OPCODES 0x81
/* Forward declarations */ /* Forward declarations */
...@@ -249,12 +249,16 @@ struct acpi_create_field_info { ...@@ -249,12 +249,16 @@ struct acpi_create_field_info {
struct acpi_namespace_node *field_node; struct acpi_namespace_node *field_node;
struct acpi_namespace_node *register_node; struct acpi_namespace_node *register_node;
struct acpi_namespace_node *data_register_node; struct acpi_namespace_node *data_register_node;
struct acpi_namespace_node *connection_node;
u8 *resource_buffer;
u32 bank_value; u32 bank_value;
u32 field_bit_position; u32 field_bit_position;
u32 field_bit_length; u32 field_bit_length;
u16 resource_length;
u8 field_flags; u8 field_flags;
u8 attribute; u8 attribute;
u8 field_type; u8 field_type;
u8 access_length;
}; };
typedef typedef
......
...@@ -254,6 +254,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO}; ...@@ -254,6 +254,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
u32 base_byte_offset; /* Byte offset within containing object */\ u32 base_byte_offset; /* Byte offset within containing object */\
u32 value; /* Value to store into the Bank or Index register */\ u32 value; /* Value to store into the Bank or Index register */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
u8 access_length; /* For serial regions/fields */
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
...@@ -261,7 +262,9 @@ struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and ...@@ -261,7 +262,9 @@ struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and
}; };
struct acpi_object_region_field { struct acpi_object_region_field {
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
union acpi_operand_object *region_obj; /* Containing op_region object */
u8 *resource_buffer; /* resource_template for serial regions/fields */
}; };
struct acpi_object_bank_field { struct acpi_object_bank_field {
......
...@@ -93,6 +93,7 @@ ...@@ -93,6 +93,7 @@
#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME) #define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
#define ARGP_CONNECTFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_CONTINUE_OP ARG_NONE #define ARGP_CONTINUE_OP ARG_NONE
#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME) #define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME)
#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) #define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
...@@ -164,6 +165,7 @@ ...@@ -164,6 +165,7 @@
#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG) #define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_REVISION_OP ARG_NONE #define ARGP_REVISION_OP ARG_NONE
#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST) #define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST)
#define ARGP_SERIALFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) #define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME) #define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME)
...@@ -223,6 +225,7 @@ ...@@ -223,6 +225,7 @@
#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF) #define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF)
#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF) #define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF)
#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF) #define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
#define ARGI_CONNECTFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE #define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE
#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET) #define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET)
#define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) #define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
...@@ -294,6 +297,7 @@ ...@@ -294,6 +297,7 @@
#define ARGI_RETURN_OP ARGI_INVALID_OPCODE #define ARGI_RETURN_OP ARGI_INVALID_OPCODE
#define ARGI_REVISION_OP ARG_NONE #define ARGI_REVISION_OP ARG_NONE
#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE #define ARGI_SCOPE_OP ARGI_INVALID_OPCODE
#define ARGI_SERIALFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT) #define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
......
...@@ -188,6 +188,14 @@ ...@@ -188,6 +188,14 @@
#define AML_LLESSEQUAL_OP (u16) 0x9294 #define AML_LLESSEQUAL_OP (u16) 0x9294
#define AML_LNOTEQUAL_OP (u16) 0x9293 #define AML_LNOTEQUAL_OP (u16) 0x9293
/*
* Opcodes for "Field" operators
*/
#define AML_FIELD_OFFSET_OP (u8) 0x00
#define AML_FIELD_ACCESS_OP (u8) 0x01
#define AML_FIELD_CONNECTION_OP (u8) 0x02 /* ACPI 5.0 */
#define AML_FIELD_EXT_ACCESS_OP (u8) 0x03 /* ACPI 5.0 */
/* /*
* Internal opcodes * Internal opcodes
* Use only "Unknown" AML opcodes, don't attempt to use * Use only "Unknown" AML opcodes, don't attempt to use
...@@ -202,6 +210,8 @@ ...@@ -202,6 +210,8 @@
#define AML_INT_METHODCALL_OP (u16) 0x0035 #define AML_INT_METHODCALL_OP (u16) 0x0035
#define AML_INT_RETURN_VALUE_OP (u16) 0x0036 #define AML_INT_RETURN_VALUE_OP (u16) 0x0036
#define AML_INT_EVAL_SUBTREE_OP (u16) 0x0037 #define AML_INT_EVAL_SUBTREE_OP (u16) 0x0037
#define AML_INT_CONNECTION_OP (u16) 0x0038
#define AML_INT_EXTACCESSFIELD_OP (u16) 0x0039
#define ARG_NONE 0x0 #define ARG_NONE 0x0
......
...@@ -221,6 +221,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ...@@ -221,6 +221,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
{ {
acpi_status status; acpi_status status;
u64 position; u64 position;
union acpi_parse_object *child;
ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
...@@ -232,10 +233,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ...@@ -232,10 +233,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
while (arg) { while (arg) {
/* /*
* Three types of field elements are handled: * Four types of field elements are handled:
* 1) Offset - specifies a bit offset * 1) Name - Enters a new named field into the namespace
* 2) access_as - changes the access mode * 2) Offset - specifies a bit offset
* 3) Name - Enters a new named field into the namespace * 3) access_as - changes the access mode/attributes
* 4) Connection - Associate a resource template with the field
*/ */
switch (arg->common.aml_opcode) { switch (arg->common.aml_opcode) {
case AML_INT_RESERVEDFIELD_OP: case AML_INT_RESERVEDFIELD_OP:
...@@ -253,21 +255,70 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ...@@ -253,21 +255,70 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
break; break;
case AML_INT_ACCESSFIELD_OP: case AML_INT_ACCESSFIELD_OP:
case AML_INT_EXTACCESSFIELD_OP:
/* /*
* Get a new access_type and access_attribute -- to be used for all * Get new access_type, access_attribute, and access_length fields
* field units that follow, until field end or another access_as * -- to be used for all field units that follow, until the
* keyword. * end-of-field or another access_as keyword is encountered.
* NOTE. These three bytes are encoded in the integer value
* of the parseop for convenience.
* *
* In field_flags, preserve the flag bits other than the * In field_flags, preserve the flag bits other than the
* ACCESS_TYPE bits * ACCESS_TYPE bits.
*/ */
/* access_type (byte_acc, word_acc, etc.) */
info->field_flags = (u8) info->field_flags = (u8)
((info-> ((info->
field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
((u8) ((u32) arg->common.value.integer >> 8))); ((u8)((u32)(arg->common.value.integer & 0x07))));
/* access_attribute (attrib_quick, attrib_byte, etc.) */
info->attribute =
(u8)((arg->common.value.integer >> 8) & 0xFF);
/* access_length (for serial/buffer protocols) */
info->access_length =
(u8)((arg->common.value.integer >> 16) & 0xFF);
break;
case AML_INT_CONNECTION_OP:
/*
* Clear any previous connection. New connection is used for all
* fields that follow, similar to access_as
*/
info->resource_buffer = NULL;
info->connection_node = NULL;
/*
* A Connection() is either an actual resource descriptor (buffer)
* or a named reference to a resource template
*/
child = arg->common.value.arg;
if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
info->resource_buffer = child->named.data;
info->resource_length =
(u16)child->named.value.integer;
} else {
/* Lookup the Connection() namepath, it should already exist */
info->attribute = (u8) (arg->common.value.integer); status = acpi_ns_lookup(walk_state->scope_info,
child->common.value.
name, ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE,
ACPI_NS_DONT_OPEN_SCOPE,
walk_state,
&info->connection_node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(child->common.
value.name,
status);
return_ACPI_STATUS(status);
}
}
break; break;
case AML_INT_NAMEDFIELD_OP: case AML_INT_NAMEDFIELD_OP:
...@@ -374,6 +425,8 @@ acpi_ds_create_field(union acpi_parse_object *op, ...@@ -374,6 +425,8 @@ acpi_ds_create_field(union acpi_parse_object *op,
} }
} }
ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info));
/* Second arg is the field flags */ /* Second arg is the field flags */
arg = arg->common.next; arg = arg->common.next;
...@@ -386,7 +439,6 @@ acpi_ds_create_field(union acpi_parse_object *op, ...@@ -386,7 +439,6 @@ acpi_ds_create_field(union acpi_parse_object *op,
info.region_node = region_node; info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -474,8 +526,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ...@@ -474,8 +526,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
*/ */
while (arg) { while (arg) {
/* /*
* Ignore OFFSET and ACCESSAS terms here; we are only interested in the * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
* field names in order to enter them into the namespace. * in the field names in order to enter them into the namespace.
*/ */
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
status = acpi_ns_lookup(walk_state->scope_info, status = acpi_ns_lookup(walk_state->scope_info,
...@@ -651,6 +703,5 @@ acpi_ds_create_index_field(union acpi_parse_object *op, ...@@ -651,6 +703,5 @@ acpi_ds_create_index_field(union acpi_parse_object *op,
info.region_node = region_node; info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -329,6 +329,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) ...@@ -329,6 +329,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
* FUNCTION: acpi_ev_address_space_dispatch * FUNCTION: acpi_ev_address_space_dispatch
* *
* PARAMETERS: region_obj - Internal region object * PARAMETERS: region_obj - Internal region object
* field_obj - Corresponding field. Can be NULL.
* Function - Read or Write operation * Function - Read or Write operation
* region_offset - Where in the region to read or write * region_offset - Where in the region to read or write
* bit_width - Field width in bits (8, 16, 32, or 64) * bit_width - Field width in bits (8, 16, 32, or 64)
...@@ -344,6 +345,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) ...@@ -344,6 +345,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
acpi_status acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *field_obj,
u32 function, u32 function,
u32 region_offset, u32 bit_width, u64 *value) u32 region_offset, u32 bit_width, u64 *value)
{ {
...@@ -353,6 +355,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ...@@ -353,6 +355,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *handler_desc; union acpi_operand_object *handler_desc;
union acpi_operand_object *region_obj2; union acpi_operand_object *region_obj2;
void *region_context = NULL; void *region_context = NULL;
struct acpi_connection_info *context;
ACPI_FUNCTION_TRACE(ev_address_space_dispatch); ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
...@@ -375,6 +378,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ...@@ -375,6 +378,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
return_ACPI_STATUS(AE_NOT_EXIST); return_ACPI_STATUS(AE_NOT_EXIST);
} }
context = handler_desc->address_space.context;
/* /*
* It may be the case that the region has never been initialized. * It may be the case that the region has never been initialized.
* Some types of regions require special init code * Some types of regions require special init code
...@@ -404,8 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ...@@ -404,8 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
acpi_ex_exit_interpreter(); acpi_ex_exit_interpreter();
status = region_setup(region_obj, ACPI_REGION_ACTIVATE, status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
handler_desc->address_space.context, context, &region_context);
&region_context);
/* Re-enter the interpreter */ /* Re-enter the interpreter */
...@@ -455,6 +459,25 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ...@@ -455,6 +459,25 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
acpi_ut_get_region_name(region_obj->region. acpi_ut_get_region_name(region_obj->region.
space_id))); space_id)));
/*
* 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.
*/
if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
(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;
}
if (!(handler_desc->address_space.handler_flags & if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/* /*
...@@ -469,7 +492,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, ...@@ -469,7 +492,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
status = handler(function, status = handler(function,
(region_obj->region.address + region_offset), (region_obj->region.address + region_offset),
bit_width, value, handler_desc->address_space.context, bit_width, value, context,
region_obj2->extra.region_context); region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
......
...@@ -297,9 +297,9 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer) ...@@ -297,9 +297,9 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
/* Bytewise reads */ /* Bytewise reads */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, status =
region_offset, 8, acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
&value); region_offset, 8, &value);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return status; return status;
} }
......
...@@ -192,10 +192,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = { ...@@ -192,10 +192,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = {
"Buffer Object"} "Buffer Object"}
}; };
static struct acpi_exdump_info acpi_ex_dump_region_field[3] = { static struct acpi_exdump_info acpi_ex_dump_region_field[5] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL}, {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL},
{ACPI_EXD_FIELD, 0, NULL}, {ACPI_EXD_FIELD, 0, NULL},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"} {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(field.access_length), "AccessLength"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.resource_buffer),
"ResourceBuffer"}
}; };
static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = { static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = {
......
...@@ -283,9 +283,10 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, ...@@ -283,9 +283,10 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
/* Invoke the appropriate address_space/op_region handler */ /* Invoke the appropriate address_space/op_region handler */
status = status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
acpi_ev_address_space_dispatch(rgn_desc, function, region_offset, function, region_offset,
ACPI_MUL_8(obj_desc->common_field. ACPI_MUL_8(obj_desc->
common_field.
access_byte_width), access_byte_width),
value); value);
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "acinterp.h" #include "acinterp.h"
#include "amlcode.h" #include "amlcode.h"
#include "acnamesp.h" #include "acnamesp.h"
#include "acdispat.h"
#define _COMPONENT ACPI_EXECUTER #define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exprep") ACPI_MODULE_NAME("exprep")
...@@ -455,6 +456,30 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) ...@@ -455,6 +456,30 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.region_obj = obj_desc->field.region_obj =
acpi_ns_get_attached_object(info->region_node); acpi_ns_get_attached_object(info->region_node);
/* Fields specific to generic_serial_bus fields */
obj_desc->field.access_length = info->access_length;
if (info->connection_node) {
second_desc = info->connection_node->object;
if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
status =
acpi_ds_get_buffer_arguments(second_desc);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(status);
}
}
obj_desc->field.resource_buffer =
second_desc->buffer.pointer;
obj_desc->field.resource_length =
(u16)second_desc->buffer.length;
} else if (info->resource_buffer) {
obj_desc->field.resource_buffer = info->resource_buffer;
obj_desc->field.resource_length = info->resource_length;
}
/* Allow full data read from EC address space */ /* Allow full data read from EC address space */
if ((obj_desc->field.region_obj->region.space_id == if ((obj_desc->field.region_obj->region.space_id ==
......
...@@ -484,34 +484,54 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, ...@@ -484,34 +484,54 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
*parser_state) *parser_state)
{ {
u32 aml_offset = (u32) u32 aml_offset;
ACPI_PTR_DIFF(parser_state->aml,
parser_state->aml_start);
union acpi_parse_object *field; union acpi_parse_object *field;
union acpi_parse_object *arg = NULL;
u16 opcode; u16 opcode;
u32 name; u32 name;
u8 access_type;
u8 access_attribute;
u8 access_length;
u32 pkg_length;
u8 *pkg_end;
u32 buffer_length;
ACPI_FUNCTION_TRACE(ps_get_next_field); ACPI_FUNCTION_TRACE(ps_get_next_field);
aml_offset =
(u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start);
/* Determine field type */ /* Determine field type */
switch (ACPI_GET8(parser_state->aml)) { switch (ACPI_GET8(parser_state->aml)) {
default: case AML_FIELD_OFFSET_OP:
opcode = AML_INT_NAMEDFIELD_OP; opcode = AML_INT_RESERVEDFIELD_OP;
parser_state->aml++;
break; break;
case 0x00: case AML_FIELD_ACCESS_OP:
opcode = AML_INT_RESERVEDFIELD_OP; opcode = AML_INT_ACCESSFIELD_OP;
parser_state->aml++; parser_state->aml++;
break; break;
case 0x01: case AML_FIELD_CONNECTION_OP:
opcode = AML_INT_ACCESSFIELD_OP; opcode = AML_INT_CONNECTION_OP;
parser_state->aml++; parser_state->aml++;
break; break;
case AML_FIELD_EXT_ACCESS_OP:
opcode = AML_INT_EXTACCESSFIELD_OP;
parser_state->aml++;
break;
default:
opcode = AML_INT_NAMEDFIELD_OP;
break;
} }
/* Allocate a new field op */ /* Allocate a new field op */
...@@ -549,16 +569,111 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state ...@@ -549,16 +569,111 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
break; break;
case AML_INT_ACCESSFIELD_OP: case AML_INT_ACCESSFIELD_OP:
case AML_INT_EXTACCESSFIELD_OP:
/* /*
* Get access_type and access_attrib and merge into the field Op * Get access_type and access_attrib and merge into the field Op
* access_type is first operand, access_attribute is second * access_type is first operand, access_attribute is second. stuff
* these bytes into the node integer value for convenience.
*/
/* Get the two bytes (Type/Attribute) */
access_type = ACPI_GET8(parser_state->aml);
parser_state->aml++;
access_attribute = ACPI_GET8(parser_state->aml);
parser_state->aml++;
field->common.value.integer = (u8)access_type;
field->common.value.integer |= (u16)(access_attribute << 8);
/* This opcode has a third byte, access_length */
if (opcode == AML_INT_EXTACCESSFIELD_OP) {
access_length = ACPI_GET8(parser_state->aml);
parser_state->aml++;
field->common.value.integer |=
(u32)(access_length << 16);
}
break;
case AML_INT_CONNECTION_OP:
/*
* Argument for Connection operator can be either a Buffer
* (resource descriptor), or a name_string.
*/ */
field->common.value.integer = if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) {
(((u32) ACPI_GET8(parser_state->aml) << 8));
parser_state->aml++; parser_state->aml++;
field->common.value.integer |= ACPI_GET8(parser_state->aml);
pkg_end = parser_state->aml;
pkg_length =
acpi_ps_get_next_package_length(parser_state);
pkg_end += pkg_length;
if (parser_state->aml < pkg_end) {
/* Non-empty list */
arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
if (!arg) {
return_PTR(NULL);
}
/* Get the actual buffer length argument */
opcode = ACPI_GET8(parser_state->aml);
parser_state->aml++; parser_state->aml++;
switch (opcode) {
case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
buffer_length =
ACPI_GET8(parser_state->aml);
parser_state->aml += 1;
break;
case AML_WORD_OP: /* AML_WORDDATA_ARG */
buffer_length =
ACPI_GET16(parser_state->aml);
parser_state->aml += 2;
break;
case AML_DWORD_OP: /* AML_DWORDATA_ARG */
buffer_length =
ACPI_GET32(parser_state->aml);
parser_state->aml += 4;
break;
default:
buffer_length = 0;
break;
}
/* Fill in bytelist data */
arg->named.value.size = buffer_length;
arg->named.data = parser_state->aml;
}
/* Skip to End of byte data */
parser_state->aml = pkg_end;
} else {
arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
if (!arg) {
return_PTR(NULL);
}
/* Get the Namestring argument */
arg->common.value.name =
acpi_ps_get_next_namestring(parser_state);
}
/* Link the buffer/namestring to parent (CONNECTION_OP) */
acpi_ps_append_arg(field, arg);
break; break;
default: default:
......
...@@ -638,7 +638,16 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { ...@@ -638,7 +638,16 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
/* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
AML_FLAGS_EXEC_0A_0T_1R) AML_FLAGS_EXEC_0A_0T_1R),
/* ACPI 5.0 opcodes */
/* 7F */ ACPI_OP("-ConnectField-", ARGP_CONNECTFIELD_OP,
ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY,
AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS),
/* 80 */ ACPI_OP("-ExtAccessField-", ARGP_CONNECTFIELD_OP,
ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY,
AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0)
/*! [End] no source code translation !*/ /*! [End] no source code translation !*/
}; };
...@@ -657,7 +666,7 @@ static const u8 acpi_gbl_short_op_index[256] = { ...@@ -657,7 +666,7 @@ static const u8 acpi_gbl_short_op_index[256] = {
/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, /* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, /* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D, /* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, /* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, /* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, /* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, /* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
......
...@@ -74,6 +74,12 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) ...@@ -74,6 +74,12 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
ACPI_FUNCTION_ENTRY(); ACPI_FUNCTION_ENTRY();
/*
if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP)
{
return (Op->Common.Value.Arg);
}
*/
/* Get the info structure for this opcode */ /* Get the info structure for this opcode */
op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
......
...@@ -957,6 +957,14 @@ acpi_status(*acpi_adr_space_handler) (u32 function, ...@@ -957,6 +957,14 @@ acpi_status(*acpi_adr_space_handler) (u32 function,
#define ACPI_DEFAULT_HANDLER NULL #define ACPI_DEFAULT_HANDLER NULL
/* Special Context data for generic_serial_bus/general_purpose_io (ACPI 5.0) */
struct acpi_connection_info {
u8 *connection;
u16 length;
u8 access_length;
};
typedef typedef
acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle, acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle,
u32 function, u32 function,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment