Blame view

drivers/acpi/acpica/exoparg2.c 16.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /******************************************************************************
   *
   * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
   *
   *****************************************************************************/
  
  /*
75a44ce00   Len Brown   ACPICA: update In...
8
   * Copyright (C) 2000 - 2008, Intel Corp.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions, and the following disclaimer,
   *    without modification.
   * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   *    substantially similar to the "NO WARRANTY" disclaimer below
   *    ("Disclaimer") and any redistribution must be conditioned upon
   *    including a substantially similar Disclaimer requirement for further
   *    binary redistribution.
   * 3. Neither the names of the above-listed copyright holders nor the names
   *    of any contributors may be used to endorse or promote products derived
   *    from this software without specific prior written permission.
   *
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * NO WARRANTY
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  #include <acpi/acpi.h>
e2f7a7772   Len Brown   ACPICA: hide priv...
44
45
46
47
48
  #include "accommon.h"
  #include "acparser.h"
  #include "acinterp.h"
  #include "acevents.h"
  #include "amlcode.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  #define _COMPONENT          ACPI_EXECUTER
4be44fcd3   Len Brown   [ACPI] Lindent al...
51
  ACPI_MODULE_NAME("exoparg2")
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  
  /*!
   * Naming convention for AML interpreter execution routines.
   *
   * The routines that begin execution of AML opcodes are named with a common
   * convention based upon the number of arguments, the number of target operands,
   * and whether or not a value is returned:
   *
   *      AcpiExOpcode_xA_yT_zR
   *
   * Where:
   *
   * xA - ARGUMENTS:    The number of arguments (input operands) that are
   *                    required for this opcode type (1 through 6 args).
   * yT - TARGETS:      The number of targets (output operands) that are required
   *                    for this opcode type (0, 1, or 2 targets).
   * zR - RETURN VALUE: Indicates whether this opcode type returns a value
   *                    as the function return (0 or 1).
   *
   * The AcpiExOpcode* functions are called via the Dispatcher component with
   * fully resolved operands.
  !*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  /*******************************************************************************
   *
   * FUNCTION:    acpi_ex_opcode_2A_0T_0R
   *
   * PARAMETERS:  walk_state          - Current walk state
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Execute opcode with two arguments, no target, and no return
   *              value.
   *
   * ALLOCATION:  Deletes both operands
   *
   ******************************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
88
  acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
90
91
92
93
  	union acpi_operand_object **operand = &walk_state->operands[0];
  	struct acpi_namespace_node *node;
  	u32 value;
  	acpi_status status = AE_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94

b229cf92e   Bob Moore   ACPI: ACPICA 2006...
95
  	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
4be44fcd3   Len Brown   [ACPI] Lindent al...
96
  				acpi_ps_get_opcode_name(walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
  
  	/* Examine the opcode */
  
  	switch (walk_state->opcode) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
101
  	case AML_NOTIFY_OP:	/* Notify (notify_object, notify_value) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
  
  		/* The first operand is a namespace node */
4be44fcd3   Len Brown   [ACPI] Lindent al...
104
  		node = (struct acpi_namespace_node *)operand[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
  
  		/* Second value is the notify value */
  
  		value = (u32) operand[1]->integer.value;
44f6c0124   Robert Moore   ACPICA 20050408 f...
109
  		/* Are notifies allowed on this object? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110

4be44fcd3   Len Brown   [ACPI] Lindent al...
111
  		if (!acpi_ev_is_notify_object(node)) {
b8e4d8935   Bob Moore   [ACPI] ACPICA 200...
112
113
114
  			ACPI_ERROR((AE_INFO,
  				    "Unexpected notify object type [%s]",
  				    acpi_ut_get_type_name(node->type)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
  
  			status = AE_AML_OPERAND_TYPE;
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
  #ifdef ACPI_GPE_NOTIFY_CHECK
  		/*
  		 * GPE method wake/notify check.  Here, we want to ensure that we
b229cf92e   Bob Moore   ACPI: ACPICA 2006...
122
  		 * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
127
128
129
130
131
132
133
  		 * GPE method during system runtime.  If we do, the GPE is marked
  		 * as "wake-only" and disabled.
  		 *
  		 * 1) Is the Notify() value == device_wake?
  		 * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
  		 * 3) Did the original GPE happen at system runtime?
  		 *    (versus during wake)
  		 *
  		 * If all three cases are true, this is a wake-only GPE that should
  		 * be disabled at runtime.
  		 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
134
135
136
137
138
  		if (value == 2) {	/* device_wake */
  			status =
  			    acpi_ev_check_for_wake_only_gpe(walk_state->
  							    gpe_event_info);
  			if (ACPI_FAILURE(status)) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
139

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  				/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
4be44fcd3   Len Brown   [ACPI] Lindent al...
141
  				return_ACPI_STATUS(AE_OK)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
145
146
147
148
149
150
151
152
  			}
  		}
  #endif
  
  		/*
  		 * Dispatch the notify to the appropriate handler
  		 * NOTE: the request is queued for execution after this method
  		 * completes.  The notify handlers are NOT invoked synchronously
  		 * from this thread -- because handlers may in turn run other
  		 * control methods.
  		 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
153
  		status = acpi_ev_queue_notify_request(node, value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  	default:
b8e4d8935   Bob Moore   [ACPI] ACPICA 200...
156
157
  		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
  			    walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  		status = AE_AML_BAD_OPCODE;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
160
  	return_ACPI_STATUS(status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
167
168
169
170
171
172
173
  /*******************************************************************************
   *
   * FUNCTION:    acpi_ex_opcode_2A_2T_1R
   *
   * PARAMETERS:  walk_state          - Current walk state
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
   *              and one implicit return value.
   *
   ******************************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
174
  acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
176
177
178
179
  	union acpi_operand_object **operand = &walk_state->operands[0];
  	union acpi_operand_object *return_desc1 = NULL;
  	union acpi_operand_object *return_desc2 = NULL;
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180

b229cf92e   Bob Moore   ACPI: ACPICA 2006...
181
  	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
4be44fcd3   Len Brown   [ACPI] Lindent al...
182
  				acpi_ps_get_opcode_name(walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

44f6c0124   Robert Moore   ACPICA 20050408 f...
184
  	/* Execute the opcode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  	switch (walk_state->opcode) {
44f6c0124   Robert Moore   ACPICA 20050408 f...
186
187
188
  	case AML_DIVIDE_OP:
  
  		/* Divide (Dividend, Divisor, remainder_result quotient_result) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189

4be44fcd3   Len Brown   [ACPI] Lindent al...
190
191
  		return_desc1 =
  		    acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
  		if (!return_desc1) {
  			status = AE_NO_MEMORY;
  			goto cleanup;
  		}
4be44fcd3   Len Brown   [ACPI] Lindent al...
196
197
  		return_desc2 =
  		    acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
201
202
203
  		if (!return_desc2) {
  			status = AE_NO_MEMORY;
  			goto cleanup;
  		}
  
  		/* Quotient to return_desc1, remainder to return_desc2 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
204
205
206
207
208
  		status = acpi_ut_divide(operand[0]->integer.value,
  					operand[1]->integer.value,
  					&return_desc1->integer.value,
  					&return_desc2->integer.value);
  		if (ACPI_FAILURE(status)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
  			goto cleanup;
  		}
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  	default:
b8e4d8935   Bob Moore   [ACPI] ACPICA 200...
213
214
  		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
  			    walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
  		status = AE_AML_BAD_OPCODE;
  		goto cleanup;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  	/* Store the results to the target reference operands */
4be44fcd3   Len Brown   [ACPI] Lindent al...
219
220
  	status = acpi_ex_store(return_desc2, operand[2], walk_state);
  	if (ACPI_FAILURE(status)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  		goto cleanup;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
223
224
  	status = acpi_ex_store(return_desc1, operand[3], walk_state);
  	if (ACPI_FAILURE(status)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
  		goto cleanup;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
227
        cleanup:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
  	/*
  	 * Since the remainder is not returned indirectly, remove a reference to
  	 * it. Only the quotient is returned indirectly.
  	 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
232
  	acpi_ut_remove_reference(return_desc2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233

4be44fcd3   Len Brown   [ACPI] Lindent al...
234
  	if (ACPI_FAILURE(status)) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
235

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  		/* Delete the return object */
4be44fcd3   Len Brown   [ACPI] Lindent al...
237
  		acpi_ut_remove_reference(return_desc1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	}
4b6e16cf2   Bob Moore   ACPICA: Avoid use...
239
240
241
242
243
  	/* Save return object (the remainder) on success */
  
  	else {
  		walk_state->result_obj = return_desc1;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
244
  	return_ACPI_STATUS(status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
248
249
250
251
252
253
254
255
256
257
  /*******************************************************************************
   *
   * FUNCTION:    acpi_ex_opcode_2A_1T_1R
   *
   * PARAMETERS:  walk_state          - Current walk state
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Execute opcode with two arguments, one target, and a return
   *              value.
   *
   ******************************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
258
  acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
260
261
262
263
264
  	union acpi_operand_object **operand = &walk_state->operands[0];
  	union acpi_operand_object *return_desc = NULL;
  	acpi_integer index;
  	acpi_status status = AE_OK;
  	acpi_size length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

b229cf92e   Bob Moore   ACPI: ACPICA 2006...
266
  	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
4be44fcd3   Len Brown   [ACPI] Lindent al...
267
  				acpi_ps_get_opcode_name(walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268

44f6c0124   Robert Moore   ACPICA 20050408 f...
269
  	/* Execute the opcode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  	if (walk_state->op_info->flags & AML_MATH) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
271

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  		/* All simple math opcodes (add, etc.) */
4be44fcd3   Len Brown   [ACPI] Lindent al...
273
  		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
276
277
  		if (!return_desc) {
  			status = AE_NO_MEMORY;
  			goto cleanup;
  		}
4be44fcd3   Len Brown   [ACPI] Lindent al...
278
279
280
281
  		return_desc->integer.value =
  		    acpi_ex_do_math_op(walk_state->opcode,
  				       operand[0]->integer.value,
  				       operand[1]->integer.value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
  		goto store_result_to_target;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  	switch (walk_state->opcode) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
285
  	case AML_MOD_OP:	/* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286

4be44fcd3   Len Brown   [ACPI] Lindent al...
287
  		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
290
291
292
293
  		if (!return_desc) {
  			status = AE_NO_MEMORY;
  			goto cleanup;
  		}
  
  		/* return_desc will contain the remainder */
4be44fcd3   Len Brown   [ACPI] Lindent al...
294
295
296
  		status = acpi_ut_divide(operand[0]->integer.value,
  					operand[1]->integer.value,
  					NULL, &return_desc->integer.value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  		break;
4be44fcd3   Len Brown   [ACPI] Lindent al...
298
  	case AML_CONCAT_OP:	/* Concatenate (Data1, Data2, Result) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299

4be44fcd3   Len Brown   [ACPI] Lindent al...
300
301
  		status = acpi_ex_do_concatenate(operand[0], operand[1],
  						&return_desc, walk_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  		break;
4be44fcd3   Len Brown   [ACPI] Lindent al...
303
  	case AML_TO_STRING_OP:	/* to_string (Buffer, Length, Result) (ACPI 2.0) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
  
  		/*
  		 * Input object is guaranteed to be a buffer at this point (it may have
44f6c0124   Robert Moore   ACPICA 20050408 f...
307
308
  		 * been converted.)  Copy the raw buffer data to a new object of
  		 * type String.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
313
314
315
316
317
318
319
320
321
  		 */
  
  		/*
  		 * Get the length of the new string. It is the smallest of:
  		 * 1) Length of the input buffer
  		 * 2) Max length as specified in the to_string operator
  		 * 3) Length of input buffer up to a zero byte (null terminator)
  		 *
  		 * NOTE: A length of zero is ok, and will create a zero-length, null
  		 *       terminated string.
  		 */
  		length = 0;
  		while ((length < operand[0]->buffer.length) &&
4be44fcd3   Len Brown   [ACPI] Lindent al...
322
323
  		       (length < operand[1]->integer.value) &&
  		       (operand[0]->buffer.pointer[length])) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  			length++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
  		}
  
  		/* Allocate a new string object */
4be44fcd3   Len Brown   [ACPI] Lindent al...
328
  		return_desc = acpi_ut_create_string_object(length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
  		if (!return_desc) {
  			status = AE_NO_MEMORY;
  			goto cleanup;
  		}
c51a4de85   Bob Moore   [ACPI] ACPICA 200...
333
334
335
336
  		/*
  		 * Copy the raw buffer data with no transform.
  		 * (NULL terminated already)
  		 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
337
338
  		ACPI_MEMCPY(return_desc->string.pointer,
  			    operand[0]->buffer.pointer, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  		break;
44f6c0124   Robert Moore   ACPICA 20050408 f...
340
341
342
  	case AML_CONCAT_RES_OP:
  
  		/* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343

4be44fcd3   Len Brown   [ACPI] Lindent al...
344
345
  		status = acpi_ex_concat_template(operand[0], operand[1],
  						 &return_desc, walk_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  		break;
4be44fcd3   Len Brown   [ACPI] Lindent al...
347
  	case AML_INDEX_OP:	/* Index (Source Index Result) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
  
  		/* Create the internal return object */
4be44fcd3   Len Brown   [ACPI] Lindent al...
350
351
  		return_desc =
  		    acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
354
355
  		if (!return_desc) {
  			status = AE_NO_MEMORY;
  			goto cleanup;
  		}
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
356
  		/* Initialize the Index reference object */
44f6c0124   Robert Moore   ACPICA 20050408 f...
357
  		index = operand[1]->integer.value;
1044f1f65   Bob Moore   ACPICA: Cleanup f...
358
359
  		return_desc->reference.value = (u32) index;
  		return_desc->reference.class = ACPI_REFCLASS_INDEX;
44f6c0124   Robert Moore   ACPICA 20050408 f...
360

52fc0b026   Bob Moore   [ACPI] ACPICA 200...
361
362
363
364
  		/*
  		 * At this point, the Source operand is a String, Buffer, or Package.
  		 * Verify that the index is within range.
  		 */
3371c19c2   Bob Moore   ACPICA: Remove AC...
365
  		switch ((operand[0])->common.type) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
366
  		case ACPI_TYPE_STRING:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367

52fc0b026   Bob Moore   [ACPI] ACPICA 200...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  			if (index >= operand[0]->string.length) {
  				status = AE_AML_STRING_LIMIT;
  			}
  
  			return_desc->reference.target_type =
  			    ACPI_TYPE_BUFFER_FIELD;
  			break;
  
  		case ACPI_TYPE_BUFFER:
  
  			if (index >= operand[0]->buffer.length) {
  				status = AE_AML_BUFFER_LIMIT;
  			}
  
  			return_desc->reference.target_type =
  			    ACPI_TYPE_BUFFER_FIELD;
  			break;
  
  		case ACPI_TYPE_PACKAGE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
  
  			if (index >= operand[0]->package.count) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  				status = AE_AML_PACKAGE_LIMIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
  			}
  
  			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
4be44fcd3   Len Brown   [ACPI] Lindent al...
393
394
  			return_desc->reference.where =
  			    &operand[0]->package.elements[index];
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
395
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

52fc0b026   Bob Moore   [ACPI] ACPICA 200...
397
  		default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398

52fc0b026   Bob Moore   [ACPI] ACPICA 200...
399
400
401
402
403
404
405
406
407
408
409
  			status = AE_AML_INTERNAL;
  			goto cleanup;
  		}
  
  		/* Failure means that the Index was beyond the end of the object */
  
  		if (ACPI_FAILURE(status)) {
  			ACPI_EXCEPTION((AE_INFO, status,
  					"Index (%X%8.8X) is beyond end of object",
  					ACPI_FORMAT_UINT64(index)));
  			goto cleanup;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
412
  		}
  
  		/*
8313524a0   Bob Moore   ACPI: ACPICA 2006...
413
  		 * Save the target object and add a reference to it for the life
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
414
  		 * of the index
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  		 */
8313524a0   Bob Moore   ACPI: ACPICA 2006...
416
  		return_desc->reference.object = operand[0];
4be44fcd3   Len Brown   [ACPI] Lindent al...
417
  		acpi_ut_add_reference(operand[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  		/* Store the reference to the Target */
4be44fcd3   Len Brown   [ACPI] Lindent al...
420
  		status = acpi_ex_store(return_desc, operand[2], walk_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
424
425
  
  		/* Return the reference */
  
  		walk_state->result_obj = return_desc;
  		goto cleanup;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  	default:
b8e4d8935   Bob Moore   [ACPI] ACPICA 200...
427
428
  		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
  			    walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
  		status = AE_AML_BAD_OPCODE;
  		break;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
432
        store_result_to_target:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433

4be44fcd3   Len Brown   [ACPI] Lindent al...
434
  	if (ACPI_SUCCESS(status)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
  		/*
  		 * Store the result of the operation (which is now in return_desc) into
  		 * the Target descriptor.
  		 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
439
440
  		status = acpi_ex_store(return_desc, operand[2], walk_state);
  		if (ACPI_FAILURE(status)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
445
446
447
  			goto cleanup;
  		}
  
  		if (!walk_state->result_obj) {
  			walk_state->result_obj = return_desc;
  		}
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
448
        cleanup:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
  
  	/* Delete return object on error */
4be44fcd3   Len Brown   [ACPI] Lindent al...
451
452
  	if (ACPI_FAILURE(status)) {
  		acpi_ut_remove_reference(return_desc);
4b6e16cf2   Bob Moore   ACPICA: Avoid use...
453
  		walk_state->result_obj = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
455
  	return_ACPI_STATUS(status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
461
462
463
464
465
466
467
  /*******************************************************************************
   *
   * FUNCTION:    acpi_ex_opcode_2A_0T_1R
   *
   * PARAMETERS:  walk_state          - Current walk state
   *
   * RETURN:      Status
   *
   * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
   *
   ******************************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
468
  acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
470
471
472
473
  	union acpi_operand_object **operand = &walk_state->operands[0];
  	union acpi_operand_object *return_desc = NULL;
  	acpi_status status = AE_OK;
  	u8 logical_result = FALSE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474

b229cf92e   Bob Moore   ACPI: ACPICA 2006...
475
  	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
4be44fcd3   Len Brown   [ACPI] Lindent al...
476
  				acpi_ps_get_opcode_name(walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
  
  	/* Create the internal return object */
4be44fcd3   Len Brown   [ACPI] Lindent al...
479
  	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
  	if (!return_desc) {
  		status = AE_NO_MEMORY;
  		goto cleanup;
  	}
44f6c0124   Robert Moore   ACPICA 20050408 f...
484
485
486
  	/* Execute the Opcode */
  
  	if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
487

44f6c0124   Robert Moore   ACPICA 20050408 f...
488
  		/* logical_op (Operand0, Operand1) */
4be44fcd3   Len Brown   [ACPI] Lindent al...
489
490
491
492
493
  		status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
  						       operand[0]->integer.
  						       value,
  						       operand[1]->integer.
  						       value, &logical_result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
  		goto store_logical_result;
4be44fcd3   Len Brown   [ACPI] Lindent al...
495
  	} else if (walk_state->op_info->flags & AML_LOGICAL) {
52fc0b026   Bob Moore   [ACPI] ACPICA 200...
496

44f6c0124   Robert Moore   ACPICA 20050408 f...
497
  		/* logical_op (Operand0, Operand1) */
4be44fcd3   Len Brown   [ACPI] Lindent al...
498
499
  		status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
  					       operand[1], &logical_result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
  		goto store_logical_result;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  	switch (walk_state->opcode) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
503
  	case AML_ACQUIRE_OP:	/* Acquire (mutex_object, Timeout) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504

4be44fcd3   Len Brown   [ACPI] Lindent al...
505
506
  		status =
  		    acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
  		if (status == AE_TIME) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
508
  			logical_result = TRUE;	/* TRUE = Acquire timed out */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
  			status = AE_OK;
  		}
  		break;
4be44fcd3   Len Brown   [ACPI] Lindent al...
512
  	case AML_WAIT_OP:	/* Wait (event_object, Timeout) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513

4be44fcd3   Len Brown   [ACPI] Lindent al...
514
  		status = acpi_ex_system_wait_event(operand[1], operand[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  		if (status == AE_TIME) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
516
  			logical_result = TRUE;	/* TRUE, Wait timed out */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
  			status = AE_OK;
  		}
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  	default:
b8e4d8935   Bob Moore   [ACPI] ACPICA 200...
521
522
  		ACPI_ERROR((AE_INFO, "Unknown AML opcode %X",
  			    walk_state->opcode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
  		status = AE_AML_BAD_OPCODE;
  		goto cleanup;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
526
        store_logical_result:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
531
532
533
  	/*
  	 * Set return value to according to logical_result. logical TRUE (all ones)
  	 * Default is FALSE (zero)
  	 */
  	if (logical_result) {
  		return_desc->integer.value = ACPI_INTEGER_MAX;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
534
        cleanup:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
  
  	/* Delete return object on error */
4be44fcd3   Len Brown   [ACPI] Lindent al...
537
538
  	if (ACPI_FAILURE(status)) {
  		acpi_ut_remove_reference(return_desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
  	}
4b6e16cf2   Bob Moore   ACPICA: Avoid use...
540
541
542
543
544
  	/* Save return object on success */
  
  	else {
  		walk_state->result_obj = return_desc;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
545
  	return_ACPI_STATUS(status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
  }