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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [dispatcher/] [dsfield.c] - Blame information for rev 67

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/******************************************************************************
2
 *
3
 * Module Name: dsfield - Dispatcher field routines
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2007, 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
#include <acpi/acpi.h>
45
#include <acpi/amlcode.h>
46
#include <acpi/acdispat.h>
47
#include <acpi/acinterp.h>
48
#include <acpi/acnamesp.h>
49
#include <acpi/acparser.h>
50
 
51
#define _COMPONENT          ACPI_DISPATCHER
52
ACPI_MODULE_NAME("dsfield")
53
 
54
/* Local prototypes */
55
static acpi_status
56
acpi_ds_get_field_names(struct acpi_create_field_info *info,
57
                        struct acpi_walk_state *walk_state,
58
                        union acpi_parse_object *arg);
59
 
60
/*******************************************************************************
61
 *
62
 * FUNCTION:    acpi_ds_create_buffer_field
63
 *
64
 * PARAMETERS:  Op                  - Current parse op (create_xXField)
65
 *              walk_state          - Current state
66
 *
67
 * RETURN:      Status
68
 *
69
 * DESCRIPTION: Execute the create_field operators:
70
 *              create_bit_field_op,
71
 *              create_byte_field_op,
72
 *              create_word_field_op,
73
 *              create_dword_field_op,
74
 *              create_qword_field_op,
75
 *              create_field_op     (all of which define a field in a buffer)
76
 *
77
 ******************************************************************************/
78
 
79
acpi_status
80
acpi_ds_create_buffer_field(union acpi_parse_object *op,
81
                            struct acpi_walk_state *walk_state)
82
{
83
        union acpi_parse_object *arg;
84
        struct acpi_namespace_node *node;
85
        acpi_status status;
86
        union acpi_operand_object *obj_desc;
87
        union acpi_operand_object *second_desc = NULL;
88
        u32 flags;
89
 
90
        ACPI_FUNCTION_TRACE(ds_create_buffer_field);
91
 
92
        /* Get the name_string argument */
93
 
94
        if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
95
                arg = acpi_ps_get_arg(op, 3);
96
        } else {
97
                /* Create Bit/Byte/Word/Dword field */
98
 
99
                arg = acpi_ps_get_arg(op, 2);
100
        }
101
 
102
        if (!arg) {
103
                return_ACPI_STATUS(AE_AML_NO_OPERAND);
104
        }
105
 
106
        if (walk_state->deferred_node) {
107
                node = walk_state->deferred_node;
108
                status = AE_OK;
109
        } else {
110
                /*
111
                 * During the load phase, we want to enter the name of the field into
112
                 * the namespace.  During the execute phase (when we evaluate the size
113
                 * operand), we want to lookup the name
114
                 */
115
                if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
116
                        flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
117
                } else {
118
                        flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
119
                            ACPI_NS_ERROR_IF_FOUND;
120
                }
121
 
122
                /*
123
                 * Enter the name_string into the namespace
124
                 */
125
                status =
126
                    acpi_ns_lookup(walk_state->scope_info,
127
                                   arg->common.value.string, ACPI_TYPE_ANY,
128
                                   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
129
                                   &(node));
130
                if (ACPI_FAILURE(status)) {
131
                        ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
132
                        return_ACPI_STATUS(status);
133
                }
134
        }
135
 
136
        /*
137
         * We could put the returned object (Node) on the object stack for later,
138
         * but for now, we will put it in the "op" object that the parser uses,
139
         * so we 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
145
         * and we need to create the field object.  Otherwise, this was a lookup
146
         * of an 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
      cleanup:
184
 
185
        /* Remove local reference to the object */
186
 
187
        acpi_ut_remove_reference(obj_desc);
188
        return_ACPI_STATUS(status);
189
}
190
 
191
/*******************************************************************************
192
 *
193
 * FUNCTION:    acpi_ds_get_field_names
194
 *
195
 * PARAMETERS:  Info            - create_field info structure
196
 *  `           walk_state      - Current method state
197
 *              Arg             - First parser arg for the field name list
198
 *
199
 * RETURN:      Status
200
 *
201
 * DESCRIPTION: Process all named fields in a field declaration.  Names are
202
 *              entered into the namespace.
203
 *
204
 ******************************************************************************/
205
 
206
static acpi_status
207
acpi_ds_get_field_names(struct acpi_create_field_info *info,
208
                        struct acpi_walk_state *walk_state,
209
                        union acpi_parse_object *arg)
210
{
211
        acpi_status status;
212
        acpi_integer position;
213
 
214
        ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
215
 
216
        /* First field starts at bit zero */
217
 
218
        info->field_bit_position = 0;
219
 
220
        /* Process all elements in the field list (of parse nodes) */
221
 
222
        while (arg) {
223
                /*
224
                 * Three types of field elements are handled:
225
                 * 1) Offset - specifies a bit offset
226
                 * 2) access_as - changes the access mode
227
                 * 3) Name - Enters a new named field into the namespace
228
                 */
229
                switch (arg->common.aml_opcode) {
230
                case AML_INT_RESERVEDFIELD_OP:
231
 
232
                        position = (acpi_integer) info->field_bit_position
233
                            + (acpi_integer) arg->common.value.size;
234
 
235
                        if (position > ACPI_UINT32_MAX) {
236
                                ACPI_ERROR((AE_INFO,
237
                                            "Bit offset within field too large (> 0xFFFFFFFF)"));
238
                                return_ACPI_STATUS(AE_SUPPORT);
239
                        }
240
 
241
                        info->field_bit_position = (u32) position;
242
                        break;
243
 
244
                case AML_INT_ACCESSFIELD_OP:
245
 
246
                        /*
247
                         * Get a new access_type and access_attribute -- to be used for all
248
                         * field units that follow, until field end or another access_as
249
                         * keyword.
250
                         *
251
                         * In field_flags, preserve the flag bits other than the
252
                         * ACCESS_TYPE bits
253
                         */
254
                        info->field_flags = (u8)
255
                            ((info->
256
                              field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
257
                             ((u8) ((u32) arg->common.value.integer >> 8)));
258
 
259
                        info->attribute = (u8) (arg->common.value.integer);
260
                        break;
261
 
262
                case AML_INT_NAMEDFIELD_OP:
263
 
264
                        /* Lookup the name */
265
 
266
                        status = acpi_ns_lookup(walk_state->scope_info,
267
                                                (char *)&arg->named.name,
268
                                                info->field_type,
269
                                                ACPI_IMODE_EXECUTE,
270
                                                ACPI_NS_DONT_OPEN_SCOPE,
271
                                                walk_state, &info->field_node);
272
                        if (ACPI_FAILURE(status)) {
273
                                ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
274
                                                     status);
275
                                if (status != AE_ALREADY_EXISTS) {
276
                                        return_ACPI_STATUS(status);
277
                                }
278
 
279
                                /* Already exists, ignore error */
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_ERROR((AE_INFO,
299
                                            "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
300
                                            ACPI_CAST_PTR(char,
301
                                                          &info->field_node->
302
                                                          name)));
303
                                return_ACPI_STATUS(AE_SUPPORT);
304
                        }
305
 
306
                        info->field_bit_position += info->field_bit_length;
307
                        break;
308
 
309
                default:
310
 
311
                        ACPI_ERROR((AE_INFO,
312
                                    "Invalid opcode in field list: %X",
313
                                    arg->common.aml_opcode));
314
                        return_ACPI_STATUS(AE_AML_BAD_OPCODE);
315
                }
316
 
317
                arg = arg->common.next;
318
        }
319
 
320
        return_ACPI_STATUS(AE_OK);
321
}
322
 
323
/*******************************************************************************
324
 *
325
 * FUNCTION:    acpi_ds_create_field
326
 *
327
 * PARAMETERS:  Op              - Op containing the Field definition and args
328
 *              region_node     - Object for the containing Operation Region
329
 *  `           walk_state      - Current method state
330
 *
331
 * RETURN:      Status
332
 *
333
 * DESCRIPTION: Create a new field in the specified operation region
334
 *
335
 ******************************************************************************/
336
 
337
acpi_status
338
acpi_ds_create_field(union acpi_parse_object *op,
339
                     struct acpi_namespace_node *region_node,
340
                     struct acpi_walk_state *walk_state)
341
{
342
        acpi_status status;
343
        union acpi_parse_object *arg;
344
        struct acpi_create_field_info info;
345
 
346
        ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
347
 
348
        /* First arg is the name of the parent op_region (must already exist) */
349
 
350
        arg = op->common.value.arg;
351
        if (!region_node) {
352
                status =
353
                    acpi_ns_lookup(walk_state->scope_info,
354
                                   arg->common.value.name, ACPI_TYPE_REGION,
355
                                   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
356
                                   walk_state, &region_node);
357
                if (ACPI_FAILURE(status)) {
358
                        ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
359
                        return_ACPI_STATUS(status);
360
                }
361
        }
362
 
363
        /* Second arg is the field flags */
364
 
365
        arg = arg->common.next;
366
        info.field_flags = (u8) arg->common.value.integer;
367
        info.attribute = 0;
368
 
369
        /* Each remaining arg is a Named Field */
370
 
371
        info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
372
        info.region_node = region_node;
373
 
374
        status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
375
 
376
        return_ACPI_STATUS(status);
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(union acpi_parse_object *op,
396
                           struct acpi_walk_state *walk_state)
397
{
398
        acpi_status status;
399
        union acpi_parse_object *arg = NULL;
400
        struct acpi_namespace_node *node;
401
        u8 type = 0;
402
 
403
        ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
404
 
405
        switch (walk_state->opcode) {
406
        case AML_FIELD_OP:
407
                arg = acpi_ps_get_arg(op, 2);
408
                type = ACPI_TYPE_LOCAL_REGION_FIELD;
409
                break;
410
 
411
        case AML_BANK_FIELD_OP:
412
                arg = acpi_ps_get_arg(op, 4);
413
                type = ACPI_TYPE_LOCAL_BANK_FIELD;
414
                break;
415
 
416
        case AML_INDEX_FIELD_OP:
417
                arg = acpi_ps_get_arg(op, 3);
418
                type = ACPI_TYPE_LOCAL_INDEX_FIELD;
419
                break;
420
 
421
        default:
422
                return_ACPI_STATUS(AE_BAD_PARAMETER);
423
        }
424
 
425
        /*
426
         * Walk the list of entries in the field_list
427
         */
428
        while (arg) {
429
 
430
                /* Ignore OFFSET and ACCESSAS terms here */
431
 
432
                if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
433
                        status = acpi_ns_lookup(walk_state->scope_info,
434
                                                (char *)&arg->named.name,
435
                                                type, ACPI_IMODE_LOAD_PASS1,
436
                                                ACPI_NS_NO_UPSEARCH |
437
                                                ACPI_NS_DONT_OPEN_SCOPE |
438
                                                ACPI_NS_ERROR_IF_FOUND,
439
                                                walk_state, &node);
440
                        if (ACPI_FAILURE(status)) {
441
                                ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
442
                                                     status);
443
                                if (status != AE_ALREADY_EXISTS) {
444
                                        return_ACPI_STATUS(status);
445
                                }
446
 
447
                                /* Name already exists, just ignore this error */
448
 
449
                                status = AE_OK;
450
                        }
451
 
452
                        arg->common.node = node;
453
                }
454
 
455
                /* Move to next field in the list */
456
 
457
                arg = arg->common.next;
458
        }
459
 
460
        return_ACPI_STATUS(AE_OK);
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(union acpi_parse_object *op,
479
                          struct acpi_namespace_node *region_node,
480
                          struct acpi_walk_state *walk_state)
481
{
482
        acpi_status status;
483
        union acpi_parse_object *arg;
484
        struct acpi_create_field_info info;
485
 
486
        ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
487
 
488
        /* First arg is the name of the parent op_region (must already exist) */
489
 
490
        arg = op->common.value.arg;
491
        if (!region_node) {
492
                status =
493
                    acpi_ns_lookup(walk_state->scope_info,
494
                                   arg->common.value.name, ACPI_TYPE_REGION,
495
                                   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
496
                                   walk_state, &region_node);
497
                if (ACPI_FAILURE(status)) {
498
                        ACPI_ERROR_NAMESPACE(arg->common.value.name, status);
499
                        return_ACPI_STATUS(status);
500
                }
501
        }
502
 
503
        /* Second arg is the Bank Register (Field) (must already exist) */
504
 
505
        arg = arg->common.next;
506
        status =
507
            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,
510
                           &info.register_node);
511
        if (ACPI_FAILURE(status)) {
512
                ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
513
                return_ACPI_STATUS(status);
514
        }
515
 
516
        /* Third arg is the bank_value */
517
 
518
        /* TBD: This arg is a term_arg, not a constant, and must be evaluated */
519
 
520
        arg = arg->common.next;
521
 
522
        /* Currently, only the following constants are supported */
523
 
524
        switch (arg->common.aml_opcode) {
525
        case AML_ZERO_OP:
526
                info.bank_value = 0;
527
                break;
528
 
529
        case AML_ONE_OP:
530
                info.bank_value = 1;
531
                break;
532
 
533
        case AML_BYTE_OP:
534
        case AML_WORD_OP:
535
        case AML_DWORD_OP:
536
        case AML_QWORD_OP:
537
                info.bank_value = (u32) arg->common.value.integer;
538
                break;
539
 
540
        default:
541
                info.bank_value = 0;
542
                ACPI_ERROR((AE_INFO,
543
                            "Non-constant BankValue for BankField is not implemented"));
544
        }
545
 
546
        /* Fourth arg is the field flags */
547
 
548
        arg = arg->common.next;
549
        info.field_flags = (u8) arg->common.value.integer;
550
 
551
        /* Each remaining arg is a Named Field */
552
 
553
        info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
554
        info.region_node = region_node;
555
 
556
        status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
557
 
558
        return_ACPI_STATUS(status);
559
}
560
 
561
/*******************************************************************************
562
 *
563
 * FUNCTION:    acpi_ds_create_index_field
564
 *
565
 * PARAMETERS:  Op              - Op containing the Field definition and args
566
 *              region_node     - Object for the containing Operation Region
567
 *  `           walk_state      - Current method state
568
 *
569
 * RETURN:      Status
570
 *
571
 * DESCRIPTION: Create a new index field in the specified operation region
572
 *
573
 ******************************************************************************/
574
 
575
acpi_status
576
acpi_ds_create_index_field(union acpi_parse_object *op,
577
                           struct acpi_namespace_node *region_node,
578
                           struct acpi_walk_state *walk_state)
579
{
580
        acpi_status status;
581
        union acpi_parse_object *arg;
582
        struct acpi_create_field_info info;
583
 
584
        ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
585
 
586
        /* First arg is the name of the Index register (must already exist) */
587
 
588
        arg = op->common.value.arg;
589
        status =
590
            acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
591
                           ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
592
                           ACPI_NS_SEARCH_PARENT, walk_state,
593
                           &info.register_node);
594
        if (ACPI_FAILURE(status)) {
595
                ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
596
                return_ACPI_STATUS(status);
597
        }
598
 
599
        /* Second arg is the data register (must already exist) */
600
 
601
        arg = arg->common.next;
602
        status =
603
            acpi_ns_lookup(walk_state->scope_info, arg->common.value.string,
604
                           ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
605
                           ACPI_NS_SEARCH_PARENT, walk_state,
606
                           &info.data_register_node);
607
        if (ACPI_FAILURE(status)) {
608
                ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
609
                return_ACPI_STATUS(status);
610
        }
611
 
612
        /* Next arg is the field flags */
613
 
614
        arg = arg->common.next;
615
        info.field_flags = (u8) arg->common.value.integer;
616
 
617
        /* Each remaining arg is a Named Field */
618
 
619
        info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
620
        info.region_node = region_node;
621
 
622
        status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
623
 
624
        return_ACPI_STATUS(status);
625
}

powered by: WebSVN 2.1.0

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