OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [acpi/] [dispatcher/] [dsfield.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/******************************************************************************
2
 *
3
 * Module Name: dsfield - Dispatcher field routines
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2004, R. Byron Moore
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
 
45
#include <acpi/acpi.h>
46
#include <acpi/amlcode.h>
47
#include <acpi/acdispat.h>
48
#include <acpi/acinterp.h>
49
#include <acpi/acnamesp.h>
50
#include <acpi/acparser.h>
51
 
52
 
53
#define _COMPONENT          ACPI_DISPATCHER
54
         ACPI_MODULE_NAME    ("dsfield")
55
 
56
 
57
/*******************************************************************************
58
 *
59
 * FUNCTION:    acpi_ds_create_buffer_field
60
 *
61
 * PARAMETERS:  Opcode              - The opcode to be executed
62
 *              Operands            - List of operands for the opcode
63
 *              walk_state          - Current state
64
 *
65
 * RETURN:      Status
66
 *
67
 * DESCRIPTION: Execute the create_field operators:
68
 *              create_bit_field_op,
69
 *              create_byte_field_op,
70
 *              create_word_field_op,
71
 *              create_dword_field_op,
72
 *              create_qword_field_op,
73
 *              create_field_op     (all of which define fields in buffers)
74
 *
75
 ******************************************************************************/
76
 
77
acpi_status
78
acpi_ds_create_buffer_field (
79
        union acpi_parse_object         *op,
80
        struct acpi_walk_state          *walk_state)
81
{
82
        union acpi_parse_object         *arg;
83
        struct acpi_namespace_node      *node;
84
        acpi_status                     status;
85
        union acpi_operand_object       *obj_desc;
86
        union acpi_operand_object       *second_desc = NULL;
87
        u32                             flags;
88
 
89
 
90
        ACPI_FUNCTION_TRACE ("ds_create_buffer_field");
91
 
92
 
93
        /* Get the name_string argument */
94
 
95
        if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
96
                arg = acpi_ps_get_arg (op, 3);
97
        }
98
        else {
99
                /* Create Bit/Byte/Word/Dword field */
100
 
101
                arg = acpi_ps_get_arg (op, 2);
102
        }
103
 
104
        if (!arg) {
105
                return_ACPI_STATUS (AE_AML_NO_OPERAND);
106
        }
107
 
108
        if (walk_state->deferred_node) {
109
                node = walk_state->deferred_node;
110
                status = AE_OK;
111
        }
112
        else {
113
                /*
114
                 * During the load phase, we want to enter the name of the field into
115
                 * the namespace.  During the execute phase (when we evaluate the size
116
                 * operand), we want to lookup the name
117
                 */
118
                if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
119
                        flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
120
                }
121
                else {
122
                        flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND;
123
                }
124
 
125
                /*
126
                 * Enter the name_string into the namespace
127
                 */
128
                status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
129
                                 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
130
                                 flags, walk_state, &(node));
131
                if (ACPI_FAILURE (status)) {
132
                        ACPI_REPORT_NSERROR (arg->common.value.string, status);
133
                        return_ACPI_STATUS (status);
134
                }
135
        }
136
 
137
        /* We could put the returned object (Node) on the object stack for later, but
138
         * for now, we will put it in the "op" object that the parser uses, so we
139
         * can get it again at the end of this scope
140
         */
141
        op->common.node = node;
142
 
143
        /*
144
         * If there is no object attached to the node, this node was just created and
145
         * we need to create the field object.  Otherwise, this was a lookup of an
146
         * existing node and we don't want to create the field object again.
147
         */
148
        obj_desc = acpi_ns_get_attached_object (node);
149
        if (obj_desc) {
150
                return_ACPI_STATUS (AE_OK);
151
        }
152
 
153
        /*
154
         * The Field definition is not fully parsed at this time.
155
         * (We must save the address of the AML for the buffer and index operands)
156
         */
157
 
158
        /* Create the buffer field object */
159
 
160
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
161
        if (!obj_desc) {
162
                status = AE_NO_MEMORY;
163
                goto cleanup;
164
        }
165
 
166
        /*
167
         * Remember location in AML stream of the field unit
168
         * opcode and operands -- since the buffer and index
169
         * operands must be evaluated.
170
         */
171
        second_desc                 = obj_desc->common.next_object;
172
        second_desc->extra.aml_start = op->named.data;
173
        second_desc->extra.aml_length = op->named.length;
174
        obj_desc->buffer_field.node = node;
175
 
176
        /* Attach constructed field descriptors to parent node */
177
 
178
        status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
179
        if (ACPI_FAILURE (status)) {
180
                goto cleanup;
181
        }
182
 
183
 
184
cleanup:
185
 
186
        /* Remove local reference to the object */
187
 
188
        acpi_ut_remove_reference (obj_desc);
189
        return_ACPI_STATUS (status);
190
}
191
 
192
 
193
/*******************************************************************************
194
 *
195
 * FUNCTION:    acpi_ds_get_field_names
196
 *
197
 * PARAMETERS:  Info            - create_field info structure
198
 *  `           walk_state      - Current method state
199
 *              Arg             - First parser arg for the field name list
200
 *
201
 * RETURN:      Status
202
 *
203
 * DESCRIPTION: Process all named fields in a field declaration.  Names are
204
 *              entered into the namespace.
205
 *
206
 ******************************************************************************/
207
 
208
acpi_status
209
acpi_ds_get_field_names (
210
        struct acpi_create_field_info   *info,
211
        struct acpi_walk_state          *walk_state,
212
        union acpi_parse_object         *arg)
213
{
214
        acpi_status                     status;
215
        acpi_integer                    position;
216
 
217
 
218
        ACPI_FUNCTION_TRACE_PTR ("ds_get_field_names", info);
219
 
220
 
221
        /* First field starts at bit zero */
222
 
223
        info->field_bit_position = 0;
224
 
225
        /* Process all elements in the field list (of parse nodes) */
226
 
227
        while (arg) {
228
                /*
229
                 * Three types of field elements are handled:
230
                 * 1) Offset - specifies a bit offset
231
                 * 2) access_as - changes the access mode
232
                 * 3) Name - Enters a new named field into the namespace
233
                 */
234
                switch (arg->common.aml_opcode) {
235
                case AML_INT_RESERVEDFIELD_OP:
236
 
237
                        position = (acpi_integer) info->field_bit_position
238
                                         + (acpi_integer) arg->common.value.size;
239
 
240
                        if (position > ACPI_UINT32_MAX) {
241
                                ACPI_REPORT_ERROR (("Bit offset within field too large (> 0xFFFFFFFF)\n"));
242
                                return_ACPI_STATUS (AE_SUPPORT);
243
                        }
244
 
245
                        info->field_bit_position = (u32) position;
246
                        break;
247
 
248
 
249
                case AML_INT_ACCESSFIELD_OP:
250
 
251
                        /*
252
                         * Get a new access_type and access_attribute -- to be used for all
253
                         * field units that follow, until field end or another access_as keyword.
254
                         *
255
                         * In field_flags, preserve the flag bits other than the ACCESS_TYPE bits
256
                         */
257
                        info->field_flags = (u8) ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
258
                                          ((u8) ((u32) arg->common.value.integer >> 8)));
259
 
260
                        info->attribute = (u8) (arg->common.value.integer);
261
                        break;
262
 
263
 
264
                case AML_INT_NAMEDFIELD_OP:
265
 
266
                        /* Lookup the name */
267
 
268
                        status = acpi_ns_lookup (walk_state->scope_info,
269
                                          (char *) &arg->named.name,
270
                                          info->field_type, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
271
                                          walk_state, &info->field_node);
272
                        if (ACPI_FAILURE (status)) {
273
                                ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
274
                                if (status != AE_ALREADY_EXISTS) {
275
                                        return_ACPI_STATUS (status);
276
                                }
277
 
278
                                /* Already exists, ignore error */
279
                        }
280
                        else {
281
                                arg->common.node = info->field_node;
282
                                info->field_bit_length = arg->common.value.size;
283
 
284
                                /* Create and initialize an object for the new Field Node */
285
 
286
                                status = acpi_ex_prep_field_value (info);
287
                                if (ACPI_FAILURE (status)) {
288
                                        return_ACPI_STATUS (status);
289
                                }
290
                        }
291
 
292
                        /* Keep track of bit position for the next field */
293
 
294
                        position = (acpi_integer) info->field_bit_position
295
                                         + (acpi_integer) arg->common.value.size;
296
 
297
                        if (position > ACPI_UINT32_MAX) {
298
                                ACPI_REPORT_ERROR (("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n",
299
                                                (char *) &info->field_node->name));
300
                                return_ACPI_STATUS (AE_SUPPORT);
301
                        }
302
 
303
                        info->field_bit_position += info->field_bit_length;
304
                        break;
305
 
306
 
307
                default:
308
 
309
                        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
310
                                arg->common.aml_opcode));
311
                        return_ACPI_STATUS (AE_AML_BAD_OPCODE);
312
                }
313
 
314
                arg = arg->common.next;
315
        }
316
 
317
        return_ACPI_STATUS (AE_OK);
318
}
319
 
320
 
321
/*******************************************************************************
322
 *
323
 * FUNCTION:    acpi_ds_create_field
324
 *
325
 * PARAMETERS:  Op              - Op containing the Field definition and args
326
 *              region_node     - Object for the containing Operation Region
327
 *  `           walk_state      - Current method state
328
 *
329
 * RETURN:      Status
330
 *
331
 * DESCRIPTION: Create a new field in the specified operation region
332
 *
333
 ******************************************************************************/
334
 
335
acpi_status
336
acpi_ds_create_field (
337
        union acpi_parse_object         *op,
338
        struct acpi_namespace_node      *region_node,
339
        struct acpi_walk_state          *walk_state)
340
{
341
        acpi_status                     status;
342
        union acpi_parse_object         *arg;
343
        struct acpi_create_field_info   info;
344
 
345
 
346
        ACPI_FUNCTION_TRACE_PTR ("ds_create_field", op);
347
 
348
 
349
        /* First arg is the name of the parent op_region (must already exist) */
350
 
351
        arg = op->common.value.arg;
352
        if (!region_node) {
353
                status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
354
                                  ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
355
                                  ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
356
                if (ACPI_FAILURE (status)) {
357
                        ACPI_REPORT_NSERROR (arg->common.value.name, status);
358
                        return_ACPI_STATUS (status);
359
                }
360
        }
361
 
362
        /* Second arg is the field flags */
363
 
364
        arg = arg->common.next;
365
        info.field_flags = (u8) arg->common.value.integer;
366
        info.attribute = 0;
367
 
368
        /* Each remaining arg is a Named Field */
369
 
370
        info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
371
        info.region_node = region_node;
372
 
373
        status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
374
 
375
        return_ACPI_STATUS (status);
376
}
377
 
378
 
379
/*******************************************************************************
380
 *
381
 * FUNCTION:    acpi_ds_init_field_objects
382
 *
383
 * PARAMETERS:  Op              - Op containing the Field definition and args
384
 *  `           walk_state      - Current method state
385
 *
386
 * RETURN:      Status
387
 *
388
 * DESCRIPTION: For each "Field Unit" name in the argument list that is
389
 *              part of the field declaration, enter the name into the
390
 *              namespace.
391
 *
392
 ******************************************************************************/
393
 
394
acpi_status
395
acpi_ds_init_field_objects (
396
        union acpi_parse_object         *op,
397
        struct acpi_walk_state          *walk_state)
398
{
399
        acpi_status                     status;
400
        union acpi_parse_object         *arg = NULL;
401
        struct acpi_namespace_node      *node;
402
        u8                              type = 0;
403
 
404
 
405
        ACPI_FUNCTION_TRACE_PTR ("ds_init_field_objects", op);
406
 
407
 
408
        switch (walk_state->opcode) {
409
        case AML_FIELD_OP:
410
                arg = acpi_ps_get_arg (op, 2);
411
                type = ACPI_TYPE_LOCAL_REGION_FIELD;
412
                break;
413
 
414
        case AML_BANK_FIELD_OP:
415
                arg = acpi_ps_get_arg (op, 4);
416
                type = ACPI_TYPE_LOCAL_BANK_FIELD;
417
                break;
418
 
419
        case AML_INDEX_FIELD_OP:
420
                arg = acpi_ps_get_arg (op, 3);
421
                type = ACPI_TYPE_LOCAL_INDEX_FIELD;
422
                break;
423
 
424
        default:
425
                return_ACPI_STATUS (AE_BAD_PARAMETER);
426
        }
427
 
428
        /*
429
         * Walk the list of entries in the field_list
430
         */
431
        while (arg) {
432
                /* Ignore OFFSET and ACCESSAS terms here */
433
 
434
                if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
435
                        status = acpi_ns_lookup (walk_state->scope_info,
436
                                          (char *) &arg->named.name,
437
                                          type, ACPI_IMODE_LOAD_PASS1,
438
                                          ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
439
                                          walk_state, &node);
440
                        if (ACPI_FAILURE (status)) {
441
                                ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
442
                                if (status != AE_ALREADY_EXISTS) {
443
                                        return_ACPI_STATUS (status);
444
                                }
445
 
446
                                /* Name already exists, just ignore this error */
447
 
448
                                status = AE_OK;
449
                        }
450
 
451
                        arg->common.node = node;
452
                }
453
 
454
                /* Move to next field in the list */
455
 
456
                arg = arg->common.next;
457
        }
458
 
459
        return_ACPI_STATUS (AE_OK);
460
}
461
 
462
 
463
/*******************************************************************************
464
 *
465
 * FUNCTION:    acpi_ds_create_bank_field
466
 *
467
 * PARAMETERS:  Op              - Op containing the Field definition and args
468
 *              region_node     - Object for the containing Operation Region
469
 *  `           walk_state      - Current method state
470
 *
471
 * RETURN:      Status
472
 *
473
 * DESCRIPTION: Create a new bank field in the specified operation region
474
 *
475
 ******************************************************************************/
476
 
477
acpi_status
478
acpi_ds_create_bank_field (
479
        union acpi_parse_object         *op,
480
        struct acpi_namespace_node      *region_node,
481
        struct acpi_walk_state          *walk_state)
482
{
483
        acpi_status                     status;
484
        union acpi_parse_object         *arg;
485
        struct acpi_create_field_info   info;
486
 
487
 
488
        ACPI_FUNCTION_TRACE_PTR ("ds_create_bank_field", op);
489
 
490
 
491
        /* First arg is the name of the parent op_region (must already exist) */
492
 
493
        arg = op->common.value.arg;
494
        if (!region_node) {
495
                status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
496
                                  ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
497
                                  ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
498
                if (ACPI_FAILURE (status)) {
499
                        ACPI_REPORT_NSERROR (arg->common.value.name, status);
500
                        return_ACPI_STATUS (status);
501
                }
502
        }
503
 
504
        /* Second arg is the Bank Register (Field) (must already exist) */
505
 
506
        arg = arg->common.next;
507
        status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
508
                          ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
509
                          ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
510
        if (ACPI_FAILURE (status)) {
511
                ACPI_REPORT_NSERROR (arg->common.value.string, status);
512
                return_ACPI_STATUS (status);
513
        }
514
 
515
        /* Third arg is the bank_value */
516
 
517
        arg = arg->common.next;
518
        info.bank_value = (u32) arg->common.value.integer;
519
 
520
        /* Fourth arg is the field flags */
521
 
522
        arg = arg->common.next;
523
        info.field_flags = (u8) arg->common.value.integer;
524
 
525
        /* Each remaining arg is a Named Field */
526
 
527
        info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
528
        info.region_node = region_node;
529
 
530
        status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
531
 
532
        return_ACPI_STATUS (status);
533
}
534
 
535
 
536
/*******************************************************************************
537
 *
538
 * FUNCTION:    acpi_ds_create_index_field
539
 *
540
 * PARAMETERS:  Op              - Op containing the Field definition and args
541
 *              region_node     - Object for the containing Operation Region
542
 *  `           walk_state      - Current method state
543
 *
544
 * RETURN:      Status
545
 *
546
 * DESCRIPTION: Create a new index field in the specified operation region
547
 *
548
 ******************************************************************************/
549
 
550
acpi_status
551
acpi_ds_create_index_field (
552
        union acpi_parse_object         *op,
553
        struct acpi_namespace_node      *region_node,
554
        struct acpi_walk_state          *walk_state)
555
{
556
        acpi_status                     status;
557
        union acpi_parse_object         *arg;
558
        struct acpi_create_field_info   info;
559
 
560
 
561
        ACPI_FUNCTION_TRACE_PTR ("ds_create_index_field", op);
562
 
563
 
564
        /* First arg is the name of the Index register (must already exist) */
565
 
566
        arg = op->common.value.arg;
567
        status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
568
                          ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
569
                          ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
570
        if (ACPI_FAILURE (status)) {
571
                ACPI_REPORT_NSERROR (arg->common.value.string, status);
572
                return_ACPI_STATUS (status);
573
        }
574
 
575
        /* Second arg is the data register (must already exist) */
576
 
577
        arg = arg->common.next;
578
        status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
579
                          ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
580
                          ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node);
581
        if (ACPI_FAILURE (status)) {
582
                ACPI_REPORT_NSERROR (arg->common.value.string, status);
583
                return_ACPI_STATUS (status);
584
        }
585
 
586
        /* Next arg is the field flags */
587
 
588
        arg = arg->common.next;
589
        info.field_flags = (u8) arg->common.value.integer;
590
 
591
        /* Each remaining arg is a Named Field */
592
 
593
        info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
594
        info.region_node = region_node;
595
 
596
        status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
597
 
598
        return_ACPI_STATUS (status);
599
}
600
 
601
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.