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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: dswload - Dispatcher namespace load callbacks
  4.  *              $Revision: 50 $
  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 "acevents.h"
  31. #define _COMPONENT          ACPI_DISPATCHER
  32.  MODULE_NAME         ("dswload")
  33. /*******************************************************************************
  34.  *
  35.  * FUNCTION:    Acpi_ds_init_callbacks
  36.  *
  37.  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
  38.  *              Pass_number     - 1, 2, or 3
  39.  *
  40.  * RETURN:      Status
  41.  *
  42.  * DESCRIPTION: Init walk state callbacks
  43.  *
  44.  ******************************************************************************/
  45. acpi_status
  46. acpi_ds_init_callbacks (
  47. acpi_walk_state         *walk_state,
  48. u32                     pass_number)
  49. {
  50. switch (pass_number) {
  51. case 1:
  52. walk_state->parse_flags       = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
  53. walk_state->descending_callback = acpi_ds_load1_begin_op;
  54. walk_state->ascending_callback = acpi_ds_load1_end_op;
  55. break;
  56. case 2:
  57. walk_state->parse_flags       = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
  58. walk_state->descending_callback = acpi_ds_load2_begin_op;
  59. walk_state->ascending_callback = acpi_ds_load2_end_op;
  60. break;
  61. case 3:
  62. walk_state->parse_flags      |= ACPI_PARSE_EXECUTE  | ACPI_PARSE_DELETE_TREE;
  63. walk_state->descending_callback = acpi_ds_exec_begin_op;
  64. walk_state->ascending_callback = acpi_ds_exec_end_op;
  65. break;
  66. default:
  67. return (AE_BAD_PARAMETER);
  68. break;
  69. }
  70. return (AE_OK);
  71. }
  72. /*******************************************************************************
  73.  *
  74.  * FUNCTION:    Acpi_ds_load1_begin_op
  75.  *
  76.  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
  77.  *              Op              - Op that has been just been reached in the
  78.  *                                walk;  Arguments have not been evaluated yet.
  79.  *
  80.  * RETURN:      Status
  81.  *
  82.  * DESCRIPTION: Descending callback used during the loading of ACPI tables.
  83.  *
  84.  ******************************************************************************/
  85. acpi_status
  86. acpi_ds_load1_begin_op (
  87. acpi_walk_state         *walk_state,
  88. acpi_parse_object       **out_op)
  89. {
  90. acpi_parse_object       *op;
  91. acpi_namespace_node     *node;
  92. acpi_status             status;
  93. acpi_object_type8       data_type;
  94. NATIVE_CHAR             *path;
  95. PROC_NAME ("Ds_load1_begin_op");
  96. op = walk_state->op;
  97. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%pn", op, walk_state));
  98. /* We are only interested in opcodes that have an associated name */
  99. if (walk_state->op) {
  100.    if (!(walk_state->op_info->flags & AML_NAMED)) {
  101. *out_op = op;
  102. return (AE_OK);
  103. }
  104. /* Check if this object has already been installed in the namespace */
  105. if (op->node) {
  106. *out_op = op;
  107. return (AE_OK);
  108. }
  109. }
  110. path = acpi_ps_get_next_namestring (&walk_state->parser_state);
  111. /* Map the raw opcode into an internal object type */
  112. data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode);
  113. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  114. "State=%p Op=%p Type=%xn", walk_state, op, data_type));
  115. if (walk_state->opcode == AML_SCOPE_OP) {
  116. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  117. "State=%p Op=%p Type=%xn", walk_state, op, data_type));
  118. }
  119. /*
  120.  * Enter the named type into the internal namespace.  We enter the name
  121.  * as we go downward in the parse tree.  Any necessary subobjects that involve
  122.  * arguments to the opcode must be created as we go back up the parse tree later.
  123.  */
  124. status = acpi_ns_lookup (walk_state->scope_info, path, data_type,
  125.   IMODE_LOAD_PASS1, NS_NO_UPSEARCH, walk_state, &(node));
  126. if (ACPI_FAILURE (status)) {
  127. return (status);
  128. }
  129. if (!op) {
  130. /* Create a new op */
  131. op = acpi_ps_alloc_op (walk_state->opcode);
  132. if (!op) {
  133. return (AE_NO_MEMORY);
  134. }
  135. }
  136. /* Initialize */
  137. ((acpi_parse2_object *)op)->name = node->name;
  138. /*
  139.  * Put the Node in the "op" object that the parser uses, so we
  140.  * can get it again quickly when this scope is closed
  141.  */
  142. op->node = node;
  143. acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op);
  144. *out_op = op;
  145. return (status);
  146. }
  147. /*******************************************************************************
  148.  *
  149.  * FUNCTION:    Acpi_ds_load1_end_op
  150.  *
  151.  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
  152.  *              Op              - Op that has been just been completed in the
  153.  *                                walk;  Arguments have now been evaluated.
  154.  *
  155.  * RETURN:      Status
  156.  *
  157.  * DESCRIPTION: Ascending callback used during the loading of the namespace,
  158.  *              both control methods and everything else.
  159.  *
  160.  ******************************************************************************/
  161. acpi_status
  162. acpi_ds_load1_end_op (
  163. acpi_walk_state         *walk_state)
  164. {
  165. acpi_parse_object       *op;
  166. acpi_object_type8       data_type;
  167. PROC_NAME ("Ds_load1_end_op");
  168. op = walk_state->op;
  169. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%pn", op, walk_state));
  170. /* We are only interested in opcodes that have an associated name */
  171. if (!(walk_state->op_info->flags & AML_NAMED)) {
  172. return (AE_OK);
  173. }
  174. /* Get the type to determine if we should pop the scope */
  175. data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
  176. if (op->opcode == AML_NAME_OP) {
  177. /* For Name opcode, check the argument */
  178. if (op->value.arg) {
  179. data_type = acpi_ds_map_opcode_to_data_type (
  180.   (op->value.arg)->opcode, NULL);
  181. ((acpi_namespace_node *)op->node)->type =
  182.   (u8) data_type;
  183. }
  184. }
  185. /* Pop the scope stack */
  186. if (acpi_ns_opens_scope (data_type)) {
  187. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %pn",
  188. acpi_ut_get_type_name (data_type), op));
  189. acpi_ds_scope_stack_pop (walk_state);
  190. }
  191. return (AE_OK);
  192. }
  193. /*******************************************************************************
  194.  *
  195.  * FUNCTION:    Acpi_ds_load2_begin_op
  196.  *
  197.  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
  198.  *              Op              - Op that has been just been reached in the
  199.  *                                walk;  Arguments have not been evaluated yet.
  200.  *
  201.  * RETURN:      Status
  202.  *
  203.  * DESCRIPTION: Descending callback used during the loading of ACPI tables.
  204.  *
  205.  ******************************************************************************/
  206. acpi_status
  207. acpi_ds_load2_begin_op (
  208. acpi_walk_state         *walk_state,
  209. acpi_parse_object       **out_op)
  210. {
  211. acpi_parse_object       *op;
  212. acpi_namespace_node     *node;
  213. acpi_status             status;
  214. acpi_object_type8       data_type;
  215. NATIVE_CHAR             *buffer_ptr;
  216. void                    *original = NULL;
  217. PROC_NAME ("Ds_load2_begin_op");
  218. op = walk_state->op;
  219. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%pn", op, walk_state));
  220. if (op) {
  221. /* We only care about Namespace opcodes here */
  222. if (!(walk_state->op_info->flags & AML_NSOPCODE) &&
  223. walk_state->opcode != AML_INT_NAMEPATH_OP) {
  224. return (AE_OK);
  225. }
  226. /* TBD: [Restructure] Temp! same code as in psparse */
  227. if (!(walk_state->op_info->flags & AML_NAMED)) {
  228. return (AE_OK);
  229. }
  230. /*
  231.  * Get the name we are going to enter or lookup in the namespace
  232.  */
  233. if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
  234. /* For Namepath op, get the path string */
  235. buffer_ptr = op->value.string;
  236. if (!buffer_ptr) {
  237. /* No name, just exit */
  238. return (AE_OK);
  239. }
  240. }
  241. else {
  242. /* Get name from the op */
  243. buffer_ptr = (NATIVE_CHAR *) &((acpi_parse2_object *)op)->name;
  244. }
  245. }
  246. else {
  247. buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
  248. }
  249. /* Map the raw opcode into an internal object type */
  250. data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode);
  251. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  252. "State=%p Op=%p Type=%xn", walk_state, op, data_type));
  253. if (walk_state->opcode == AML_FIELD_OP         ||
  254. walk_state->opcode == AML_BANK_FIELD_OP    ||
  255. walk_state->opcode == AML_INDEX_FIELD_OP) {
  256. node = NULL;
  257. status = AE_OK;
  258. }
  259. else if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
  260. /*
  261.  * The Name_path is an object reference to an existing object. Don't enter the
  262.  * name into the namespace, but look it up for use later
  263.  */
  264. status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type,
  265.   IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node));
  266. }
  267. else {
  268. if (op && op->node) {
  269. original = op->node;
  270. node = op->node;
  271. if (acpi_ns_opens_scope (data_type)) {
  272. status = acpi_ds_scope_stack_push (node, data_type, walk_state);
  273. if (ACPI_FAILURE (status)) {
  274. return (status);
  275. }
  276. }
  277. return (AE_OK);
  278. }
  279. /*
  280.  * Enter the named type into the internal namespace.  We enter the name
  281.  * as we go downward in the parse tree.  Any necessary subobjects that involve
  282.  * arguments to the opcode must be created as we go back up the parse tree later.
  283.  */
  284. status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type,
  285.   IMODE_EXECUTE, NS_NO_UPSEARCH, walk_state, &(node));
  286. }
  287. if (ACPI_SUCCESS (status)) {
  288. if (!op) {
  289. /* Create a new op */
  290. op = acpi_ps_alloc_op (walk_state->opcode);
  291. if (!op) {
  292. return (AE_NO_MEMORY);
  293. }
  294. /* Initialize */
  295. ((acpi_parse2_object *)op)->name = node->name;
  296. *out_op = op;
  297. }
  298. /*
  299.  * Put the Node in the "op" object that the parser uses, so we
  300.  * can get it again quickly when this scope is closed
  301.  */
  302. op->node = node;
  303. if (original) {
  304. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "old %p new %pn", original, node));
  305. if (original != node) {
  306. ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
  307. "Lookup match error: old %p new %pn", original, node));
  308. }
  309. }
  310. }
  311. return (status);
  312. }
  313. /*******************************************************************************
  314.  *
  315.  * FUNCTION:    Acpi_ds_load2_end_op
  316.  *
  317.  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
  318.  *              Op              - Op that has been just been completed in the
  319.  *                                walk;  Arguments have now been evaluated.
  320.  *
  321.  * RETURN:      Status
  322.  *
  323.  * DESCRIPTION: Ascending callback used during the loading of the namespace,
  324.  *              both control methods and everything else.
  325.  *
  326.  ******************************************************************************/
  327. acpi_status
  328. acpi_ds_load2_end_op (
  329. acpi_walk_state         *walk_state)
  330. {
  331. acpi_parse_object       *op;
  332. acpi_status             status = AE_OK;
  333. acpi_object_type8       data_type;
  334. acpi_namespace_node     *node;
  335. acpi_parse_object       *arg;
  336. acpi_namespace_node     *new_node;
  337. u32                     i;
  338. PROC_NAME ("Ds_load2_end_op");
  339. op = walk_state->op;
  340. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%pn", op, walk_state));
  341. /* Only interested in opcodes that have namespace objects */
  342. if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
  343. return (AE_OK);
  344. }
  345. if (op->opcode == AML_SCOPE_OP) {
  346. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  347. "Ending scope Op=%p State=%pn", op, walk_state));
  348. if (((acpi_parse2_object *)op)->name == -1) {
  349. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%pn",
  350. op, walk_state));
  351. return (AE_OK);
  352. }
  353. }
  354. data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
  355. /*
  356.  * Get the Node/name from the earlier lookup
  357.  * (It was saved in the *op structure)
  358.  */
  359. node = op->node;
  360. /*
  361.  * Put the Node on the object stack (Contains the ACPI Name of
  362.  * this object)
  363.  */
  364. walk_state->operands[0] = (void *) node;
  365. walk_state->num_operands = 1;
  366. /* Pop the scope stack */
  367. if (acpi_ns_opens_scope (data_type)) {
  368. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %pn",
  369. acpi_ut_get_type_name (data_type), op));
  370. acpi_ds_scope_stack_pop (walk_state);
  371. }
  372. /*
  373.  * Named operations are as follows:
  374.  *
  375.  * AML_ALIAS
  376.  * AML_BANKFIELD
  377.  * AML_CREATEBITFIELD
  378.  * AML_CREATEBYTEFIELD
  379.  * AML_CREATEDWORDFIELD
  380.  * AML_CREATEFIELD
  381.  * AML_CREATEQWORDFIELD
  382.  * AML_CREATEWORDFIELD
  383.  * AML_DATA_REGION
  384.  * AML_DEVICE
  385.  * AML_EVENT
  386.  * AML_FIELD
  387.  * AML_INDEXFIELD
  388.  * AML_METHOD
  389.  * AML_METHODCALL
  390.  * AML_MUTEX
  391.  * AML_NAME
  392.  * AML_NAMEDFIELD
  393.  * AML_OPREGION
  394.  * AML_POWERRES
  395.  * AML_PROCESSOR
  396.  * AML_SCOPE
  397.  * AML_THERMALZONE
  398.  */
  399. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  400. "Create-Load [%s] State=%p Op=%p Named_obj=%pn",
  401. acpi_ps_get_opcode_name (op->opcode), walk_state, op, node));
  402. /* Decode the opcode */
  403. arg = op->value.arg;
  404. switch (walk_state->op_info->type) {
  405. case AML_TYPE_CREATE_FIELD:
  406. /*
  407.  * Create the field object, but the field buffer and index must
  408.  * be evaluated later during the execution phase
  409.  */
  410. status = acpi_ds_create_buffer_field (op, walk_state);
  411. break;
  412.  case AML_TYPE_NAMED_FIELD:
  413. arg = op->value.arg;
  414. switch (op->opcode) {
  415. case AML_INDEX_FIELD_OP:
  416. status = acpi_ds_create_index_field (op, (acpi_handle) arg->node,
  417.    walk_state);
  418. break;
  419. case AML_BANK_FIELD_OP:
  420. status = acpi_ds_create_bank_field (op, arg->node, walk_state);
  421. break;
  422. case AML_FIELD_OP:
  423. status = acpi_ds_create_field (op, arg->node, walk_state);
  424. break;
  425. }
  426. break;
  427.  case AML_TYPE_NAMED_SIMPLE:
  428. status = acpi_ds_create_operands (walk_state, arg);
  429. if (ACPI_FAILURE (status)) {
  430. goto cleanup;
  431. }
  432. switch (op->opcode) {
  433. case AML_PROCESSOR_OP:
  434. status = acpi_ex_create_processor (walk_state);
  435. break;
  436. case AML_POWER_RES_OP:
  437. status = acpi_ex_create_power_resource (walk_state);
  438. break;
  439. case AML_MUTEX_OP:
  440. status = acpi_ex_create_mutex (walk_state);
  441. break;
  442. case AML_EVENT_OP:
  443. status = acpi_ex_create_event (walk_state);
  444. break;
  445. case AML_DATA_REGION_OP:
  446. status = acpi_ex_create_table_region (walk_state);
  447. break;
  448. case AML_ALIAS_OP:
  449. status = acpi_ex_create_alias (walk_state);
  450. break;
  451. default:
  452. /* Unknown opcode */
  453. status = AE_OK;
  454. goto cleanup;
  455. break;
  456. }
  457. /* Delete operands */
  458. for (i = 1; i < walk_state->num_operands; i++) {
  459. acpi_ut_remove_reference (walk_state->operands[i]);
  460. walk_state->operands[i] = NULL;
  461. }
  462. break;
  463. case AML_TYPE_NAMED_COMPLEX:
  464. switch (op->opcode) {
  465. case AML_METHOD_OP:
  466. /*
  467.  * Method_op Pkg_length Names_string Method_flags Term_list
  468.  */
  469. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  470. "LOADING-Method: State=%p Op=%p Named_obj=%pn",
  471. walk_state, op, node));
  472. if (!node->object) {
  473. status = acpi_ds_create_operands (walk_state, arg);
  474. if (ACPI_FAILURE (status)) {
  475. goto cleanup;
  476. }
  477. status = acpi_ex_create_method (((acpi_parse2_object *) op)->data,
  478.    ((acpi_parse2_object *) op)->length,
  479.    walk_state);
  480. }
  481. break;
  482. case AML_REGION_OP:
  483. /*
  484.  * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
  485.  * (We must save the address of the AML of the address and length operands)
  486.  */
  487. status = acpi_ex_create_region (((acpi_parse2_object *) op)->data,
  488.   ((acpi_parse2_object *) op)->length,
  489.  (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state);
  490. break;
  491. case AML_NAME_OP:
  492. status = acpi_ds_create_node (walk_state, node, op);
  493. break;
  494. }
  495. break;
  496. case AML_CLASS_INTERNAL:
  497. /* case AML_INT_NAMEPATH_OP: */
  498. break;
  499. case AML_CLASS_METHOD_CALL:
  500. ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
  501. "RESOLVING-Method_call: State=%p Op=%p Named_obj=%pn",
  502. walk_state, op, node));
  503. /*
  504.  * Lookup the method name and save the Node
  505.  */
  506. status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
  507.   ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
  508.   NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
  509.   walk_state, &(new_node));
  510. if (ACPI_SUCCESS (status)) {
  511. /* TBD: has name already been resolved by here ??*/
  512. /* TBD: [Restructure] Make sure that what we found is indeed a method! */
  513. /* We didn't search for a method on purpose, to see if the name would resolve! */
  514. /* We could put the returned object (Node) on the object stack for later, but
  515.  * for now, we will put it in the "op" object that the parser uses, so we
  516.  * can get it again at the end of this scope
  517.  */
  518. op->node = new_node;
  519. }
  520. break;
  521. default:
  522. break;
  523. }
  524. cleanup:
  525. /* Remove the Node pushed at the very beginning */
  526. walk_state->operands[0] = NULL;
  527. walk_state->num_operands = 0;
  528. return (status);
  529. }