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

嵌入式Linux

开发平台:

Unix_Linux

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
  4.  *              $Revision: 92 $
  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 "acinterp.h"
  27. #include "amlcode.h"
  28. #include "acdispat.h"
  29. #define _COMPONENT          ACPI_EXECUTER
  30.  MODULE_NAME         ("exmisc")
  31. /*******************************************************************************
  32.  *
  33.  * FUNCTION:    Acpi_ex_get_object_reference
  34.  *
  35.  * PARAMETERS:  Obj_desc        - Create a reference to this object
  36.  *              Return_desc        - Where to store the reference
  37.  *
  38.  * RETURN:      Status
  39.  *
  40.  * DESCRIPTION: Obtain and return a "reference" to the target object
  41.  *              Common code for the Ref_of_op and the Cond_ref_of_op.
  42.  *
  43.  ******************************************************************************/
  44. acpi_status
  45. acpi_ex_get_object_reference (
  46. acpi_operand_object     *obj_desc,
  47. acpi_operand_object     **return_desc,
  48. acpi_walk_state         *walk_state)
  49. {
  50. acpi_status             status = AE_OK;
  51. FUNCTION_TRACE_PTR ("Ex_get_object_reference", obj_desc);
  52. if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
  53. if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) {
  54. *return_desc = NULL;
  55. status = AE_TYPE;
  56. goto cleanup;
  57. }
  58. /*
  59.  * Not a Name -- an indirect name pointer would have
  60.  * been converted to a direct name pointer in Acpi_ex_resolve_operands
  61.  */
  62. switch (obj_desc->reference.opcode) {
  63. case AML_LOCAL_OP:
  64. case AML_ARG_OP:
  65. *return_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode,
  66.   obj_desc->reference.offset, walk_state);
  67. break;
  68. default:
  69. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(Internal) Unknown Ref subtype %02xn",
  70. obj_desc->reference.opcode));
  71. *return_desc = NULL;
  72. status = AE_AML_INTERNAL;
  73. goto cleanup;
  74. }
  75. }
  76. else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
  77. /* Must be a named object;  Just return the Node */
  78. *return_desc = obj_desc;
  79. }
  80. else {
  81. *return_desc = NULL;
  82. status = AE_TYPE;
  83. }
  84. cleanup:
  85. ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p Ref=%pn", obj_desc, *return_desc));
  86. return_ACPI_STATUS (status);
  87. }
  88. /*******************************************************************************
  89.  *
  90.  * FUNCTION:    Acpi_ex_do_concatenate
  91.  *
  92.  * PARAMETERS:  *Obj_desc           - Object to be converted.  Must be an
  93.  *                                    Integer, Buffer, or String
  94.  *              Walk_state          - Current walk state
  95.  *
  96.  * RETURN:      Status
  97.  *
  98.  * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
  99.  *
  100.  ******************************************************************************/
  101. acpi_status
  102. acpi_ex_do_concatenate (
  103. acpi_operand_object     *obj_desc,
  104. acpi_operand_object     *obj_desc2,
  105. acpi_operand_object     **actual_return_desc,
  106. acpi_walk_state         *walk_state)
  107. {
  108. acpi_status             status;
  109. u32                     i;
  110. acpi_integer            this_integer;
  111. acpi_operand_object     *return_desc;
  112. NATIVE_CHAR             *new_buf;
  113. u32                     integer_size = sizeof (acpi_integer);
  114. FUNCTION_ENTRY ();
  115. /*
  116.  * There are three cases to handle:
  117.  * 1) Two Integers concatenated to produce a buffer
  118.  * 2) Two Strings concatenated to produce a string
  119.  * 3) Two Buffers concatenated to produce a buffer
  120.  */
  121. switch (obj_desc->common.type) {
  122. case ACPI_TYPE_INTEGER:
  123. /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
  124. if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
  125. /*
  126.  * We are running a method that exists in a 32-bit ACPI table.
  127.  * Truncate the value to 32 bits by zeroing out the upper
  128.  * 32-bit field
  129.  */
  130. integer_size = sizeof (u32);
  131. }
  132. /* Result of two integers is a buffer */
  133. return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
  134. if (!return_desc) {
  135. return (AE_NO_MEMORY);
  136. }
  137. /* Need enough space for two integers */
  138. return_desc->buffer.length = integer_size * 2;
  139. new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length);
  140. if (!new_buf) {
  141. REPORT_ERROR
  142. (("Ex_do_concatenate: Buffer allocation failuren"));
  143. status = AE_NO_MEMORY;
  144. goto cleanup;
  145. }
  146. return_desc->buffer.pointer = (u8 *) new_buf;
  147. /* Convert the first integer */
  148. this_integer = obj_desc->integer.value;
  149. for (i = 0; i < integer_size; i++) {
  150. new_buf[i] = (u8) this_integer;
  151. this_integer >>= 8;
  152. }
  153. /* Convert the second integer */
  154. this_integer = obj_desc2->integer.value;
  155. for (; i < (integer_size * 2); i++) {
  156. new_buf[i] = (u8) this_integer;
  157. this_integer >>= 8;
  158. }
  159. break;
  160. case ACPI_TYPE_STRING:
  161. return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
  162. if (!return_desc) {
  163. return (AE_NO_MEMORY);
  164. }
  165. /* Operand0 is string  */
  166. new_buf = ACPI_MEM_ALLOCATE (obj_desc->string.length +
  167.   obj_desc2->string.length + 1);
  168. if (!new_buf) {
  169. REPORT_ERROR
  170. (("Ex_do_concatenate: String allocation failuren"));
  171. status = AE_NO_MEMORY;
  172. goto cleanup;
  173. }
  174. STRCPY (new_buf, obj_desc->string.pointer);
  175. STRCPY (new_buf + obj_desc->string.length,
  176.   obj_desc2->string.pointer);
  177. /* Point the return object to the new string */
  178. return_desc->string.pointer = new_buf;
  179. return_desc->string.length = obj_desc->string.length +=
  180.   obj_desc2->string.length;
  181. break;
  182. case ACPI_TYPE_BUFFER:
  183. /* Operand0 is a buffer */
  184. return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
  185. if (!return_desc) {
  186. return (AE_NO_MEMORY);
  187. }
  188. new_buf = ACPI_MEM_ALLOCATE (obj_desc->buffer.length +
  189.   obj_desc2->buffer.length);
  190. if (!new_buf) {
  191. REPORT_ERROR
  192. (("Ex_do_concatenate: Buffer allocation failuren"));
  193. status = AE_NO_MEMORY;
  194. goto cleanup;
  195. }
  196. MEMCPY (new_buf, obj_desc->buffer.pointer,
  197.   obj_desc->buffer.length);
  198. MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
  199.    obj_desc2->buffer.length);
  200. /*
  201.  * Point the return object to the new buffer
  202.  */
  203. return_desc->buffer.pointer    = (u8 *) new_buf;
  204. return_desc->buffer.length     = obj_desc->buffer.length +
  205.  obj_desc2->buffer.length;
  206. break;
  207. default:
  208. status = AE_AML_INTERNAL;
  209. return_desc = NULL;
  210. }
  211. *actual_return_desc = return_desc;
  212. return (AE_OK);
  213. cleanup:
  214. acpi_ut_remove_reference (return_desc);
  215. return (status);
  216. }
  217. /*******************************************************************************
  218.  *
  219.  * FUNCTION:    Acpi_ex_do_math_op
  220.  *
  221.  * PARAMETERS:  Opcode              - AML opcode
  222.  *              Operand0            - Integer operand #0
  223.  *              Operand0            - Integer operand #1
  224.  *
  225.  * RETURN:      Integer result of the operation
  226.  *
  227.  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
  228.  *              math functions here is to prevent a lot of pointer dereferencing
  229.  *              to obtain the operands.
  230.  *
  231.  ******************************************************************************/
  232. acpi_integer
  233. acpi_ex_do_math_op (
  234. u16                     opcode,
  235. acpi_integer            operand0,
  236. acpi_integer            operand1)
  237. {
  238. switch (opcode) {
  239. case AML_ADD_OP:                /* Add (Operand0, Operand1, Result) */
  240. return (operand0 + operand1);
  241. case AML_BIT_AND_OP:            /* And (Operand0, Operand1, Result) */
  242. return (operand0 & operand1);
  243. case AML_BIT_NAND_OP:           /* NAnd (Operand0, Operand1, Result) */
  244. return (~(operand0 & operand1));
  245. case AML_BIT_OR_OP:             /* Or (Operand0, Operand1, Result) */
  246. return (operand0 | operand1);
  247. case AML_BIT_NOR_OP:            /* NOr (Operand0, Operand1, Result) */
  248. return (~(operand0 | operand1));
  249. case AML_BIT_XOR_OP:            /* XOr (Operand0, Operand1, Result) */
  250. return (operand0 ^ operand1);
  251. case AML_MULTIPLY_OP:           /* Multiply (Operand0, Operand1, Result) */
  252. return (operand0 * operand1);
  253. case AML_SHIFT_LEFT_OP:         /* Shift_left (Operand, Shift_count, Result) */
  254. return (operand0 << operand1);
  255. case AML_SHIFT_RIGHT_OP:        /* Shift_right (Operand, Shift_count, Result) */
  256. return (operand0 >> operand1);
  257. case AML_SUBTRACT_OP:           /* Subtract (Operand0, Operand1, Result) */
  258. return (operand0 - operand1);
  259. default:
  260. return (0);
  261. }
  262. }
  263. /*******************************************************************************
  264.  *
  265.  * FUNCTION:    Acpi_ex_do_logical_op
  266.  *
  267.  * PARAMETERS:  Opcode              - AML opcode
  268.  *              Operand0            - Integer operand #0
  269.  *              Operand0            - Integer operand #1
  270.  *
  271.  * RETURN:      TRUE/FALSE result of the operation
  272.  *
  273.  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
  274.  *              functions here is to prevent a lot of pointer dereferencing
  275.  *              to obtain the operands and to simplify the generation of the
  276.  *              logical value.
  277.  *
  278.  *              Note: cleanest machine code seems to be produced by the code
  279.  *              below, rather than using statements of the form:
  280.  *                  Result = (Operand0 == Operand1);
  281.  *
  282.  ******************************************************************************/
  283. u8
  284. acpi_ex_do_logical_op (
  285. u16                     opcode,
  286. acpi_integer            operand0,
  287. acpi_integer            operand1)
  288. {
  289. switch (opcode) {
  290. case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
  291. if (operand0 && operand1) {
  292. return (TRUE);
  293. }
  294. break;
  295. case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
  296. if (operand0 == operand1) {
  297. return (TRUE);
  298. }
  299. break;
  300. case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
  301. if (operand0 > operand1) {
  302. return (TRUE);
  303. }
  304. break;
  305. case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
  306. if (operand0 < operand1) {
  307. return (TRUE);
  308. }
  309. break;
  310. case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
  311. if (operand0 || operand1) {
  312. return (TRUE);
  313. }
  314. break;
  315. }
  316. return (FALSE);
  317. }