Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: dsopcode - Dispatcher support for regions and fields
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2015, Intel Corp.
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
#include 
45
#include "accommon.h"
46
#include "acparser.h"
47
#include "amlcode.h"
48
#include "acdispat.h"
49
#include "acinterp.h"
50
#include "acnamesp.h"
51
#include "acevents.h"
52
#include "actables.h"
53
 
54
#define _COMPONENT          ACPI_DISPATCHER
55
ACPI_MODULE_NAME("dsopcode")
56
 
57
/* Local prototypes */
58
static acpi_status
59
acpi_ds_init_buffer_field(u16 aml_opcode,
60
			  union acpi_operand_object *obj_desc,
61
			  union acpi_operand_object *buffer_desc,
62
			  union acpi_operand_object *offset_desc,
63
			  union acpi_operand_object *length_desc,
64
			  union acpi_operand_object *result_desc);
65
 
66
/*******************************************************************************
67
 *
68
 * FUNCTION:    acpi_ds_initialize_region
69
 *
70
 * PARAMETERS:  obj_handle      - Region namespace node
71
 *
72
 * RETURN:      Status
73
 *
74
 * DESCRIPTION: Front end to ev_initialize_region
75
 *
76
 ******************************************************************************/
77
 
78
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
79
{
80
	union acpi_operand_object *obj_desc;
81
	acpi_status status;
82
 
83
	obj_desc = acpi_ns_get_attached_object(obj_handle);
84
 
85
	/* Namespace is NOT locked */
86
 
87
	status = acpi_ev_initialize_region(obj_desc, FALSE);
88
	return (status);
89
}
90
 
91
/*******************************************************************************
92
 *
93
 * FUNCTION:    acpi_ds_init_buffer_field
94
 *
95
 * PARAMETERS:  aml_opcode      - create_xxx_field
96
 *              obj_desc        - buffer_field object
97
 *              buffer_desc     - Host Buffer
98
 *              offset_desc     - Offset into buffer
99
 *              length_desc     - Length of field (CREATE_FIELD_OP only)
100
 *              result_desc     - Where to store the result
101
 *
102
 * RETURN:      Status
103
 *
104
 * DESCRIPTION: Perform actual initialization of a buffer field
105
 *
106
 ******************************************************************************/
107
 
108
static acpi_status
109
acpi_ds_init_buffer_field(u16 aml_opcode,
110
			  union acpi_operand_object *obj_desc,
111
			  union acpi_operand_object *buffer_desc,
112
			  union acpi_operand_object *offset_desc,
113
			  union acpi_operand_object *length_desc,
114
			  union acpi_operand_object *result_desc)
115
{
116
	u32 offset;
117
	u32 bit_offset;
118
	u32 bit_count;
119
	u8 field_flags;
120
	acpi_status status;
121
 
122
	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
123
 
124
	/* Host object must be a Buffer */
125
 
126
	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
127
		ACPI_ERROR((AE_INFO,
128
			    "Target of Create Field is not a Buffer object - %s",
129
			    acpi_ut_get_object_type_name(buffer_desc)));
130
 
131
		status = AE_AML_OPERAND_TYPE;
132
		goto cleanup;
133
	}
134
 
135
	/*
136
	 * The last parameter to all of these opcodes (result_desc) started
137
	 * out as a name_string, and should therefore now be a NS node
138
	 * after resolution in acpi_ex_resolve_operands().
139
	 */
140
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
141
		ACPI_ERROR((AE_INFO,
142
			    "(%s) destination not a NS Node [%s]",
143
			    acpi_ps_get_opcode_name(aml_opcode),
144
			    acpi_ut_get_descriptor_name(result_desc)));
145
 
146
		status = AE_AML_OPERAND_TYPE;
147
		goto cleanup;
148
	}
149
 
150
	offset = (u32) offset_desc->integer.value;
151
 
152
	/*
153
	 * Setup the Bit offsets and counts, according to the opcode
154
	 */
155
	switch (aml_opcode) {
156
	case AML_CREATE_FIELD_OP:
157
 
158
		/* Offset is in bits, count is in bits */
159
 
160
		field_flags = AML_FIELD_ACCESS_BYTE;
161
		bit_offset = offset;
162
		bit_count = (u32) length_desc->integer.value;
163
 
164
		/* Must have a valid (>0) bit count */
165
 
166
		if (bit_count == 0) {
167
			ACPI_ERROR((AE_INFO,
168
				    "Attempt to CreateField of length zero"));
169
			status = AE_AML_OPERAND_VALUE;
170
			goto cleanup;
171
		}
172
		break;
173
 
174
	case AML_CREATE_BIT_FIELD_OP:
175
 
176
		/* Offset is in bits, Field is one bit */
177
 
178
		bit_offset = offset;
179
		bit_count = 1;
180
		field_flags = AML_FIELD_ACCESS_BYTE;
181
		break;
182
 
183
	case AML_CREATE_BYTE_FIELD_OP:
184
 
185
		/* Offset is in bytes, field is one byte */
186
 
187
		bit_offset = 8 * offset;
188
		bit_count = 8;
189
		field_flags = AML_FIELD_ACCESS_BYTE;
190
		break;
191
 
192
	case AML_CREATE_WORD_FIELD_OP:
193
 
194
		/* Offset is in bytes, field is one word */
195
 
196
		bit_offset = 8 * offset;
197
		bit_count = 16;
198
		field_flags = AML_FIELD_ACCESS_WORD;
199
		break;
200
 
201
	case AML_CREATE_DWORD_FIELD_OP:
202
 
203
		/* Offset is in bytes, field is one dword */
204
 
205
		bit_offset = 8 * offset;
206
		bit_count = 32;
207
		field_flags = AML_FIELD_ACCESS_DWORD;
208
		break;
209
 
210
	case AML_CREATE_QWORD_FIELD_OP:
211
 
212
		/* Offset is in bytes, field is one qword */
213
 
214
		bit_offset = 8 * offset;
215
		bit_count = 64;
216
		field_flags = AML_FIELD_ACCESS_QWORD;
217
		break;
218
 
219
	default:
220
 
221
		ACPI_ERROR((AE_INFO,
222
			    "Unknown field creation opcode 0x%02X",
223
			    aml_opcode));
224
		status = AE_AML_BAD_OPCODE;
225
		goto cleanup;
226
	}
227
 
228
	/* Entire field must fit within the current length of the buffer */
229
 
230
	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
231
		ACPI_ERROR((AE_INFO,
232
			    "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",
233
			    acpi_ut_get_node_name(result_desc),
234
			    bit_offset + bit_count,
235
			    acpi_ut_get_node_name(buffer_desc->buffer.node),
236
			    8 * (u32) buffer_desc->buffer.length));
237
		status = AE_AML_BUFFER_LIMIT;
238
		goto cleanup;
239
	}
240
 
241
	/*
242
	 * Initialize areas of the field object that are common to all fields
243
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
244
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
245
	 */
246
	status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
247
						  bit_offset, bit_count);
248
	if (ACPI_FAILURE(status)) {
249
		goto cleanup;
250
	}
251
 
252
	obj_desc->buffer_field.buffer_obj = buffer_desc;
253
 
254
	/* Reference count for buffer_desc inherits obj_desc count */
255
 
256
	buffer_desc->common.reference_count = (u16)
257
	    (buffer_desc->common.reference_count +
258
	     obj_desc->common.reference_count);
259
 
260
cleanup:
261
 
262
	/* Always delete the operands */
263
 
264
	acpi_ut_remove_reference(offset_desc);
265
	acpi_ut_remove_reference(buffer_desc);
266
 
267
	if (aml_opcode == AML_CREATE_FIELD_OP) {
268
		acpi_ut_remove_reference(length_desc);
269
	}
270
 
271
	/* On failure, delete the result descriptor */
272
 
273
	if (ACPI_FAILURE(status)) {
274
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
275
	} else {
276
		/* Now the address and length are valid for this buffer_field */
277
 
278
		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
279
	}
280
 
281
	return_ACPI_STATUS(status);
282
}
283
 
284
/*******************************************************************************
285
 *
286
 * FUNCTION:    acpi_ds_eval_buffer_field_operands
287
 *
288
 * PARAMETERS:  walk_state      - Current walk
289
 *              op              - A valid buffer_field Op object
290
 *
291
 * RETURN:      Status
292
 *
293
 * DESCRIPTION: Get buffer_field Buffer and Index
294
 *              Called from acpi_ds_exec_end_op during buffer_field parse tree walk
295
 *
296
 ******************************************************************************/
297
 
298
acpi_status
299
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
300
				   union acpi_parse_object *op)
301
{
302
	acpi_status status;
303
	union acpi_operand_object *obj_desc;
304
	struct acpi_namespace_node *node;
305
	union acpi_parse_object *next_op;
306
 
307
	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
308
 
309
	/*
310
	 * This is where we evaluate the address and length fields of the
311
	 * create_xxx_field declaration
312
	 */
313
	node = op->common.node;
314
 
315
	/* next_op points to the op that holds the Buffer */
316
 
317
	next_op = op->common.value.arg;
318
 
319
	/* Evaluate/create the address and length operands */
320
 
321
	status = acpi_ds_create_operands(walk_state, next_op);
322
	if (ACPI_FAILURE(status)) {
323
		return_ACPI_STATUS(status);
324
	}
325
 
326
	obj_desc = acpi_ns_get_attached_object(node);
327
	if (!obj_desc) {
328
		return_ACPI_STATUS(AE_NOT_EXIST);
329
	}
330
 
331
	/* Resolve the operands */
332
 
333
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
334
					  ACPI_WALK_OPERANDS, walk_state);
335
	if (ACPI_FAILURE(status)) {
336
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
337
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
338
			    status));
339
 
340
		return_ACPI_STATUS(status);
341
	}
342
 
343
	/* Initialize the Buffer Field */
344
 
345
	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
346
 
347
		/* NOTE: Slightly different operands for this opcode */
348
 
349
		status =
350
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
351
					      walk_state->operands[0],
352
					      walk_state->operands[1],
353
					      walk_state->operands[2],
354
					      walk_state->operands[3]);
355
	} else {
356
		/* All other, create_xxx_field opcodes */
357
 
358
		status =
359
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
360
					      walk_state->operands[0],
361
					      walk_state->operands[1], NULL,
362
					      walk_state->operands[2]);
363
	}
364
 
365
	return_ACPI_STATUS(status);
366
}
367
 
368
/*******************************************************************************
369
 *
370
 * FUNCTION:    acpi_ds_eval_region_operands
371
 *
372
 * PARAMETERS:  walk_state      - Current walk
373
 *              op              - A valid region Op object
374
 *
375
 * RETURN:      Status
376
 *
377
 * DESCRIPTION: Get region address and length
378
 *              Called from acpi_ds_exec_end_op during op_region parse tree walk
379
 *
380
 ******************************************************************************/
381
 
382
acpi_status
383
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
384
			     union acpi_parse_object *op)
385
{
386
	acpi_status status;
387
	union acpi_operand_object *obj_desc;
388
	union acpi_operand_object *operand_desc;
389
	struct acpi_namespace_node *node;
390
	union acpi_parse_object *next_op;
391
 
392
	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
393
 
394
	/*
395
	 * This is where we evaluate the address and length fields of the
396
	 * op_region declaration
397
	 */
398
	node = op->common.node;
399
 
400
	/* next_op points to the op that holds the space_ID */
401
 
402
	next_op = op->common.value.arg;
403
 
404
	/* next_op points to address op */
405
 
406
	next_op = next_op->common.next;
407
 
408
	/* Evaluate/create the address and length operands */
409
 
410
	status = acpi_ds_create_operands(walk_state, next_op);
411
	if (ACPI_FAILURE(status)) {
412
		return_ACPI_STATUS(status);
413
	}
414
 
415
	/* Resolve the length and address operands to numbers */
416
 
417
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
418
					  ACPI_WALK_OPERANDS, walk_state);
419
	if (ACPI_FAILURE(status)) {
420
		return_ACPI_STATUS(status);
421
	}
422
 
423
	obj_desc = acpi_ns_get_attached_object(node);
424
	if (!obj_desc) {
425
		return_ACPI_STATUS(AE_NOT_EXIST);
426
	}
427
 
428
	/*
429
	 * Get the length operand and save it
430
	 * (at Top of stack)
431
	 */
432
	operand_desc = walk_state->operands[walk_state->num_operands - 1];
433
 
434
	obj_desc->region.length = (u32) operand_desc->integer.value;
435
	acpi_ut_remove_reference(operand_desc);
436
 
437
	/*
438
	 * Get the address and save it
439
	 * (at top of stack - 1)
440
	 */
441
	operand_desc = walk_state->operands[walk_state->num_operands - 2];
442
 
443
	obj_desc->region.address = (acpi_physical_address)
444
	    operand_desc->integer.value;
445
	acpi_ut_remove_reference(operand_desc);
446
 
447
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
448
			  obj_desc,
449
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
450
			  obj_desc->region.length));
451
 
452
	/* Now the address and length are valid for this opregion */
453
 
454
	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
455
 
456
	return_ACPI_STATUS(status);
457
}
458
 
459
/*******************************************************************************
460
 *
461
 * FUNCTION:    acpi_ds_eval_table_region_operands
462
 *
463
 * PARAMETERS:  walk_state      - Current walk
464
 *              op              - A valid region Op object
465
 *
466
 * RETURN:      Status
467
 *
468
 * DESCRIPTION: Get region address and length.
469
 *              Called from acpi_ds_exec_end_op during data_table_region parse
470
 *              tree walk.
471
 *
472
 ******************************************************************************/
473
 
474
acpi_status
475
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
476
				   union acpi_parse_object *op)
477
{
478
	acpi_status status;
479
	union acpi_operand_object *obj_desc;
480
	union acpi_operand_object **operand;
481
	struct acpi_namespace_node *node;
482
	union acpi_parse_object *next_op;
483
	struct acpi_table_header *table;
484
	u32 table_index;
485
 
486
	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
487
 
488
	/*
489
	 * This is where we evaluate the Signature string, oem_id string,
490
	 * and oem_table_id string of the Data Table Region declaration
491
	 */
492
	node = op->common.node;
493
 
494
	/* next_op points to Signature string op */
495
 
496
	next_op = op->common.value.arg;
497
 
498
	/*
499
	 * Evaluate/create the Signature string, oem_id string,
500
	 * and oem_table_id string operands
501
	 */
502
	status = acpi_ds_create_operands(walk_state, next_op);
503
	if (ACPI_FAILURE(status)) {
504
		return_ACPI_STATUS(status);
505
	}
506
 
507
	operand = &walk_state->operands[0];
508
 
509
	/*
510
	 * Resolve the Signature string, oem_id string,
511
	 * and oem_table_id string operands
512
	 */
513
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
514
					  ACPI_WALK_OPERANDS, walk_state);
515
	if (ACPI_FAILURE(status)) {
516
		goto cleanup;
517
	}
518
 
519
	/* Find the ACPI table */
520
 
521
	status = acpi_tb_find_table(operand[0]->string.pointer,
522
				    operand[1]->string.pointer,
523
				    operand[2]->string.pointer, &table_index);
524
	if (ACPI_FAILURE(status)) {
525
		if (status == AE_NOT_FOUND) {
526
			ACPI_ERROR((AE_INFO,
527
				    "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
528
				    operand[0]->string.pointer,
529
				    operand[1]->string.pointer,
530
				    operand[2]->string.pointer));
531
		}
532
		goto cleanup;
533
	}
534
 
535
	status = acpi_get_table_by_index(table_index, &table);
536
	if (ACPI_FAILURE(status)) {
537
		goto cleanup;
538
	}
539
 
540
	obj_desc = acpi_ns_get_attached_object(node);
541
	if (!obj_desc) {
542
		status = AE_NOT_EXIST;
543
		goto cleanup;
544
	}
545
 
546
	obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
547
	obj_desc->region.length = table->length;
548
 
549
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
550
			  obj_desc,
551
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
552
			  obj_desc->region.length));
553
 
554
	/* Now the address and length are valid for this opregion */
555
 
556
	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
557
 
558
cleanup:
559
	acpi_ut_remove_reference(operand[0]);
560
	acpi_ut_remove_reference(operand[1]);
561
	acpi_ut_remove_reference(operand[2]);
562
 
563
	return_ACPI_STATUS(status);
564
}
565
 
566
/*******************************************************************************
567
 *
568
 * FUNCTION:    acpi_ds_eval_data_object_operands
569
 *
570
 * PARAMETERS:  walk_state      - Current walk
571
 *              op              - A valid data_object Op object
572
 *              obj_desc        - data_object
573
 *
574
 * RETURN:      Status
575
 *
576
 * DESCRIPTION: Get the operands and complete the following data object types:
577
 *              Buffer, Package.
578
 *
579
 ******************************************************************************/
580
 
581
acpi_status
582
acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
583
				  union acpi_parse_object *op,
584
				  union acpi_operand_object *obj_desc)
585
{
586
	acpi_status status;
587
	union acpi_operand_object *arg_desc;
588
	u32 length;
589
 
590
	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
591
 
592
	/* The first operand (for all of these data objects) is the length */
593
 
594
	/*
595
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
596
	 * invoked inside acpi_ds_create_operand.
597
	 */
598
	walk_state->operand_index = walk_state->num_operands;
599
 
600
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
601
	if (ACPI_FAILURE(status)) {
602
		return_ACPI_STATUS(status);
603
	}
604
 
605
	status = acpi_ex_resolve_operands(walk_state->opcode,
606
					  &(walk_state->
607
					    operands[walk_state->num_operands -
608
						     1]), walk_state);
609
	if (ACPI_FAILURE(status)) {
610
		return_ACPI_STATUS(status);
611
	}
612
 
613
	/* Extract length operand */
614
 
615
	arg_desc = walk_state->operands[walk_state->num_operands - 1];
616
	length = (u32) arg_desc->integer.value;
617
 
618
	/* Cleanup for length operand */
619
 
620
	status = acpi_ds_obj_stack_pop(1, walk_state);
621
	if (ACPI_FAILURE(status)) {
622
		return_ACPI_STATUS(status);
623
	}
624
 
625
	acpi_ut_remove_reference(arg_desc);
626
 
627
	/*
628
	 * Create the actual data object
629
	 */
630
	switch (op->common.aml_opcode) {
631
	case AML_BUFFER_OP:
632
 
633
		status =
634
		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
635
						      &obj_desc);
636
		break;
637
 
638
	case AML_PACKAGE_OP:
639
	case AML_VAR_PACKAGE_OP:
640
 
641
		status =
642
		    acpi_ds_build_internal_package_obj(walk_state, op, length,
643
						       &obj_desc);
644
		break;
645
 
646
	default:
647
 
648
		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
649
	}
650
 
651
	if (ACPI_SUCCESS(status)) {
652
		/*
653
		 * Return the object in the walk_state, unless the parent is a package -
654
		 * in this case, the return object will be stored in the parse tree
655
		 * for the package.
656
		 */
657
		if ((!op->common.parent) ||
658
		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
659
		     (op->common.parent->common.aml_opcode !=
660
		      AML_VAR_PACKAGE_OP)
661
		     && (op->common.parent->common.aml_opcode !=
662
			 AML_NAME_OP))) {
663
			walk_state->result_obj = obj_desc;
664
		}
665
	}
666
 
667
	return_ACPI_STATUS(status);
668
}
669
 
670
/*******************************************************************************
671
 *
672
 * FUNCTION:    acpi_ds_eval_bank_field_operands
673
 *
674
 * PARAMETERS:  walk_state      - Current walk
675
 *              op              - A valid bank_field Op object
676
 *
677
 * RETURN:      Status
678
 *
679
 * DESCRIPTION: Get bank_field bank_value
680
 *              Called from acpi_ds_exec_end_op during bank_field parse tree walk
681
 *
682
 ******************************************************************************/
683
 
684
acpi_status
685
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
686
				 union acpi_parse_object *op)
687
{
688
	acpi_status status;
689
	union acpi_operand_object *obj_desc;
690
	union acpi_operand_object *operand_desc;
691
	struct acpi_namespace_node *node;
692
	union acpi_parse_object *next_op;
693
	union acpi_parse_object *arg;
694
 
695
	ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);
696
 
697
	/*
698
	 * This is where we evaluate the bank_value field of the
699
	 * bank_field declaration
700
	 */
701
 
702
	/* next_op points to the op that holds the Region */
703
 
704
	next_op = op->common.value.arg;
705
 
706
	/* next_op points to the op that holds the Bank Register */
707
 
708
	next_op = next_op->common.next;
709
 
710
	/* next_op points to the op that holds the Bank Value */
711
 
712
	next_op = next_op->common.next;
713
 
714
	/*
715
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
716
	 * invoked inside acpi_ds_create_operand.
717
	 *
718
	 * We use walk_state->Operands[0] to store the evaluated bank_value
719
	 */
720
	walk_state->operand_index = 0;
721
 
722
	status = acpi_ds_create_operand(walk_state, next_op, 0);
723
	if (ACPI_FAILURE(status)) {
724
		return_ACPI_STATUS(status);
725
	}
726
 
727
	status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
728
	if (ACPI_FAILURE(status)) {
729
		return_ACPI_STATUS(status);
730
	}
731
 
732
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
733
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
734
	/*
735
	 * Get the bank_value operand and save it
736
	 * (at Top of stack)
737
	 */
738
	operand_desc = walk_state->operands[0];
739
 
740
	/* Arg points to the start Bank Field */
741
 
742
	arg = acpi_ps_get_arg(op, 4);
743
	while (arg) {
744
 
745
		/* Ignore OFFSET and ACCESSAS terms here */
746
 
747
		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
748
			node = arg->common.node;
749
 
750
			obj_desc = acpi_ns_get_attached_object(node);
751
			if (!obj_desc) {
752
				return_ACPI_STATUS(AE_NOT_EXIST);
753
			}
754
 
755
			obj_desc->bank_field.value =
756
			    (u32) operand_desc->integer.value;
757
		}
758
 
759
		/* Move to next field in the list */
760
 
761
		arg = arg->common.next;
762
	}
763
 
764
	acpi_ut_remove_reference(operand_desc);
765
	return_ACPI_STATUS(status);
766
}