dsopcode.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:25k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: dsopcode - Dispatcher Op Region support and handling of
  4.  *                         "control" opcodes
  5.  *              $Revision: 56 $
  6.  *
  7.  *****************************************************************************/
  8. /*
  9.  *  Copyright (C) 2000, 2001 R. Byron Moore
  10.  *
  11.  *  This program is free software; you can redistribute it and/or modify
  12.  *  it under the terms of the GNU General Public License as published by
  13.  *  the Free Software Foundation; either version 2 of the License, or
  14.  *  (at your option) any later version.
  15.  *
  16.  *  This program is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *  GNU General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU General Public License
  22.  *  along with this program; if not, write to the Free Software
  23.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  24.  */
  25. #include "acpi.h"
  26. #include "acparser.h"
  27. #include "amlcode.h"
  28. #include "acdispat.h"
  29. #include "acinterp.h"
  30. #include "acnamesp.h"
  31. #include "acevents.h"
  32. #include "actables.h"
  33. #define _COMPONENT          ACPI_DISPATCHER
  34.  MODULE_NAME         ("dsopcode")
  35. /*****************************************************************************
  36.  *
  37.  * FUNCTION:    Acpi_ds_get_buffer_field_arguments
  38.  *
  39.  * PARAMETERS:  Obj_desc        - A valid Buffer_field object
  40.  *
  41.  * RETURN:      Status.
  42.  *
  43.  * DESCRIPTION: Get Buffer_field Buffer and Index. This implements the late
  44.  *              evaluation of these field attributes.
  45.  *
  46.  ****************************************************************************/
  47. acpi_status
  48. acpi_ds_get_buffer_field_arguments (
  49. acpi_operand_object     *obj_desc)
  50. {
  51. acpi_operand_object     *extra_desc;
  52. acpi_namespace_node     *node;
  53. acpi_parse_object       *op;
  54. acpi_parse_object       *field_op;
  55. acpi_status             status;
  56. acpi_table_desc         *table_desc;
  57. acpi_walk_state         *walk_state;
  58. FUNCTION_TRACE_PTR ("Ds_get_buffer_field_arguments", obj_desc);
  59. if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
  60. return_ACPI_STATUS (AE_OK);
  61. }
  62. /* Get the AML pointer (method object) and Buffer_field node */
  63. extra_desc = obj_desc->buffer_field.extra;
  64. node = obj_desc->buffer_field.node;
  65. DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Field]"));
  66. ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Buffer_field JIT Initn",
  67. (char*)&node->name));
  68. /*
  69.  * Allocate a new parser op to be the root of the parsed
  70.  * Op_region tree
  71.  */
  72. op = acpi_ps_alloc_op (AML_SCOPE_OP);
  73. if (!op) {
  74. return (AE_NO_MEMORY);
  75. }
  76. /* Save the Node for use in Acpi_ps_parse_aml */
  77. op->node = acpi_ns_get_parent_object (node);
  78. /* Get a handle to the parent ACPI table */
  79. status = acpi_tb_handle_to_object (node->owner_id, &table_desc);
  80. if (ACPI_FAILURE (status)) {
  81. return_ACPI_STATUS (status);
  82. }
  83. /* Create and initialize a new parser state */
  84. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
  85.    NULL, NULL, NULL);
  86. if (!walk_state) {
  87. return_ACPI_STATUS (AE_NO_MEMORY);
  88. }
  89. status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start,
  90.   extra_desc->extra.aml_length, NULL, NULL, 1);
  91. if (ACPI_FAILURE (status)) {
  92. /* TBD: delete walk state */
  93. return_ACPI_STATUS (status);
  94. }
  95. /* TBD: No Walk flags?? */
  96. walk_state->parse_flags = 0;
  97. /* Pass1: Parse the entire Buffer_field declaration */
  98. status = acpi_ps_parse_aml (walk_state);
  99. if (ACPI_FAILURE (status)) {
  100. acpi_ps_delete_parse_tree (op);
  101. return_ACPI_STATUS (status);
  102. }
  103. /* Get and init the actual Field_unit Op created above */
  104. field_op = op->value.arg;
  105. op->node = node;
  106. field_op = op->value.arg;
  107. field_op->node = node;
  108. acpi_ps_delete_parse_tree (op);
  109. /* Evaluate the address and length arguments for the Op_region */
  110. op = acpi_ps_alloc_op (AML_SCOPE_OP);
  111. if (!op) {
  112. return (AE_NO_MEMORY);
  113. }
  114. op->node = acpi_ns_get_parent_object (node);
  115. /* Create and initialize a new parser state */
  116. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
  117.    NULL, NULL, NULL);
  118. if (!walk_state) {
  119. return_ACPI_STATUS (AE_NO_MEMORY);
  120. }
  121. status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start,
  122.   extra_desc->extra.aml_length, NULL, NULL, 3);
  123. if (ACPI_FAILURE (status)) {
  124. /* TBD: delete walk state */
  125. return_ACPI_STATUS (status);
  126. }
  127. status = acpi_ps_parse_aml (walk_state);
  128. acpi_ps_delete_parse_tree (op);
  129. /*
  130.  * The pseudo-method object is no longer needed since the region is
  131.  * now initialized
  132.  */
  133. acpi_ut_remove_reference (obj_desc->buffer_field.extra);
  134. obj_desc->buffer_field.extra = NULL;
  135. return_ACPI_STATUS (status);
  136. }
  137. /*****************************************************************************
  138.  *
  139.  * FUNCTION:    Acpi_ds_get_region_arguments
  140.  *
  141.  * PARAMETERS:  Obj_desc        - A valid region object
  142.  *
  143.  * RETURN:      Status.
  144.  *
  145.  * DESCRIPTION: Get region address and length.  This implements the late
  146.  *              evaluation of these region attributes.
  147.  *
  148.  ****************************************************************************/
  149. acpi_status
  150. acpi_ds_get_region_arguments (
  151. acpi_operand_object     *obj_desc)
  152. {
  153. acpi_operand_object     *extra_desc = NULL;
  154. acpi_namespace_node     *node;
  155. acpi_parse_object       *op;
  156. acpi_parse_object       *region_op;
  157. acpi_status             status;
  158. acpi_table_desc         *table_desc;
  159. acpi_walk_state         *walk_state;
  160. FUNCTION_TRACE_PTR ("Ds_get_region_arguments", obj_desc);
  161. if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
  162. return_ACPI_STATUS (AE_OK);
  163. }
  164. /* Get the AML pointer (method object) and region node */
  165. extra_desc = obj_desc->region.extra;
  166. node = obj_desc->region.node;
  167. DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Operation Region]"));
  168. ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Op_region Init at AML %pn",
  169. (char*)&node->name, extra_desc->extra.aml_start));
  170. /*
  171.  * Allocate a new parser op to be the root of the parsed
  172.  * Op_region tree
  173.  */
  174. op = acpi_ps_alloc_op (AML_SCOPE_OP);
  175. if (!op) {
  176. return (AE_NO_MEMORY);
  177. }
  178. /* Save the Node for use in Acpi_ps_parse_aml */
  179. op->node = acpi_ns_get_parent_object (node);
  180. /* Get a handle to the parent ACPI table */
  181. status = acpi_tb_handle_to_object (node->owner_id, &table_desc);
  182. if (ACPI_FAILURE (status)) {
  183. return_ACPI_STATUS (status);
  184. }
  185. /* Create and initialize a new parser state */
  186. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
  187.    op, NULL, NULL);
  188. if (!walk_state) {
  189. return_ACPI_STATUS (AE_NO_MEMORY);
  190. }
  191. status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start,
  192.   extra_desc->extra.aml_length, NULL, NULL, 1);
  193. if (ACPI_FAILURE (status)) {
  194. /* TBD: delete walk state */
  195. return_ACPI_STATUS (status);
  196. }
  197. /* TBD: No Walk flags?? */
  198. walk_state->parse_flags = 0;
  199. /* Parse the entire Op_region declaration, creating a parse tree */
  200. status = acpi_ps_parse_aml (walk_state);
  201. if (ACPI_FAILURE (status)) {
  202. acpi_ps_delete_parse_tree (op);
  203. return_ACPI_STATUS (status);
  204. }
  205. /* Get and init the actual Region_op created above */
  206. region_op = op->value.arg;
  207. op->node = node;
  208. region_op = op->value.arg;
  209. region_op->node = node;
  210. acpi_ps_delete_parse_tree (op);
  211. /* Evaluate the address and length arguments for the Op_region */
  212. op = acpi_ps_alloc_op (AML_SCOPE_OP);
  213. if (!op) {
  214. return (AE_NO_MEMORY);
  215. }
  216. op->node = acpi_ns_get_parent_object (node);
  217. /* Create and initialize a new parser state */
  218. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
  219.    op, NULL, NULL);
  220. if (!walk_state) {
  221. return_ACPI_STATUS (AE_NO_MEMORY);
  222. }
  223. status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start,
  224.   extra_desc->extra.aml_length, NULL, NULL, 3);
  225. if (ACPI_FAILURE (status)) {
  226. /* TBD: delete walk state */
  227. return_ACPI_STATUS (status);
  228. }
  229. status = acpi_ps_parse_aml (walk_state);
  230. acpi_ps_delete_parse_tree (op);
  231. return_ACPI_STATUS (status);
  232. }
  233. /*****************************************************************************
  234.  *
  235.  * FUNCTION:    Acpi_ds_initialize_region
  236.  *
  237.  * PARAMETERS:  Op              - A valid region Op object
  238.  *
  239.  * RETURN:      Status
  240.  *
  241.  * DESCRIPTION:
  242.  *
  243.  ****************************************************************************/
  244. acpi_status
  245. acpi_ds_initialize_region (
  246. acpi_handle             obj_handle)
  247. {
  248. acpi_operand_object     *obj_desc;
  249. acpi_status             status;
  250. obj_desc = acpi_ns_get_attached_object (obj_handle);
  251. /* Namespace is NOT locked */
  252. status = acpi_ev_initialize_region (obj_desc, FALSE);
  253. return (status);
  254. }
  255. /*****************************************************************************
  256.  *
  257.  * FUNCTION:    Acpi_ds_eval_buffer_field_operands
  258.  *
  259.  * PARAMETERS:  Op              - A valid Buffer_field Op object
  260.  *
  261.  * RETURN:      Status
  262.  *
  263.  * DESCRIPTION: Get Buffer_field Buffer and Index
  264.  *              Called from Acpi_ds_exec_end_op during Buffer_field parse tree walk
  265.  *
  266.  * ACPI SPECIFICATION REFERENCES:
  267.  *  Each of the Buffer Field opcodes is defined as specified in in-line
  268.  *  comments below. For each one, use the following definitions.
  269.  *
  270.  *  Def_bit_field   :=  Bit_field_op    Src_buf Bit_idx Destination
  271.  *  Def_byte_field  :=  Byte_field_op   Src_buf Byte_idx Destination
  272.  *  Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string
  273.  *  Def_dWord_field :=  DWord_field_op  Src_buf Byte_idx Destination
  274.  *  Def_word_field  :=  Word_field_op   Src_buf Byte_idx Destination
  275.  *  Bit_index       :=  Term_arg=>Integer
  276.  *  Byte_index      :=  Term_arg=>Integer
  277.  *  Destination     :=  Name_string
  278.  *  Num_bits        :=  Term_arg=>Integer
  279.  *  Source_buf      :=  Term_arg=>Buffer
  280.  *
  281.  ****************************************************************************/
  282. acpi_status
  283. acpi_ds_eval_buffer_field_operands (
  284. acpi_walk_state         *walk_state,
  285. acpi_parse_object       *op)
  286. {
  287. acpi_status             status;
  288. acpi_operand_object     *obj_desc;
  289. acpi_namespace_node     *node;
  290. acpi_parse_object       *next_op;
  291. u32                     offset;
  292. u32                     bit_offset;
  293. u32                     bit_count;
  294. u8                      field_flags;
  295. acpi_operand_object     *res_desc = NULL;
  296. acpi_operand_object     *cnt_desc = NULL;
  297. acpi_operand_object     *off_desc = NULL;
  298. acpi_operand_object     *src_desc = NULL;
  299. FUNCTION_TRACE_PTR ("Ds_eval_buffer_field_operands", op);
  300. /*
  301.  * This is where we evaluate the address and length fields of the
  302.  * Create_xxx_field declaration
  303.  */
  304. node =  op->node;
  305. /* Next_op points to the op that holds the Buffer */
  306. next_op = op->value.arg;
  307. /* Acpi_evaluate/create the address and length operands */
  308. status = acpi_ds_create_operands (walk_state, next_op);
  309. if (ACPI_FAILURE (status)) {
  310. return_ACPI_STATUS (status);
  311. }
  312. obj_desc = acpi_ns_get_attached_object (node);
  313. if (!obj_desc) {
  314. return_ACPI_STATUS (AE_NOT_EXIST);
  315. }
  316. /* Resolve the operands */
  317. status = acpi_ex_resolve_operands (op->opcode, WALK_OPERANDS, walk_state);
  318. DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE, acpi_ps_get_opcode_name (op->opcode),
  319.   walk_state->num_operands, "after Acpi_ex_resolve_operands");
  320. if (ACPI_FAILURE (status)) {
  321. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)n",
  322. acpi_ps_get_opcode_name (op->opcode), status));
  323. goto cleanup;
  324. }
  325. /* Get the operands */
  326. if (AML_CREATE_FIELD_OP == op->opcode) {
  327. res_desc = walk_state->operands[3];
  328. cnt_desc = walk_state->operands[2];
  329. }
  330. else {
  331. res_desc = walk_state->operands[2];
  332. }
  333. off_desc = walk_state->operands[1];
  334. src_desc = walk_state->operands[0];
  335. offset = (u32) off_desc->integer.value;
  336. /*
  337.  * If Res_desc is a Name, it will be a direct name pointer after
  338.  * Acpi_ex_resolve_operands()
  339.  */
  340. if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) {
  341. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination must be a Noden",
  342. acpi_ps_get_opcode_name (op->opcode)));
  343. status = AE_AML_OPERAND_TYPE;
  344. goto cleanup;
  345. }
  346. /*
  347.  * Setup the Bit offsets and counts, according to the opcode
  348.  */
  349. switch (op->opcode) {
  350. /* Def_create_field */
  351. case AML_CREATE_FIELD_OP:
  352. /* Offset is in bits, count is in bits */
  353. bit_offset  = offset;
  354. bit_count   = (u32) cnt_desc->integer.value;
  355. field_flags = ACCESS_BYTE_ACC;
  356. break;
  357. /* Def_create_bit_field */
  358. case AML_CREATE_BIT_FIELD_OP:
  359. /* Offset is in bits, Field is one bit */
  360. bit_offset  = offset;
  361. bit_count   = 1;
  362. field_flags = ACCESS_BYTE_ACC;
  363. break;
  364. /* Def_create_byte_field */
  365. case AML_CREATE_BYTE_FIELD_OP:
  366. /* Offset is in bytes, field is one byte */
  367. bit_offset  = 8 * offset;
  368. bit_count   = 8;
  369. field_flags = ACCESS_BYTE_ACC;
  370. break;
  371. /* Def_create_word_field */
  372. case AML_CREATE_WORD_FIELD_OP:
  373. /* Offset is in bytes, field is one word */
  374. bit_offset  = 8 * offset;
  375. bit_count   = 16;
  376. field_flags = ACCESS_WORD_ACC;
  377. break;
  378. /* Def_create_dWord_field */
  379. case AML_CREATE_DWORD_FIELD_OP:
  380. /* Offset is in bytes, field is one dword */
  381. bit_offset  = 8 * offset;
  382. bit_count   = 32;
  383. field_flags = ACCESS_DWORD_ACC;
  384. break;
  385. /* Def_create_qWord_field */
  386. case AML_CREATE_QWORD_FIELD_OP:
  387. /* Offset is in bytes, field is one qword */
  388. bit_offset  = 8 * offset;
  389. bit_count   = 64;
  390. field_flags = ACCESS_QWORD_ACC;
  391. break;
  392. default:
  393. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  394. "Internal error - unknown field creation opcode %02xn",
  395. op->opcode));
  396. status = AE_AML_BAD_OPCODE;
  397. goto cleanup;
  398. }
  399. /*
  400.  * Setup field according to the object type
  401.  */
  402. switch (src_desc->common.type) {
  403. /* Source_buff :=  Term_arg=>Buffer */
  404. case ACPI_TYPE_BUFFER:
  405. if ((bit_offset + bit_count) >
  406. (8 * (u32) src_desc->buffer.length)) {
  407. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  408. "Field size %d exceeds Buffer size %d (bits)n",
  409.  bit_offset + bit_count, 8 * (u32) src_desc->buffer.length));
  410. status = AE_AML_BUFFER_LIMIT;
  411. goto cleanup;
  412. }
  413. /*
  414.  * Initialize areas of the field object that are common to all fields
  415.  * For Field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE)
  416.  */
  417. status = acpi_ex_prep_common_field_object (obj_desc, field_flags,
  418.   bit_offset, bit_count);
  419. if (ACPI_FAILURE (status)) {
  420. return_ACPI_STATUS (status);
  421. }
  422. obj_desc->buffer_field.buffer_obj = src_desc;
  423. /* Reference count for Src_desc inherits Obj_desc count */
  424. src_desc->common.reference_count = (u16) (src_desc->common.reference_count +
  425.   obj_desc->common.reference_count);
  426. break;
  427. /* Improper object type */
  428. default:
  429. if ((src_desc->common.type > (u8) INTERNAL_TYPE_REFERENCE) || !acpi_ut_valid_object_type (src_desc->common.type)) /* TBD: This line MUST be a single line until Acpi_src can handle it (block deletion) */ {
  430. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  431. "Tried to create field in invalid object type %Xn",
  432. src_desc->common.type));
  433. }
  434. else {
  435. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  436. "Tried to create field in improper object type - %sn",
  437. acpi_ut_get_type_name (src_desc->common.type)));
  438. }
  439. status = AE_AML_OPERAND_TYPE;
  440. goto cleanup;
  441. }
  442. if (AML_CREATE_FIELD_OP == op->opcode) {
  443. /* Delete object descriptor unique to Create_field */
  444. acpi_ut_remove_reference (cnt_desc);
  445. cnt_desc = NULL;
  446. }
  447. cleanup:
  448. /* Always delete the operands */
  449. acpi_ut_remove_reference (off_desc);
  450. acpi_ut_remove_reference (src_desc);
  451. if (AML_CREATE_FIELD_OP == op->opcode) {
  452. acpi_ut_remove_reference (cnt_desc);
  453. }
  454. /* On failure, delete the result descriptor */
  455. if (ACPI_FAILURE (status)) {
  456. acpi_ut_remove_reference (res_desc); /* Result descriptor */
  457. }
  458. else {
  459. /* Now the address and length are valid for this Buffer_field */
  460. obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
  461. }
  462. return_ACPI_STATUS (status);
  463. }
  464. /*****************************************************************************
  465.  *
  466.  * FUNCTION:    Acpi_ds_eval_region_operands
  467.  *
  468.  * PARAMETERS:  Op              - A valid region Op object
  469.  *
  470.  * RETURN:      Status
  471.  *
  472.  * DESCRIPTION: Get region address and length
  473.  *              Called from Acpi_ds_exec_end_op during Op_region parse tree walk
  474.  *
  475.  ****************************************************************************/
  476. acpi_status
  477. acpi_ds_eval_region_operands (
  478. acpi_walk_state         *walk_state,
  479. acpi_parse_object       *op)
  480. {
  481. acpi_status             status;
  482. acpi_operand_object     *obj_desc;
  483. acpi_operand_object     *operand_desc;
  484. acpi_namespace_node     *node;
  485. acpi_parse_object       *next_op;
  486. FUNCTION_TRACE_PTR ("Ds_eval_region_operands", op);
  487. /*
  488.  * This is where we evaluate the address and length fields of the Op_region declaration
  489.  */
  490. node =  op->node;
  491. /* Next_op points to the op that holds the Space_iD */
  492. next_op = op->value.arg;
  493. /* Next_op points to address op */
  494. next_op = next_op->next;
  495. /* Acpi_evaluate/create the address and length operands */
  496. status = acpi_ds_create_operands (walk_state, next_op);
  497. if (ACPI_FAILURE (status)) {
  498. return_ACPI_STATUS (status);
  499. }
  500. /* Resolve the length and address operands to numbers */
  501. status = acpi_ex_resolve_operands (op->opcode, WALK_OPERANDS, walk_state);
  502. if (ACPI_FAILURE (status)) {
  503. return_ACPI_STATUS (status);
  504. }
  505. DUMP_OPERANDS (WALK_OPERANDS, IMODE_EXECUTE,
  506.   acpi_ps_get_opcode_name (op->opcode),
  507.   1, "after Acpi_ex_resolve_operands");
  508. obj_desc = acpi_ns_get_attached_object (node);
  509. if (!obj_desc) {
  510. return_ACPI_STATUS (AE_NOT_EXIST);
  511. }
  512. /*
  513.  * Get the length operand and save it
  514.  * (at Top of stack)
  515.  */
  516. operand_desc = walk_state->operands[walk_state->num_operands - 1];
  517. obj_desc->region.length = (u32) operand_desc->integer.value;
  518. acpi_ut_remove_reference (operand_desc);
  519. /*
  520.  * Get the address and save it
  521.  * (at top of stack - 1)
  522.  */
  523. operand_desc = walk_state->operands[walk_state->num_operands - 2];
  524. obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value;
  525. acpi_ut_remove_reference (operand_desc);
  526. ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Rgn_obj %p Addr %8.8X%8.8X Len %Xn",
  527. obj_desc, HIDWORD(obj_desc->region.address), LODWORD(obj_desc->region.address),
  528. obj_desc->region.length));
  529. /* Now the address and length are valid for this opregion */
  530. obj_desc->region.flags |= AOPOBJ_DATA_VALID;
  531. return_ACPI_STATUS (status);
  532. }
  533. /*******************************************************************************
  534.  *
  535.  * FUNCTION:    Acpi_ds_exec_begin_control_op
  536.  *
  537.  * PARAMETERS:  Walk_list       - The list that owns the walk stack
  538.  *              Op              - The control Op
  539.  *
  540.  * RETURN:      Status
  541.  *
  542.  * DESCRIPTION: Handles all control ops encountered during control method
  543.  *              execution.
  544.  *
  545.  ******************************************************************************/
  546. acpi_status
  547. acpi_ds_exec_begin_control_op (
  548. acpi_walk_state         *walk_state,
  549. acpi_parse_object       *op)
  550. {
  551. acpi_status             status = AE_OK;
  552. acpi_generic_state      *control_state;
  553. PROC_NAME ("Ds_exec_begin_control_op");
  554. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%pn", op,
  555. op->opcode, walk_state));
  556. switch (op->opcode) {
  557. case AML_IF_OP:
  558. case AML_WHILE_OP:
  559. /*
  560.  * IF/WHILE: Create a new control state to manage these
  561.  * constructs. We need to manage these as a stack, in order
  562.  * to handle nesting.
  563.  */
  564. control_state = acpi_ut_create_control_state ();
  565. if (!control_state) {
  566. status = AE_NO_MEMORY;
  567. break;
  568. }
  569. acpi_ut_push_generic_state (&walk_state->control_state, control_state);
  570. /*
  571.  * Save a pointer to the predicate for multiple executions
  572.  * of a loop
  573.  */
  574. walk_state->control_state->control.aml_predicate_start =
  575.  walk_state->parser_state.aml - 1;
  576.  /* TBD: can this be removed? */
  577.  /*Acpi_ps_pkg_length_encoding_size (GET8 (Walk_state->Parser_state->Aml));*/
  578. break;
  579. case AML_ELSE_OP:
  580. /* Predicate is in the state object */
  581. /* If predicate is true, the IF was executed, ignore ELSE part */
  582. if (walk_state->last_predicate) {
  583. status = AE_CTRL_TRUE;
  584. }
  585. break;
  586. case AML_RETURN_OP:
  587. break;
  588. default:
  589. break;
  590. }
  591. return (status);
  592. }
  593. /*******************************************************************************
  594.  *
  595.  * FUNCTION:    Acpi_ds_exec_end_control_op
  596.  *
  597.  * PARAMETERS:  Walk_list       - The list that owns the walk stack
  598.  *              Op              - The control Op
  599.  *
  600.  * RETURN:      Status
  601.  *
  602.  * DESCRIPTION: Handles all control ops encountered during control method
  603.  *              execution.
  604.  *
  605.  *
  606.  ******************************************************************************/
  607. acpi_status
  608. acpi_ds_exec_end_control_op (
  609. acpi_walk_state         *walk_state,
  610. acpi_parse_object       *op)
  611. {
  612. acpi_status             status = AE_OK;
  613. acpi_generic_state      *control_state;
  614. PROC_NAME ("Ds_exec_end_control_op");
  615. switch (op->opcode) {
  616. case AML_IF_OP:
  617. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%pn", op));
  618. /*
  619.  * Save the result of the predicate in case there is an
  620.  * ELSE to come
  621.  */
  622. walk_state->last_predicate =
  623. (u8) walk_state->control_state->common.value;
  624. /*
  625.  * Pop the control state that was created at the start
  626.  * of the IF and free it
  627.  */
  628. control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
  629. acpi_ut_delete_generic_state (control_state);
  630. break;
  631. case AML_ELSE_OP:
  632. break;
  633. case AML_WHILE_OP:
  634. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%pn", op));
  635. if (walk_state->control_state->common.value) {
  636. /* Predicate was true, go back and evaluate it again! */
  637. status = AE_CTRL_PENDING;
  638. }
  639. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%pn", op));
  640. /* Pop this control state and free it */
  641. control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
  642. walk_state->aml_last_while = control_state->control.aml_predicate_start;
  643. acpi_ut_delete_generic_state (control_state);
  644. break;
  645. case AML_RETURN_OP:
  646. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  647. "[RETURN_OP] Op=%p Arg=%pn",op, op->value.arg));
  648. /*
  649.  * One optional operand -- the return value
  650.  * It can be either an immediate operand or a result that
  651.  * has been bubbled up the tree
  652.  */
  653. if (op->value.arg) {
  654. /* Return statement has an immediate operand */
  655. status = acpi_ds_create_operands (walk_state, op->value.arg);
  656. if (ACPI_FAILURE (status)) {
  657. return (status);
  658. }
  659. /*
  660.  * If value being returned is a Reference (such as
  661.  * an arg or local), resolve it now because it may
  662.  * cease to exist at the end of the method.
  663.  */
  664. status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
  665. if (ACPI_FAILURE (status)) {
  666. return (status);
  667. }
  668. /*
  669.  * Get the return value and save as the last result
  670.  * value.  This is the only place where Walk_state->Return_desc
  671.  * is set to anything other than zero!
  672.  */
  673. walk_state->return_desc = walk_state->operands[0];
  674. }
  675. else if ((walk_state->results) &&
  676.  (walk_state->results->results.num_results > 0)) {
  677. /*
  678.  * The return value has come from a previous calculation.
  679.  *
  680.  * If value being returned is a Reference (such as
  681.  * an arg or local), resolve it now because it may
  682.  * cease to exist at the end of the method.
  683.  *
  684.  * Allow references created by the Index operator to return unchanged.
  685.  */
  686. if (VALID_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc [0], ACPI_DESC_TYPE_INTERNAL) &&
  687. ((walk_state->results->results.obj_desc [0])->common.type == INTERNAL_TYPE_REFERENCE) &&
  688. ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) {
  689. status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state);
  690. if (ACPI_FAILURE (status)) {
  691. return (status);
  692. }
  693. }
  694. walk_state->return_desc = walk_state->results->results.obj_desc [0];
  695. }
  696. else {
  697. /* No return operand */
  698. if (walk_state->num_operands) {
  699. acpi_ut_remove_reference (walk_state->operands [0]);
  700. }
  701. walk_state->operands [0]    = NULL;
  702. walk_state->num_operands    = 0;
  703. walk_state->return_desc     = NULL;
  704. }
  705. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  706. "Completed RETURN_OP State=%p, Ret_val=%pn",
  707. walk_state, walk_state->return_desc));
  708. /* End the control method execution right now */
  709. status = AE_CTRL_TERMINATE;
  710. break;
  711. case AML_NOOP_OP:
  712. /* Just do nothing! */
  713. break;
  714. case AML_BREAK_POINT_OP:
  715. /* Call up to the OS service layer to handle this */
  716. acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode");
  717. /* If and when it returns, all done. */
  718. break;
  719. case AML_BREAK_OP:
  720. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  721. "Break to end of current package, Op=%pn", op));
  722. /* TBD: update behavior for ACPI 2.0 */
  723. /*
  724.  * As per the ACPI specification:
  725.  *      "The break operation causes the current package
  726.  *          execution to complete"
  727.  *      "Break -- Stop executing the current code package
  728.  *          at this point"
  729.  *
  730.  * Returning AE_FALSE here will cause termination of
  731.  * the current package, and execution will continue one
  732.  * level up, starting with the completion of the parent Op.
  733.  */
  734. status = AE_CTRL_FALSE;
  735. break;
  736. case AML_CONTINUE_OP: /* ACPI 2.0 */
  737. status = AE_NOT_IMPLEMENTED;
  738. break;
  739. default:
  740. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%pn",
  741. op->opcode, op));
  742. status = AE_AML_BAD_OPCODE;
  743. break;
  744. }
  745. return (status);
  746. }