exoparg2.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
  4.  *              $Revision: 97 $
  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 "acnamesp.h"
  27. #include "acinterp.h"
  28. #include "acevents.h"
  29. #include "amlcode.h"
  30. #include "acdispat.h"
  31. #define _COMPONENT          ACPI_EXECUTER
  32.  MODULE_NAME         ("exoparg2")
  33. /*!
  34.  * Naming convention for AML interpreter execution routines.
  35.  *
  36.  * The routines that begin execution of AML opcodes are named with a common
  37.  * convention based upon the number of arguments, the number of target operands,
  38.  * and whether or not a value is returned:
  39.  *
  40.  *      AcpiExOpcode_xA_yT_zR
  41.  *
  42.  * Where:
  43.  *
  44.  * xA - ARGUMENTS:    The number of arguments (input operands) that are
  45.  *                    required for this opcode type (1 through 6 args).
  46.  * yT - TARGETS:      The number of targets (output operands) that are required
  47.  *                    for this opcode type (0, 1, or 2 targets).
  48.  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
  49.  *                    as the function return (0 or 1).
  50.  *
  51.  * The AcpiExOpcode* functions are called via the Dispatcher component with
  52.  * fully resolved operands.
  53. !*/
  54. /*******************************************************************************
  55.  *
  56.  * FUNCTION:    Acpi_ex_opcode_2A_0T_0R
  57.  *
  58.  * PARAMETERS:  Walk_state          - Current walk state
  59.  *
  60.  * RETURN:      Status
  61.  *
  62.  * DESCRIPTION: Execute opcode with two arguments, no target, and no return
  63.  *              value.
  64.  *
  65.  * ALLOCATION:  Deletes both operands
  66.  *
  67.  ******************************************************************************/
  68. acpi_status
  69. acpi_ex_opcode_2A_0T_0R (
  70. acpi_walk_state         *walk_state)
  71. {
  72. acpi_operand_object     **operand = &walk_state->operands[0];
  73. acpi_namespace_node     *node;
  74. acpi_status             status = AE_OK;
  75. FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode));
  76. /* Examine the opcode */
  77. switch (walk_state->opcode) {
  78. case AML_NOTIFY_OP:         /* Notify (Notify_object, Notify_value) */
  79. /* The first operand is a namespace node */
  80. node = (acpi_namespace_node *) operand[0];
  81. /* The node must refer to a device or thermal zone */
  82. if (node && operand[1])     /* TBD: is this check necessary? */ {
  83. switch (node->type) {
  84. case ACPI_TYPE_DEVICE:
  85. case ACPI_TYPE_THERMAL:
  86. /*
  87.  * Dispatch the notify to the appropriate handler
  88.  * NOTE: the request is queued for execution after this method
  89.  * completes.  The notify handlers are NOT invoked synchronously
  90.  * from this thread -- because handlers may in turn run other
  91.  * control methods.
  92.  */
  93. status = acpi_ev_queue_notify_request (node,
  94.  (u32) operand[1]->integer.value);
  95. break;
  96. default:
  97. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type %Xn",
  98. node->type));
  99. status = AE_AML_OPERAND_TYPE;
  100. break;
  101. }
  102. }
  103. break;
  104. default:
  105. REPORT_ERROR (("Acpi_ex_opcode_2A_0T_0R: Unknown opcode %Xn", walk_state->opcode));
  106. status = AE_AML_BAD_OPCODE;
  107. }
  108. return_ACPI_STATUS (status);
  109. }
  110. /*******************************************************************************
  111.  *
  112.  * FUNCTION:    Acpi_ex_opcode_2A_2T_1R
  113.  *
  114.  * PARAMETERS:  Walk_state          - Current walk state
  115.  *
  116.  * RETURN:      Status
  117.  *
  118.  * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
  119.  *              and one implicit return value.
  120.  *
  121.  ******************************************************************************/
  122. acpi_status
  123. acpi_ex_opcode_2A_2T_1R (
  124. acpi_walk_state         *walk_state)
  125. {
  126. acpi_operand_object     **operand = &walk_state->operands[0];
  127. acpi_operand_object     *return_desc1 = NULL;
  128. acpi_operand_object     *return_desc2 = NULL;
  129. acpi_status             status;
  130. FUNCTION_TRACE_STR ("Ex_opcode_2A_2T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
  131. /*
  132.  * Execute the opcode
  133.  */
  134. switch (walk_state->opcode) {
  135. case AML_DIVIDE_OP:             /* Divide (Dividend, Divisor, Remainder_result Quotient_result) */
  136. return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
  137. if (!return_desc1) {
  138. status = AE_NO_MEMORY;
  139. goto cleanup;
  140. }
  141. return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
  142. if (!return_desc2) {
  143. status = AE_NO_MEMORY;
  144. goto cleanup;
  145. }
  146. /* Quotient to Return_desc1, remainder to Return_desc2 */
  147. status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value,
  148.    &return_desc1->integer.value, &return_desc2->integer.value);
  149. if (ACPI_FAILURE (status)) {
  150. goto cleanup;
  151. }
  152. break;
  153. default:
  154. REPORT_ERROR (("Acpi_ex_opcode_2A_2T_1R: Unknown opcode %Xn",
  155. walk_state->opcode));
  156. status = AE_AML_BAD_OPCODE;
  157. goto cleanup;
  158. break;
  159. }
  160. /* Store the results to the target reference operands */
  161. status = acpi_ex_store (return_desc2, operand[2], walk_state);
  162. if (ACPI_FAILURE (status)) {
  163. goto cleanup;
  164. }
  165. status = acpi_ex_store (return_desc1, operand[3], walk_state);
  166. if (ACPI_FAILURE (status)) {
  167. goto cleanup;
  168. }
  169. /* Return the remainder */
  170. walk_state->result_obj = return_desc1;
  171. cleanup:
  172. /*
  173.  * Since the remainder is not returned indirectly, remove a reference to
  174.  * it. Only the quotient is returned indirectly.
  175.  */
  176. acpi_ut_remove_reference (return_desc2);
  177. if (ACPI_FAILURE (status)) {
  178. /* Delete the return object */
  179. acpi_ut_remove_reference (return_desc1);
  180. }
  181. return_ACPI_STATUS (status);
  182. }
  183. /*******************************************************************************
  184.  *
  185.  * FUNCTION:    Acpi_ex_opcode_2A_1T_1R
  186.  *
  187.  * PARAMETERS:  Walk_state          - Current walk state
  188.  *
  189.  * RETURN:      Status
  190.  *
  191.  * DESCRIPTION: Execute opcode with two arguments, one target, and a return
  192.  *              value.
  193.  *
  194.  ******************************************************************************/
  195. acpi_status
  196. acpi_ex_opcode_2A_1T_1R (
  197. acpi_walk_state         *walk_state)
  198. {
  199. acpi_operand_object     **operand   = &walk_state->operands[0];
  200. acpi_operand_object     *return_desc = NULL;
  201. acpi_operand_object     *temp_desc;
  202. u32                     index;
  203. acpi_status             status      = AE_OK;
  204. FUNCTION_TRACE_STR ("Ex_opcode_2A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
  205. /*
  206.  * Execute the opcode
  207.  */
  208. if (walk_state->op_info->flags & AML_MATH) {
  209. /* All simple math opcodes (add, etc.) */
  210. return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
  211. if (!return_desc) {
  212. status = AE_NO_MEMORY;
  213. goto cleanup;
  214. }
  215. return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
  216.   operand[0]->integer.value,
  217.   operand[1]->integer.value);
  218. goto store_result_to_target;
  219. }
  220. switch (walk_state->opcode) {
  221. case AML_MOD_OP:                /* Mod (Dividend, Divisor, Remainder_result (ACPI 2.0) */
  222. return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
  223. if (!return_desc) {
  224. status = AE_NO_MEMORY;
  225. goto cleanup;
  226. }
  227. /* Return_desc will contain the remainder */
  228. status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value,
  229.   NULL, &return_desc->integer.value);
  230. break;
  231. case AML_CONCAT_OP:             /* Concatenate (Data1, Data2, Result) */
  232. /*
  233.  * Convert the second operand if necessary.  The first operand
  234.  * determines the type of the second operand, (See the Data Types
  235.  * section of the ACPI specification.)  Both object types are
  236.  * guaranteed to be either Integer/String/Buffer by the operand
  237.  * resolution mechanism above.
  238.  */
  239. switch (operand[0]->common.type) {
  240. case ACPI_TYPE_INTEGER:
  241. status = acpi_ex_convert_to_integer (operand[1], &operand[1], walk_state);
  242. break;
  243. case ACPI_TYPE_STRING:
  244. status = acpi_ex_convert_to_string (operand[1], &operand[1], 16, ACPI_UINT32_MAX, walk_state);
  245. break;
  246. case ACPI_TYPE_BUFFER:
  247. status = acpi_ex_convert_to_buffer (operand[1], &operand[1], walk_state);
  248. break;
  249. default:
  250. status = AE_AML_INTERNAL;
  251. }
  252. if (ACPI_FAILURE (status)) {
  253. goto cleanup;
  254. }
  255. /*
  256.  * Both operands are now known to be the same object type
  257.  * (Both are Integer, String, or Buffer), and we can now perform the
  258.  * concatenation.
  259.  */
  260. status = acpi_ex_do_concatenate (operand[0], operand[1], &return_desc, walk_state);
  261. break;
  262. case AML_TO_STRING_OP:          /* To_string (Buffer, Length, Result) (ACPI 2.0) */
  263. status = acpi_ex_convert_to_string (operand[0], &return_desc, 16,
  264.   (u32) operand[1]->integer.value, walk_state);
  265. break;
  266. case AML_CONCAT_RES_OP:         /* Concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
  267. status = AE_NOT_IMPLEMENTED;
  268. break;
  269. case AML_INDEX_OP:              /* Index (Source Index Result) */
  270. /* Create the internal return object */
  271. return_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE);
  272. if (!return_desc) {
  273. status = AE_NO_MEMORY;
  274. goto cleanup;
  275. }
  276. index = (u32) operand[1]->integer.value;
  277. /*
  278.  * At this point, the Source operand is either a Package or a Buffer
  279.  */
  280. if (operand[0]->common.type == ACPI_TYPE_PACKAGE) {
  281. /* Object to be indexed is a Package */
  282. if (index >= operand[0]->package.count) {
  283. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond package endn"));
  284. status = AE_AML_PACKAGE_LIMIT;
  285. goto cleanup;
  286. }
  287. if ((operand[2]->common.type == INTERNAL_TYPE_REFERENCE) &&
  288. (operand[2]->reference.opcode == AML_ZERO_OP)) {
  289. /*
  290.  * There is no actual result descriptor (the Zero_op Result
  291.  * descriptor is a placeholder), so just delete the placeholder and
  292.  * return a reference to the package element
  293.  */
  294. acpi_ut_remove_reference (operand[2]);
  295. }
  296. else {
  297. /*
  298.  * Each element of the package is an internal object.  Get the one
  299.  * we are after.
  300.  */
  301. temp_desc                        = operand[0]->package.elements [index];
  302. return_desc->reference.opcode    = AML_INDEX_OP;
  303. return_desc->reference.target_type = temp_desc->common.type;
  304. return_desc->reference.object    = temp_desc;
  305. status = acpi_ex_store (return_desc, operand[2], walk_state);
  306. return_desc->reference.object    = NULL;
  307. }
  308. /*
  309.  * The local return object must always be a reference to the package element,
  310.  * not the element itself.
  311.  */
  312. return_desc->reference.opcode    = AML_INDEX_OP;
  313. return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
  314. return_desc->reference.where     = &operand[0]->package.elements [index];
  315. }
  316. else {
  317. /* Object to be indexed is a Buffer */
  318. if (index >= operand[0]->buffer.length) {
  319. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond end of buffern"));
  320. status = AE_AML_BUFFER_LIMIT;
  321. goto cleanup;
  322. }
  323. return_desc->reference.opcode      = AML_INDEX_OP;
  324. return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
  325. return_desc->reference.object      = operand[0];
  326. return_desc->reference.offset      = index;
  327. status = acpi_ex_store (return_desc, operand[2], walk_state);
  328. }
  329. walk_state->result_obj = return_desc;
  330. goto cleanup;
  331. break;
  332. default:
  333. REPORT_ERROR (("Acpi_ex_opcode_2A_1T_1R: Unknown opcode %Xn",
  334. walk_state->opcode));
  335. status = AE_AML_BAD_OPCODE;
  336. break;
  337. }
  338. store_result_to_target:
  339. if (ACPI_SUCCESS (status)) {
  340. /*
  341.  * Store the result of the operation (which is now in Return_desc) into
  342.  * the Target descriptor.
  343.  */
  344. status = acpi_ex_store (return_desc, operand[2], walk_state);
  345. if (ACPI_FAILURE (status)) {
  346. goto cleanup;
  347. }
  348. walk_state->result_obj = return_desc;
  349. }
  350. cleanup:
  351. /* Delete return object on error */
  352. if (ACPI_FAILURE (status)) {
  353. acpi_ut_remove_reference (return_desc);
  354. }
  355. return_ACPI_STATUS (status);
  356. }
  357. /*******************************************************************************
  358.  *
  359.  * FUNCTION:    Acpi_ex_opcode_2A_0T_1R
  360.  *
  361.  * PARAMETERS:  Walk_state          - Current walk state
  362.  *
  363.  * RETURN:      Status
  364.  *
  365.  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
  366.  *
  367.  ******************************************************************************/
  368. acpi_status
  369. acpi_ex_opcode_2A_0T_1R (
  370. acpi_walk_state         *walk_state)
  371. {
  372. acpi_operand_object     **operand = &walk_state->operands[0];
  373. acpi_operand_object     *return_desc = NULL;
  374. acpi_status             status = AE_OK;
  375. u8                      logical_result = FALSE;
  376. FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
  377. /* Create the internal return object */
  378. return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
  379. if (!return_desc) {
  380. status = AE_NO_MEMORY;
  381. goto cleanup;
  382. }
  383. /*
  384.  * Execute the Opcode
  385.  */
  386. if (walk_state->op_info->flags & AML_LOGICAL) /* Logical_op (Operand0, Operand1) */ {
  387. logical_result = acpi_ex_do_logical_op (walk_state->opcode,
  388.  operand[0]->integer.value,
  389.  operand[1]->integer.value);
  390. goto store_logical_result;
  391. }
  392. switch (walk_state->opcode) {
  393. case AML_ACQUIRE_OP:            /* Acquire (Mutex_object, Timeout) */
  394. status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
  395. if (status == AE_TIME) {
  396. logical_result = TRUE;      /* TRUE = Acquire timed out */
  397. status = AE_OK;
  398. }
  399. break;
  400. case AML_WAIT_OP:               /* Wait (Event_object, Timeout) */
  401. status = acpi_ex_system_wait_event (operand[1], operand[0]);
  402. if (status == AE_TIME) {
  403. logical_result = TRUE;      /* TRUE, Wait timed out */
  404. status = AE_OK;
  405. }
  406. break;
  407. default:
  408. REPORT_ERROR (("Acpi_ex_opcode_2A_0T_1R: Unknown opcode %Xn", walk_state->opcode));
  409. status = AE_AML_BAD_OPCODE;
  410. goto cleanup;
  411. break;
  412. }
  413. store_logical_result:
  414. /*
  415.  * Set return value to according to Logical_result. logical TRUE (all ones)
  416.  * Default is FALSE (zero)
  417.  */
  418. if (logical_result) {
  419. return_desc->integer.value = ACPI_INTEGER_MAX;
  420. }
  421. walk_state->result_obj = return_desc;
  422. cleanup:
  423. /* Delete return object on error */
  424. if (ACPI_FAILURE (status)) {
  425. acpi_ut_remove_reference (return_desc);
  426. }
  427. return_ACPI_STATUS (status);
  428. }