diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsopcode.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsopcode.c | 260 |
1 files changed, 256 insertions, 4 deletions
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index f501e083aac7..a818e0ddb996 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -49,6 +49,7 @@ | |||
49 | #include <acpi/acinterp.h> | 49 | #include <acpi/acinterp.h> |
50 | #include <acpi/acnamesp.h> | 50 | #include <acpi/acnamesp.h> |
51 | #include <acpi/acevents.h> | 51 | #include <acpi/acevents.h> |
52 | #include <acpi/actables.h> | ||
52 | 53 | ||
53 | #define _COMPONENT ACPI_DISPATCHER | 54 | #define _COMPONENT ACPI_DISPATCHER |
54 | ACPI_MODULE_NAME("dsopcode") | 55 | ACPI_MODULE_NAME("dsopcode") |
@@ -219,6 +220,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) | |||
219 | 220 | ||
220 | /******************************************************************************* | 221 | /******************************************************************************* |
221 | * | 222 | * |
223 | * FUNCTION: acpi_ds_get_bank_field_arguments | ||
224 | * | ||
225 | * PARAMETERS: obj_desc - A valid bank_field object | ||
226 | * | ||
227 | * RETURN: Status. | ||
228 | * | ||
229 | * DESCRIPTION: Get bank_field bank_value. This implements the late | ||
230 | * evaluation of these field attributes. | ||
231 | * | ||
232 | ******************************************************************************/ | ||
233 | |||
234 | acpi_status | ||
235 | acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) | ||
236 | { | ||
237 | union acpi_operand_object *extra_desc; | ||
238 | struct acpi_namespace_node *node; | ||
239 | acpi_status status; | ||
240 | |||
241 | ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); | ||
242 | |||
243 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
244 | return_ACPI_STATUS(AE_OK); | ||
245 | } | ||
246 | |||
247 | /* Get the AML pointer (method object) and bank_field node */ | ||
248 | |||
249 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
250 | node = obj_desc->bank_field.node; | ||
251 | |||
252 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
253 | (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); | ||
254 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", | ||
255 | acpi_ut_get_node_name(node))); | ||
256 | |||
257 | /* Execute the AML code for the term_arg arguments */ | ||
258 | |||
259 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | ||
260 | extra_desc->extra.aml_length, | ||
261 | extra_desc->extra.aml_start); | ||
262 | return_ACPI_STATUS(status); | ||
263 | } | ||
264 | |||
265 | /******************************************************************************* | ||
266 | * | ||
222 | * FUNCTION: acpi_ds_get_buffer_arguments | 267 | * FUNCTION: acpi_ds_get_buffer_arguments |
223 | * | 268 | * |
224 | * PARAMETERS: obj_desc - A valid Buffer object | 269 | * PARAMETERS: obj_desc - A valid Buffer object |
@@ -770,7 +815,109 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, | |||
770 | 815 | ||
771 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | 816 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", |
772 | obj_desc, | 817 | obj_desc, |
773 | ACPI_FORMAT_UINT64(obj_desc->region.address), | 818 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), |
819 | obj_desc->region.length)); | ||
820 | |||
821 | /* Now the address and length are valid for this opregion */ | ||
822 | |||
823 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | ||
824 | |||
825 | return_ACPI_STATUS(status); | ||
826 | } | ||
827 | |||
828 | /******************************************************************************* | ||
829 | * | ||
830 | * FUNCTION: acpi_ds_eval_table_region_operands | ||
831 | * | ||
832 | * PARAMETERS: walk_state - Current walk | ||
833 | * Op - A valid region Op object | ||
834 | * | ||
835 | * RETURN: Status | ||
836 | * | ||
837 | * DESCRIPTION: Get region address and length | ||
838 | * Called from acpi_ds_exec_end_op during data_table_region parse tree walk | ||
839 | * | ||
840 | ******************************************************************************/ | ||
841 | |||
842 | acpi_status | ||
843 | acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, | ||
844 | union acpi_parse_object *op) | ||
845 | { | ||
846 | acpi_status status; | ||
847 | union acpi_operand_object *obj_desc; | ||
848 | union acpi_operand_object **operand; | ||
849 | struct acpi_namespace_node *node; | ||
850 | union acpi_parse_object *next_op; | ||
851 | acpi_native_uint table_index; | ||
852 | struct acpi_table_header *table; | ||
853 | |||
854 | ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); | ||
855 | |||
856 | /* | ||
857 | * This is where we evaluate the signature_string and oem_iDString | ||
858 | * and oem_table_iDString of the data_table_region declaration | ||
859 | */ | ||
860 | node = op->common.node; | ||
861 | |||
862 | /* next_op points to signature_string op */ | ||
863 | |||
864 | next_op = op->common.value.arg; | ||
865 | |||
866 | /* | ||
867 | * Evaluate/create the signature_string and oem_iDString | ||
868 | * and oem_table_iDString operands | ||
869 | */ | ||
870 | status = acpi_ds_create_operands(walk_state, next_op); | ||
871 | if (ACPI_FAILURE(status)) { | ||
872 | return_ACPI_STATUS(status); | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * Resolve the signature_string and oem_iDString | ||
877 | * and oem_table_iDString operands | ||
878 | */ | ||
879 | status = acpi_ex_resolve_operands(op->common.aml_opcode, | ||
880 | ACPI_WALK_OPERANDS, walk_state); | ||
881 | if (ACPI_FAILURE(status)) { | ||
882 | return_ACPI_STATUS(status); | ||
883 | } | ||
884 | |||
885 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, | ||
886 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
887 | 1, "after AcpiExResolveOperands"); | ||
888 | |||
889 | operand = &walk_state->operands[0]; | ||
890 | |||
891 | /* Find the ACPI table */ | ||
892 | |||
893 | status = acpi_tb_find_table(operand[0]->string.pointer, | ||
894 | operand[1]->string.pointer, | ||
895 | operand[2]->string.pointer, &table_index); | ||
896 | if (ACPI_FAILURE(status)) { | ||
897 | return_ACPI_STATUS(status); | ||
898 | } | ||
899 | |||
900 | acpi_ut_remove_reference(operand[0]); | ||
901 | acpi_ut_remove_reference(operand[1]); | ||
902 | acpi_ut_remove_reference(operand[2]); | ||
903 | |||
904 | status = acpi_get_table_by_index(table_index, &table); | ||
905 | if (ACPI_FAILURE(status)) { | ||
906 | return_ACPI_STATUS(status); | ||
907 | } | ||
908 | |||
909 | obj_desc = acpi_ns_get_attached_object(node); | ||
910 | if (!obj_desc) { | ||
911 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
912 | } | ||
913 | |||
914 | obj_desc->region.address = | ||
915 | (acpi_physical_address) ACPI_TO_INTEGER(table); | ||
916 | obj_desc->region.length = table->length; | ||
917 | |||
918 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | ||
919 | obj_desc, | ||
920 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), | ||
774 | obj_desc->region.length)); | 921 | obj_desc->region.length)); |
775 | 922 | ||
776 | /* Now the address and length are valid for this opregion */ | 923 | /* Now the address and length are valid for this opregion */ |
@@ -808,6 +955,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | |||
808 | 955 | ||
809 | /* The first operand (for all of these data objects) is the length */ | 956 | /* The first operand (for all of these data objects) is the length */ |
810 | 957 | ||
958 | /* | ||
959 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
960 | * invoked inside acpi_ds_create_operand. | ||
961 | */ | ||
962 | walk_state->operand_index = walk_state->num_operands; | ||
963 | |||
811 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); | 964 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); |
812 | if (ACPI_FAILURE(status)) { | 965 | if (ACPI_FAILURE(status)) { |
813 | return_ACPI_STATUS(status); | 966 | return_ACPI_STATUS(status); |
@@ -878,6 +1031,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | |||
878 | 1031 | ||
879 | /******************************************************************************* | 1032 | /******************************************************************************* |
880 | * | 1033 | * |
1034 | * FUNCTION: acpi_ds_eval_bank_field_operands | ||
1035 | * | ||
1036 | * PARAMETERS: walk_state - Current walk | ||
1037 | * Op - A valid bank_field Op object | ||
1038 | * | ||
1039 | * RETURN: Status | ||
1040 | * | ||
1041 | * DESCRIPTION: Get bank_field bank_value | ||
1042 | * Called from acpi_ds_exec_end_op during bank_field parse tree walk | ||
1043 | * | ||
1044 | ******************************************************************************/ | ||
1045 | |||
1046 | acpi_status | ||
1047 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | ||
1048 | union acpi_parse_object *op) | ||
1049 | { | ||
1050 | acpi_status status; | ||
1051 | union acpi_operand_object *obj_desc; | ||
1052 | union acpi_operand_object *operand_desc; | ||
1053 | struct acpi_namespace_node *node; | ||
1054 | union acpi_parse_object *next_op; | ||
1055 | union acpi_parse_object *arg; | ||
1056 | |||
1057 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | ||
1058 | |||
1059 | /* | ||
1060 | * This is where we evaluate the bank_value field of the | ||
1061 | * bank_field declaration | ||
1062 | */ | ||
1063 | |||
1064 | /* next_op points to the op that holds the Region */ | ||
1065 | |||
1066 | next_op = op->common.value.arg; | ||
1067 | |||
1068 | /* next_op points to the op that holds the Bank Register */ | ||
1069 | |||
1070 | next_op = next_op->common.next; | ||
1071 | |||
1072 | /* next_op points to the op that holds the Bank Value */ | ||
1073 | |||
1074 | next_op = next_op->common.next; | ||
1075 | |||
1076 | /* | ||
1077 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
1078 | * invoked inside acpi_ds_create_operand. | ||
1079 | * | ||
1080 | * We use walk_state->Operands[0] to store the evaluated bank_value | ||
1081 | */ | ||
1082 | walk_state->operand_index = 0; | ||
1083 | |||
1084 | status = acpi_ds_create_operand(walk_state, next_op, 0); | ||
1085 | if (ACPI_FAILURE(status)) { | ||
1086 | return_ACPI_STATUS(status); | ||
1087 | } | ||
1088 | |||
1089 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | ||
1090 | if (ACPI_FAILURE(status)) { | ||
1091 | return_ACPI_STATUS(status); | ||
1092 | } | ||
1093 | |||
1094 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, | ||
1095 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
1096 | 1, "after AcpiExResolveOperands"); | ||
1097 | |||
1098 | /* | ||
1099 | * Get the bank_value operand and save it | ||
1100 | * (at Top of stack) | ||
1101 | */ | ||
1102 | operand_desc = walk_state->operands[0]; | ||
1103 | |||
1104 | /* Arg points to the start Bank Field */ | ||
1105 | |||
1106 | arg = acpi_ps_get_arg(op, 4); | ||
1107 | while (arg) { | ||
1108 | |||
1109 | /* Ignore OFFSET and ACCESSAS terms here */ | ||
1110 | |||
1111 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | ||
1112 | node = arg->common.node; | ||
1113 | |||
1114 | obj_desc = acpi_ns_get_attached_object(node); | ||
1115 | if (!obj_desc) { | ||
1116 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
1117 | } | ||
1118 | |||
1119 | obj_desc->bank_field.value = | ||
1120 | (u32) operand_desc->integer.value; | ||
1121 | } | ||
1122 | |||
1123 | /* Move to next field in the list */ | ||
1124 | |||
1125 | arg = arg->common.next; | ||
1126 | } | ||
1127 | |||
1128 | acpi_ut_remove_reference(operand_desc); | ||
1129 | return_ACPI_STATUS(status); | ||
1130 | } | ||
1131 | |||
1132 | /******************************************************************************* | ||
1133 | * | ||
881 | * FUNCTION: acpi_ds_exec_begin_control_op | 1134 | * FUNCTION: acpi_ds_exec_begin_control_op |
882 | * | 1135 | * |
883 | * PARAMETERS: walk_list - The list that owns the walk stack | 1136 | * PARAMETERS: walk_list - The list that owns the walk stack |
@@ -1070,8 +1323,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | |||
1070 | * is set to anything other than zero! | 1323 | * is set to anything other than zero! |
1071 | */ | 1324 | */ |
1072 | walk_state->return_desc = walk_state->operands[0]; | 1325 | walk_state->return_desc = walk_state->operands[0]; |
1073 | } else if ((walk_state->results) && | 1326 | } else if (walk_state->result_count) { |
1074 | (walk_state->results->results.num_results > 0)) { | ||
1075 | 1327 | ||
1076 | /* Since we have a real Return(), delete any implicit return */ | 1328 | /* Since we have a real Return(), delete any implicit return */ |
1077 | 1329 | ||