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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
  4.  *              $Revision: 69 $
  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 "acparser.h"
  26. #include "amlcode.h"
  27. #include "acdispat.h"
  28. #include "acinterp.h"
  29. #include "acnamesp.h"
  30. #include "actables.h"
  31. #include "acdebug.h"
  32. #define _COMPONENT          ACPI_DISPATCHER
  33.  MODULE_NAME         ("dsmethod")
  34. /*******************************************************************************
  35.  *
  36.  * FUNCTION:    Acpi_ds_parse_method
  37.  *
  38.  * PARAMETERS:  Obj_handle      - Node of the method
  39.  *              Level           - Current nesting level
  40.  *              Context         - Points to a method counter
  41.  *              Return_value    - Not used
  42.  *
  43.  * RETURN:      Status
  44.  *
  45.  * DESCRIPTION: Call the parser and parse the AML that is
  46.  *              associated with the method.
  47.  *
  48.  * MUTEX:       Assumes parser is locked
  49.  *
  50.  ******************************************************************************/
  51. acpi_status
  52. acpi_ds_parse_method (
  53. acpi_handle             obj_handle)
  54. {
  55. acpi_status             status;
  56. acpi_operand_object     *obj_desc;
  57. acpi_parse_object       *op;
  58. acpi_namespace_node     *node;
  59. acpi_owner_id           owner_id;
  60. acpi_walk_state         *walk_state;
  61. FUNCTION_TRACE_PTR ("Ds_parse_method", obj_handle);
  62. /* Parameter Validation */
  63. if (!obj_handle) {
  64. return_ACPI_STATUS (AE_NULL_ENTRY);
  65. }
  66. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Parsing [%4.4s] **** Named_obj=%pn",
  67. (char*)&((acpi_namespace_node *)obj_handle)->name, obj_handle));
  68. /* Extract the method object from the method Node */
  69. node = (acpi_namespace_node *) obj_handle;
  70. obj_desc = node->object;
  71. if (!obj_desc) {
  72. return_ACPI_STATUS (AE_NULL_OBJECT);
  73. }
  74. /* Create a mutex for the method if there is a concurrency limit */
  75. if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) &&
  76. (!obj_desc->method.semaphore)) {
  77. status = acpi_os_create_semaphore (obj_desc->method.concurrency,
  78.    obj_desc->method.concurrency,
  79.    &obj_desc->method.semaphore);
  80. if (ACPI_FAILURE (status)) {
  81. return_ACPI_STATUS (status);
  82. }
  83. }
  84. /*
  85.  * Allocate a new parser op to be the root of the parsed
  86.  * method tree
  87.  */
  88. op = acpi_ps_alloc_op (AML_METHOD_OP);
  89. if (!op) {
  90. return_ACPI_STATUS (AE_NO_MEMORY);
  91. }
  92. /* Init new op with the method name and pointer back to the Node */
  93. acpi_ps_set_name (op, node->name);
  94. op->node = node;
  95. /* Create and initialize a new walk state */
  96. walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT,
  97.    NULL, NULL, NULL);
  98. if (!walk_state) {
  99. return_ACPI_STATUS (AE_NO_MEMORY);
  100. }
  101. status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start,
  102.   obj_desc->method.aml_length, NULL, NULL, 1);
  103. if (ACPI_FAILURE (status)) {
  104. /* TBD: delete walk state */
  105. return_ACPI_STATUS (status);
  106. }
  107. /*
  108.  * Parse the method, first pass
  109.  *
  110.  * The first pass load is where newly declared named objects are
  111.  * added into the namespace.  Actual evaluation of
  112.  * the named objects (what would be called a "second
  113.  * pass") happens during the actual execution of the
  114.  * method so that operands to the named objects can
  115.  * take on dynamic run-time values.
  116.  */
  117. status = acpi_ps_parse_aml (walk_state);
  118. if (ACPI_FAILURE (status)) {
  119. return_ACPI_STATUS (status);
  120. }
  121. /* Get a new Owner_id for objects created by this method */
  122. owner_id = acpi_ut_allocate_owner_id (OWNER_TYPE_METHOD);
  123. obj_desc->method.owning_id = owner_id;
  124. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** [%4.4s] Parsed **** Named_obj=%p Op=%pn",
  125. (char*)&((acpi_namespace_node *)obj_handle)->name, obj_handle, op));
  126. acpi_ps_delete_parse_tree (op);
  127. return_ACPI_STATUS (status);
  128. }
  129. /*******************************************************************************
  130.  *
  131.  * FUNCTION:    Acpi_ds_begin_method_execution
  132.  *
  133.  * PARAMETERS:  Method_node         - Node of the method
  134.  *              Obj_desc            - The method object
  135.  *              Calling_method_node - Caller of this method (if non-null)
  136.  *
  137.  * RETURN:      Status
  138.  *
  139.  * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
  140.  *              increments the thread count, and waits at the method semaphore
  141.  *              for clearance to execute.
  142.  *
  143.  * MUTEX:       Locks/unlocks parser.
  144.  *
  145.  ******************************************************************************/
  146. acpi_status
  147. acpi_ds_begin_method_execution (
  148. acpi_namespace_node     *method_node,
  149. acpi_operand_object     *obj_desc,
  150. acpi_namespace_node     *calling_method_node)
  151. {
  152. acpi_status             status = AE_OK;
  153. FUNCTION_TRACE_PTR ("Ds_begin_method_execution", method_node);
  154. if (!method_node) {
  155. return_ACPI_STATUS (AE_NULL_ENTRY);
  156. }
  157. /*
  158.  * If there is a concurrency limit on this method, we need to
  159.  * obtain a unit from the method semaphore.
  160.  */
  161. if (obj_desc->method.semaphore) {
  162. /*
  163.  * Allow recursive method calls, up to the reentrancy/concurrency
  164.  * limit imposed by the SERIALIZED rule and the Sync_level method
  165.  * parameter.
  166.  *
  167.  * The point of this code is to avoid permanently blocking a
  168.  * thread that is making recursive method calls.
  169.  */
  170. if (method_node == calling_method_node) {
  171. if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
  172. return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
  173. }
  174. }
  175. /*
  176.  * Get a unit from the method semaphore. This releases the
  177.  * interpreter if we block
  178.  */
  179. status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
  180.  WAIT_FOREVER);
  181. }
  182. /*
  183.  * Increment the method parse tree thread count since it has been
  184.  * reentered one more time (even if it is the same thread)
  185.  */
  186. obj_desc->method.thread_count++;
  187. return_ACPI_STATUS (status);
  188. }
  189. /*******************************************************************************
  190.  *
  191.  * FUNCTION:    Acpi_ds_call_control_method
  192.  *
  193.  * PARAMETERS:  Walk_state          - Current state of the walk
  194.  *              Op                  - Current Op to be walked
  195.  *
  196.  * RETURN:      Status
  197.  *
  198.  * DESCRIPTION: Transfer execution to a called control method
  199.  *
  200.  ******************************************************************************/
  201. acpi_status
  202. acpi_ds_call_control_method (
  203. acpi_walk_list          *walk_list,
  204. acpi_walk_state         *this_walk_state,
  205. acpi_parse_object       *op)  /* TBD: This operand is obsolete */
  206. {
  207. acpi_status             status;
  208. acpi_namespace_node     *method_node;
  209. acpi_operand_object     *obj_desc;
  210. acpi_walk_state         *next_walk_state;
  211. u32                     i;
  212. FUNCTION_TRACE_PTR ("Ds_call_control_method", this_walk_state);
  213. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%pn",
  214. this_walk_state->prev_op, this_walk_state));
  215. /*
  216.  * Get the namespace entry for the control method we are about to call
  217.  */
  218. method_node = this_walk_state->method_call_node;
  219. if (!method_node) {
  220. return_ACPI_STATUS (AE_NULL_ENTRY);
  221. }
  222. obj_desc = acpi_ns_get_attached_object (method_node);
  223. if (!obj_desc) {
  224. return_ACPI_STATUS (AE_NULL_OBJECT);
  225. }
  226. /* Init for new method, wait on concurrency semaphore */
  227. status = acpi_ds_begin_method_execution (method_node, obj_desc,
  228.   this_walk_state->method_node);
  229. if (ACPI_FAILURE (status)) {
  230. return_ACPI_STATUS (status);
  231. }
  232. /* 1) Parse: Create a new walk state for the preempting walk */
  233. next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
  234.   op, obj_desc, NULL);
  235. if (!next_walk_state) {
  236. return_ACPI_STATUS (AE_NO_MEMORY);
  237. goto cleanup;
  238. }
  239. /* Create and init a Root Node */
  240. op = acpi_ps_alloc_op (AML_SCOPE_OP);
  241. if (!op) {
  242. status = AE_NO_MEMORY;
  243. goto cleanup;
  244. }
  245. status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
  246.   obj_desc->method.aml_start, obj_desc->method.aml_length,
  247.   NULL, NULL, 1);
  248. if (ACPI_FAILURE (status)) {
  249. /* TBD: delete walk state */
  250. goto cleanup;
  251. }
  252. /* Begin AML parse */
  253. status = acpi_ps_parse_aml (next_walk_state);
  254. acpi_ps_delete_parse_tree (op);
  255. /* 2) Execute: Create a new state for the preempting walk */
  256. next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
  257.   NULL, obj_desc, walk_list);
  258. if (!next_walk_state) {
  259. status = AE_NO_MEMORY;
  260. goto cleanup;
  261. }
  262. /*
  263.  * The resolved arguments were put on the previous walk state's operand
  264.  * stack.  Operands on the previous walk state stack always
  265.  * start at index 0.
  266.  * Null terminate the list of arguments
  267.  */
  268. this_walk_state->operands [this_walk_state->num_operands] = NULL;
  269. status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
  270.   obj_desc->method.aml_start, obj_desc->method.aml_length,
  271.   &this_walk_state->operands[0], NULL, 3);
  272. if (ACPI_FAILURE (status)) {
  273. goto cleanup;
  274. }
  275. /*
  276.  * Delete the operands on the previous walkstate operand stack
  277.  * (they were copied to new objects)
  278.  */
  279. for (i = 0; i < obj_desc->method.param_count; i++) {
  280. acpi_ut_remove_reference (this_walk_state->operands [i]);
  281. this_walk_state->operands [i] = NULL;
  282. }
  283. /* Clear the operand stack */
  284. this_walk_state->num_operands = 0;
  285. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%pn",
  286. next_walk_state));
  287. return_ACPI_STATUS (AE_OK);
  288. /* On error, we must delete the new walk state */
  289. cleanup:
  290. acpi_ds_terminate_control_method (next_walk_state);
  291. acpi_ds_delete_walk_state (next_walk_state);
  292. return_ACPI_STATUS (status);
  293. }
  294. /*******************************************************************************
  295.  *
  296.  * FUNCTION:    Acpi_ds_restart_control_method
  297.  *
  298.  * PARAMETERS:  Walk_state          - State of the method when it was preempted
  299.  *              Op                  - Pointer to new current op
  300.  *
  301.  * RETURN:      Status
  302.  *
  303.  * DESCRIPTION: Restart a method that was preempted
  304.  *
  305.  ******************************************************************************/
  306. acpi_status
  307. acpi_ds_restart_control_method (
  308. acpi_walk_state         *walk_state,
  309. acpi_operand_object     *return_desc)
  310. {
  311. acpi_status             status;
  312. FUNCTION_TRACE_PTR ("Ds_restart_control_method", walk_state);
  313. if (return_desc) {
  314. if (walk_state->return_used) {
  315. /*
  316.  * Get the return value (if any) from the previous method.
  317.  * NULL if no return value
  318.  */
  319. status = acpi_ds_result_push (return_desc, walk_state);
  320. if (ACPI_FAILURE (status)) {
  321. acpi_ut_remove_reference (return_desc);
  322. return_ACPI_STATUS (status);
  323. }
  324. }
  325. else {
  326. /*
  327.  * Delete the return value if it will not be used by the
  328.  * calling method
  329.  */
  330. acpi_ut_remove_reference (return_desc);
  331. }
  332. }
  333. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  334. "Method=%p Return=%p Return_used?=%X Res_stack=%p State=%pn",
  335. walk_state->method_call_op, return_desc, walk_state->return_used,
  336. walk_state->results, walk_state));
  337. return_ACPI_STATUS (AE_OK);
  338. }
  339. /*******************************************************************************
  340.  *
  341.  * FUNCTION:    Acpi_ds_terminate_control_method
  342.  *
  343.  * PARAMETERS:  Walk_state          - State of the method
  344.  *
  345.  * RETURN:      Status
  346.  *
  347.  * DESCRIPTION: Terminate a control method.  Delete everything that the method
  348.  *              created, delete all locals and arguments, and delete the parse
  349.  *              tree if requested.
  350.  *
  351.  ******************************************************************************/
  352. acpi_status
  353. acpi_ds_terminate_control_method (
  354. acpi_walk_state         *walk_state)
  355. {
  356. acpi_operand_object     *obj_desc;
  357. acpi_namespace_node     *method_node;
  358. FUNCTION_TRACE_PTR ("Ds_terminate_control_method", walk_state);
  359. /* The method object should be stored in the walk state */
  360. obj_desc = walk_state->method_desc;
  361. if (!obj_desc) {
  362. return_ACPI_STATUS (AE_OK);
  363. }
  364. /* Delete all arguments and locals */
  365. acpi_ds_method_data_delete_all (walk_state);
  366. /*
  367.  * Lock the parser while we terminate this method.
  368.  * If this is the last thread executing the method,
  369.  * we have additional cleanup to perform
  370.  */
  371. acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
  372. /* Signal completion of the execution of this method if necessary */
  373. if (walk_state->method_desc->method.semaphore) {
  374. acpi_os_signal_semaphore (
  375. walk_state->method_desc->method.semaphore, 1);
  376. }
  377. /* Decrement the thread count on the method parse tree */
  378. walk_state->method_desc->method.thread_count--;
  379. if (!walk_state->method_desc->method.thread_count) {
  380. /*
  381.  * There are no more threads executing this method.  Perform
  382.  * additional cleanup.
  383.  *
  384.  * The method Node is stored in the walk state
  385.  */
  386. method_node = walk_state->method_node;
  387. /*
  388.  * Delete any namespace entries created immediately underneath
  389.  * the method
  390.  */
  391. acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
  392. if (method_node->child) {
  393. acpi_ns_delete_namespace_subtree (method_node);
  394. }
  395. /*
  396.  * Delete any namespace entries created anywhere else within
  397.  * the namespace
  398.  */
  399. acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
  400. acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
  401. }
  402. acpi_ut_release_mutex (ACPI_MTX_PARSER);
  403. return_ACPI_STATUS (AE_OK);
  404. }