Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 95461
b: refs/heads/master
c: ef805d9
h: refs/heads/master
i:
  95459: 77bfffd
v: v3
  • Loading branch information
Lin Ming authored and Len Brown committed Apr 22, 2008
1 parent 017761e commit b92e639
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 43 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 57345ee6b807d32e5eecf724a463378b80cc261c
refs/heads/master: ef805d956320ffa36d068673d5c5eb2a7d13209b
80 changes: 41 additions & 39 deletions trunk/drivers/acpi/dispatcher/dsfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,17 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
arg->common.node = info->field_node;
info->field_bit_length = arg->common.value.size;

/* Create and initialize an object for the new Field Node */

status = acpi_ex_prep_field_value(info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
/*
* If there is no object attached to the node, this node was just created
* and we need to create the field object. Otherwise, this was a lookup
* of an existing node and we don't want to create the field object again.
*/
if (!acpi_ns_get_attached_object
(info->field_node)) {
status = acpi_ex_prep_field_value(info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}

Expand Down Expand Up @@ -399,9 +405,22 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
union acpi_parse_object *arg = NULL;
struct acpi_namespace_node *node;
u8 type = 0;
u32 flags;

ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);

/*
* During the load phase, we want to enter the name of the field into
* the namespace. During the execute phase (when we evaluate the bank_value
* operand), we want to lookup the name.
*/
if (walk_state->deferred_node) {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
} else {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
}

switch (walk_state->opcode) {
case AML_FIELD_OP:
arg = acpi_ps_get_arg(op, 2);
Expand Down Expand Up @@ -433,10 +452,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name,
type, ACPI_IMODE_LOAD_PASS1,
ACPI_NS_NO_UPSEARCH |
ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND,
walk_state, &node);
flags, walk_state, &node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
status);
Expand Down Expand Up @@ -466,7 +482,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
*
* PARAMETERS: Op - Op containing the Field definition and args
* region_node - Object for the containing Operation Region
* ` walk_state - Current method state
* walk_state - Current method state
*
* RETURN: Status
*
Expand Down Expand Up @@ -513,36 +529,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
return_ACPI_STATUS(status);
}

/* Third arg is the bank_value */

/* TBD: This arg is a term_arg, not a constant, and must be evaluated */

/*
* Third arg is the bank_value
* This arg is a term_arg, not a constant
* It will be evaluated later, by acpi_ds_eval_bank_field_operands
*/
arg = arg->common.next;

/* Currently, only the following constants are supported */

switch (arg->common.aml_opcode) {
case AML_ZERO_OP:
info.bank_value = 0;
break;

case AML_ONE_OP:
info.bank_value = 1;
break;

case AML_BYTE_OP:
case AML_WORD_OP:
case AML_DWORD_OP:
case AML_QWORD_OP:
info.bank_value = (u32) arg->common.value.integer;
break;

default:
info.bank_value = 0;
ACPI_ERROR((AE_INFO,
"Non-constant BankValue for BankField is not implemented"));
}

/* Fourth arg is the field flags */

arg = arg->common.next;
Expand All @@ -553,8 +546,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op,
info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
info.region_node = region_node;

status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
/*
* Use Info.data_register_node to store bank_field Op
* It's safe because data_register_node will never be used when create bank field
* We store aml_start and aml_length in the bank_field Op for late evaluation
* Used in acpi_ex_prep_field_value(Info)
*
* TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
*/
info.data_register_node = (struct acpi_namespace_node *)op;

status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
return_ACPI_STATUS(status);
}

Expand Down
144 changes: 144 additions & 0 deletions trunk/drivers/acpi/dispatcher/dsopcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_get_bank_field_arguments
*
* PARAMETERS: obj_desc - A valid bank_field object
*
* RETURN: Status.
*
* DESCRIPTION: Get bank_field bank_value. This implements the late
* evaluation of these field attributes.
*
******************************************************************************/

acpi_status
acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
{
union acpi_operand_object *extra_desc;
struct acpi_namespace_node *node;
acpi_status status;

ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);

if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
return_ACPI_STATUS(AE_OK);
}

/* Get the AML pointer (method object) and bank_field node */

extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->bank_field.node;

ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
acpi_ut_get_node_name(node)));

/* Execute the AML code for the term_arg arguments */

status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_get_buffer_arguments
Expand Down Expand Up @@ -985,6 +1029,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_eval_bank_field_operands
*
* PARAMETERS: walk_state - Current walk
* Op - A valid bank_field Op object
*
* RETURN: Status
*
* DESCRIPTION: Get bank_field bank_value
* Called from acpi_ds_exec_end_op during bank_field parse tree walk
*
******************************************************************************/

acpi_status
acpi_ds_eval_bank_field_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;
union acpi_parse_object *arg;

ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);

/*
* This is where we evaluate the bank_value field of the
* bank_field declaration
*/

/* next_op points to the op that holds the Region */

next_op = op->common.value.arg;

/* next_op points to the op that holds the Bank Register */

next_op = next_op->common.next;

/* next_op points to the op that holds the Bank Value */

next_op = next_op->common.next;

/*
* Set proper index into operand stack for acpi_ds_obj_stack_push
* invoked inside acpi_ds_create_operand.
*
* We use walk_state->Operands[0] to store the evaluated bank_value
*/
walk_state->operand_index = 0;

status = acpi_ds_create_operand(walk_state, next_op, 0);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
acpi_ps_get_opcode_name(op->common.aml_opcode),
1, "after AcpiExResolveOperands");

/*
* Get the bank_value operand and save it
* (at Top of stack)
*/
operand_desc = walk_state->operands[0];

/* Arg points to the start Bank Field */

arg = acpi_ps_get_arg(op, 4);
while (arg) {

/* Ignore OFFSET and ACCESSAS terms here */

if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
node = arg->common.node;

obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
}

obj_desc->bank_field.value =
(u32) operand_desc->integer.value;
}

/* Move to next field in the list */

arg = arg->common.next;
}

acpi_ut_remove_reference(operand_desc);
return_ACPI_STATUS(status);
}

/*******************************************************************************
*
* FUNCTION: acpi_ds_exec_begin_control_op
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/acpi/dispatcher/dsutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
AML_VAR_PACKAGE_OP)
|| (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
|| (op->common.parent->common.aml_opcode ==
AML_INT_EVAL_SUBTREE_OP)) {
AML_INT_EVAL_SUBTREE_OP)
|| (op->common.parent->common.aml_opcode ==
AML_BANK_FIELD_OP)) {
/*
* These opcodes allow term_arg(s) as operands and therefore
* the operands can be method calls. The result is used.
Expand Down
11 changes: 11 additions & 0 deletions trunk/drivers/acpi/dispatcher/dswexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
break;
}
} else if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing BankField Op=%p\n",
op));

status =
acpi_ds_eval_bank_field_operands(walk_state,
op);
if (ACPI_FAILURE(status)) {
break;
}
}
break;

Expand Down
15 changes: 15 additions & 0 deletions trunk/drivers/acpi/executer/exprep.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL;
u32 type;
acpi_status status;

Expand Down Expand Up @@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.access_byte_width,
obj_desc->bank_field.region_obj,
obj_desc->bank_field.bank_obj));

/*
* Remember location in AML stream of the field unit
* opcode and operands -- since the bank_value
* operands must be evaluated.
*/
second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start =
((union acpi_parse_object *)(info->data_register_node))->
named.data;
second_desc->extra.aml_length =
((union acpi_parse_object *)(info->data_register_node))->
named.length;

break;

case ACPI_TYPE_LOCAL_INDEX_FIELD:
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/acpi/namespace/nsinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
info->field_count++;
break;

case ACPI_TYPE_LOCAL_BANK_FIELD:
info->field_count++;
break;

case ACPI_TYPE_BUFFER:
info->buffer_count++;
break;
Expand Down Expand Up @@ -287,6 +291,12 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
status = acpi_ds_get_buffer_field_arguments(obj_desc);
break;

case ACPI_TYPE_LOCAL_BANK_FIELD:

info->field_init++;
status = acpi_ds_get_bank_field_arguments(obj_desc);
break;

case ACPI_TYPE_BUFFER:

info->buffer_init++;
Expand Down
Loading

0 comments on commit b92e639

Please sign in to comment.