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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: pswalk - Parser routines to walk parsed op tree(s)
  4.  *              $Revision: 58 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "amlcode.h"
  26. #include "acparser.h"
  27. #include "acdispat.h"
  28. #include "acnamesp.h"
  29. #include "acinterp.h"
  30. #define _COMPONENT          ACPI_PARSER
  31.  MODULE_NAME         ("pswalk")
  32. /*******************************************************************************
  33.  *
  34.  * FUNCTION:    Acpi_ps_get_next_walk_op
  35.  *
  36.  * PARAMETERS:  Walk_state          - Current state of the walk
  37.  *              Op                  - Current Op to be walked
  38.  *              Ascending_callback  - Procedure called when Op is complete
  39.  *
  40.  * RETURN:      Status
  41.  *
  42.  * DESCRIPTION: Get the next Op in a walk of the parse tree.
  43.  *
  44.  ******************************************************************************/
  45. acpi_status
  46. acpi_ps_get_next_walk_op (
  47. acpi_walk_state         *walk_state,
  48. acpi_parse_object       *op,
  49. acpi_parse_upwards      ascending_callback)
  50. {
  51. acpi_parse_object       *next;
  52. acpi_parse_object       *parent;
  53. acpi_parse_object       *grand_parent;
  54. acpi_status             status;
  55. FUNCTION_TRACE_PTR ("Ps_get_next_walk_op", op);
  56. /* Check for a argument only if we are descending in the tree */
  57. if (walk_state->next_op_info != NEXT_OP_UPWARD) {
  58. /* Look for an argument or child of the current op */
  59. next = acpi_ps_get_arg (op, 0);
  60. if (next) {
  61. /* Still going downward in tree (Op is not completed yet) */
  62. walk_state->prev_op     = op;
  63. walk_state->next_op     = next;
  64. walk_state->next_op_info = NEXT_OP_DOWNWARD;
  65. return_ACPI_STATUS (AE_OK);
  66. }
  67. /*
  68.  * No more children, this Op is complete.  Save Next and Parent
  69.  * in case the Op object gets deleted by the callback routine
  70.  */
  71. next    = op->next;
  72. parent  = op->parent;
  73. walk_state->op    = op;
  74. walk_state->op_info = acpi_ps_get_opcode_info (op->opcode);
  75. walk_state->opcode = op->opcode;
  76. status = ascending_callback (walk_state);
  77. /*
  78.  * If we are back to the starting point, the walk is complete.
  79.  */
  80. if (op == walk_state->origin) {
  81. /* Reached the point of origin, the walk is complete */
  82. walk_state->prev_op     = op;
  83. walk_state->next_op     = NULL;
  84. return_ACPI_STATUS (status);
  85. }
  86. /*
  87.  * Check for a sibling to the current op.  A sibling means
  88.  * we are still going "downward" in the tree.
  89.  */
  90. if (next) {
  91. /* There is a sibling, it will be next */
  92. walk_state->prev_op     = op;
  93. walk_state->next_op     = next;
  94. walk_state->next_op_info = NEXT_OP_DOWNWARD;
  95. /* Continue downward */
  96. return_ACPI_STATUS (status);
  97. }
  98. /*
  99.  * Drop into the loop below because we are moving upwards in
  100.  * the tree
  101.  */
  102. }
  103. else {
  104. /*
  105.  * We are resuming a walk, and we were (are) going upward in the tree.
  106.  * So, we want to drop into the parent loop below.
  107.  */
  108. parent = op;
  109. }
  110. /*
  111.  * Look for a sibling of the current Op's parent
  112.  * Continue moving up the tree until we find a node that has not been
  113.  * visited, or we get back to where we started.
  114.  */
  115. while (parent) {
  116. /* We are moving up the tree, therefore this parent Op is complete */
  117. grand_parent = parent->parent;
  118. next        = parent->next;
  119. walk_state->op    = parent;
  120. walk_state->op_info = acpi_ps_get_opcode_info (parent->opcode);
  121. walk_state->opcode = parent->opcode;
  122. status = ascending_callback (walk_state);
  123. /*
  124.  * If we are back to the starting point, the walk is complete.
  125.  */
  126. if (parent == walk_state->origin) {
  127. /* Reached the point of origin, the walk is complete */
  128. walk_state->prev_op     = parent;
  129. walk_state->next_op     = NULL;
  130. return_ACPI_STATUS (status);
  131. }
  132. /*
  133.  * If there is a sibling to this parent (it is not the starting point
  134.  * Op), then we will visit it.
  135.  */
  136. if (next) {
  137. /* found sibling of parent */
  138. walk_state->prev_op     = parent;
  139. walk_state->next_op     = next;
  140. walk_state->next_op_info = NEXT_OP_DOWNWARD;
  141. return_ACPI_STATUS (status);
  142. }
  143. /* No siblings, no errors, just move up one more level in the tree */
  144. op                  = parent;
  145. parent              = grand_parent;
  146. walk_state->prev_op = op;
  147. }
  148. /* Got all the way to the top of the tree, we must be done! */
  149. /* However, the code should have terminated in the loop above */
  150. walk_state->next_op     = NULL;
  151. return_ACPI_STATUS (AE_OK);
  152. }
  153. /*******************************************************************************
  154.  *
  155.  * FUNCTION:    Acpi_ps_delete_completed_op
  156.  *
  157.  * PARAMETERS:  State           - Walk state
  158.  *              Op              - Completed op
  159.  *
  160.  * RETURN:      AE_OK
  161.  *
  162.  * DESCRIPTION: Callback function for Acpi_ps_get_next_walk_op(). Used during
  163.  *              Acpi_ps_delete_parse tree to delete Op objects when all sub-objects
  164.  *              have been visited (and deleted.)
  165.  *
  166.  ******************************************************************************/
  167. static acpi_status
  168. acpi_ps_delete_completed_op (
  169. acpi_walk_state         *walk_state)
  170. {
  171. acpi_ps_free_op (walk_state->op);
  172. return (AE_OK);
  173. }
  174. /*******************************************************************************
  175.  *
  176.  * FUNCTION:    Acpi_ps_delete_parse_tree
  177.  *
  178.  * PARAMETERS:  Subtree_root        - Root of tree (or subtree) to delete
  179.  *
  180.  * RETURN:      None
  181.  *
  182.  * DESCRIPTION: Delete a portion of or an entire parse tree.
  183.  *
  184.  ******************************************************************************/
  185. void
  186. acpi_ps_delete_parse_tree (
  187. acpi_parse_object       *subtree_root)
  188. {
  189. acpi_walk_state         *walk_state;
  190. acpi_walk_list          walk_list;
  191. FUNCTION_TRACE_PTR ("Ps_delete_parse_tree", subtree_root);
  192. if (!subtree_root) {
  193. return_VOID;
  194. }
  195. /* Create and initialize a new walk list */
  196. walk_list.walk_state = NULL;
  197. walk_list.acquired_mutex_list.prev = NULL;
  198. walk_list.acquired_mutex_list.next = NULL;
  199. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, &walk_list);
  200. if (!walk_state) {
  201. return_VOID;
  202. }
  203. walk_state->parse_flags         = 0;
  204. walk_state->descending_callback = NULL;
  205. walk_state->ascending_callback  = NULL;
  206. walk_state->origin = subtree_root;
  207. walk_state->next_op = subtree_root;
  208. /* Head downward in the tree */
  209. walk_state->next_op_info = NEXT_OP_DOWNWARD;
  210. /* Visit all nodes in the subtree */
  211. while (walk_state->next_op) {
  212. acpi_ps_get_next_walk_op (walk_state, walk_state->next_op,
  213.  acpi_ps_delete_completed_op);
  214. }
  215. /* We are done with this walk */
  216. acpi_ex_release_all_mutexes ((acpi_operand_object *) &walk_list.acquired_mutex_list);
  217. acpi_ds_delete_walk_state (walk_state);
  218. return_VOID;
  219. }