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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/******************************************************************************
2
 *
3
 * Module Name: excreate - Named object creation
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/acinterp.h>
47
#include <acpi/amlcode.h>
48
#include <acpi/acnamesp.h>
49
#include <acpi/acevents.h>
50
#include <acpi/actables.h>
51
 
52
 
53
#define _COMPONENT          ACPI_EXECUTER
54
         ACPI_MODULE_NAME    ("excreate")
55
 
56
 
57
#ifndef ACPI_NO_METHOD_EXECUTION
58
/*****************************************************************************
59
 *
60
 * FUNCTION:    acpi_ex_create_alias
61
 *
62
 * PARAMETERS:  walk_state           - Current state, contains operands
63
 *
64
 * RETURN:      Status
65
 *
66
 * DESCRIPTION: Create a new named alias
67
 *
68
 ****************************************************************************/
69
 
70
acpi_status
71
acpi_ex_create_alias (
72
        struct acpi_walk_state          *walk_state)
73
{
74
        struct acpi_namespace_node      *target_node;
75
        struct acpi_namespace_node      *alias_node;
76
        acpi_status                     status = AE_OK;
77
 
78
 
79
        ACPI_FUNCTION_TRACE ("ex_create_alias");
80
 
81
 
82
        /* Get the source/alias operands (both namespace nodes) */
83
 
84
        alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
85
        target_node = (struct acpi_namespace_node *) walk_state->operands[1];
86
 
87
        if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
88
                (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
89
                /*
90
                 * Dereference an existing alias so that we don't create a chain
91
                 * of aliases.  With this code, we guarantee that an alias is
92
                 * always exactly one level of indirection away from the
93
                 * actual aliased name.
94
                 */
95
                target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
96
        }
97
 
98
        /*
99
         * For objects that can never change (i.e., the NS node will
100
         * permanently point to the same object), we can simply attach
101
         * the object to the new NS node.  For other objects (such as
102
         * Integers, buffers, etc.), we have to point the Alias node
103
         * to the original Node.
104
         */
105
        switch (target_node->type) {
106
        case ACPI_TYPE_INTEGER:
107
        case ACPI_TYPE_STRING:
108
        case ACPI_TYPE_BUFFER:
109
        case ACPI_TYPE_PACKAGE:
110
        case ACPI_TYPE_BUFFER_FIELD:
111
 
112
                /*
113
                 * The new alias has the type ALIAS and points to the original
114
                 * NS node, not the object itself.  This is because for these
115
                 * types, the object can change dynamically via a Store.
116
                 */
117
                alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
118
                alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
119
                break;
120
 
121
        case ACPI_TYPE_METHOD:
122
 
123
                /*
124
                 * The new alias has the type ALIAS and points to the original
125
                 * NS node, not the object itself.  This is because for these
126
                 * types, the object can change dynamically via a Store.
127
                 */
128
                alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
129
                alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
130
                break;
131
 
132
        default:
133
 
134
                /* Attach the original source object to the new Alias Node */
135
 
136
                /*
137
                 * The new alias assumes the type of the target, and it points
138
                 * to the same object.  The reference count of the object has an
139
                 * additional reference to prevent deletion out from under either the
140
                 * target node or the alias Node
141
                 */
142
                status = acpi_ns_attach_object (alias_node,
143
                                 acpi_ns_get_attached_object (target_node),
144
                                 target_node->type);
145
                break;
146
        }
147
 
148
        /* Since both operands are Nodes, we don't need to delete them */
149
 
150
        return_ACPI_STATUS (status);
151
}
152
 
153
 
154
/*****************************************************************************
155
 *
156
 * FUNCTION:    acpi_ex_create_event
157
 *
158
 * PARAMETERS:  walk_state          - Current state
159
 *
160
 * RETURN:      Status
161
 *
162
 * DESCRIPTION: Create a new event object
163
 *
164
 ****************************************************************************/
165
 
166
acpi_status
167
acpi_ex_create_event (
168
        struct acpi_walk_state          *walk_state)
169
{
170
        acpi_status                     status;
171
        union acpi_operand_object       *obj_desc;
172
 
173
 
174
        ACPI_FUNCTION_TRACE ("ex_create_event");
175
 
176
 
177
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT);
178
        if (!obj_desc) {
179
                status = AE_NO_MEMORY;
180
                goto cleanup;
181
        }
182
 
183
        /*
184
         * Create the actual OS semaphore, with zero initial units -- meaning
185
         * that the event is created in an unsignalled state
186
         */
187
        status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0,
188
                           &obj_desc->event.semaphore);
189
        if (ACPI_FAILURE (status)) {
190
                goto cleanup;
191
        }
192
 
193
        /* Attach object to the Node */
194
 
195
        status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0],
196
                           obj_desc, ACPI_TYPE_EVENT);
197
 
198
cleanup:
199
        /*
200
         * Remove local reference to the object (on error, will cause deletion
201
         * of both object and semaphore if present.)
202
         */
203
        acpi_ut_remove_reference (obj_desc);
204
        return_ACPI_STATUS (status);
205
}
206
 
207
 
208
/*****************************************************************************
209
 *
210
 * FUNCTION:    acpi_ex_create_mutex
211
 *
212
 * PARAMETERS:  walk_state          - Current state
213
 *
214
 * RETURN:      Status
215
 *
216
 * DESCRIPTION: Create a new mutex object
217
 *
218
 *              Mutex (Name[0], sync_level[1])
219
 *
220
 ****************************************************************************/
221
 
222
acpi_status
223
acpi_ex_create_mutex (
224
        struct acpi_walk_state          *walk_state)
225
{
226
        acpi_status                     status = AE_OK;
227
        union acpi_operand_object       *obj_desc;
228
 
229
 
230
        ACPI_FUNCTION_TRACE_PTR ("ex_create_mutex", ACPI_WALK_OPERANDS);
231
 
232
 
233
        /* Create the new mutex object */
234
 
235
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX);
236
        if (!obj_desc) {
237
                status = AE_NO_MEMORY;
238
                goto cleanup;
239
        }
240
 
241
        /*
242
         * Create the actual OS semaphore.
243
         * One unit max to make it a mutex, with one initial unit to allow
244
         * the mutex to be acquired.
245
         */
246
        status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore);
247
        if (ACPI_FAILURE (status)) {
248
                goto cleanup;
249
        }
250
 
251
        /* Init object and attach to NS node */
252
 
253
        obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value;
254
        obj_desc->mutex.node = (struct acpi_namespace_node *) walk_state->operands[0];
255
 
256
        status = acpi_ns_attach_object (obj_desc->mutex.node,
257
                         obj_desc, ACPI_TYPE_MUTEX);
258
 
259
 
260
cleanup:
261
        /*
262
         * Remove local reference to the object (on error, will cause deletion
263
         * of both object and semaphore if present.)
264
         */
265
        acpi_ut_remove_reference (obj_desc);
266
        return_ACPI_STATUS (status);
267
}
268
 
269
 
270
/*****************************************************************************
271
 *
272
 * FUNCTION:    acpi_ex_create_region
273
 *
274
 * PARAMETERS:  aml_start           - Pointer to the region declaration AML
275
 *              aml_length          - Max length of the declaration AML
276
 *              Operands            - List of operands for the opcode
277
 *              walk_state          - Current state
278
 *
279
 * RETURN:      Status
280
 *
281
 * DESCRIPTION: Create a new operation region object
282
 *
283
 ****************************************************************************/
284
 
285
acpi_status
286
acpi_ex_create_region (
287
        u8                              *aml_start,
288
        u32                             aml_length,
289
        u8                              region_space,
290
        struct acpi_walk_state          *walk_state)
291
{
292
        acpi_status                     status;
293
        union acpi_operand_object       *obj_desc;
294
        struct acpi_namespace_node      *node;
295
        union acpi_operand_object       *region_obj2;
296
 
297
 
298
        ACPI_FUNCTION_TRACE ("ex_create_region");
299
 
300
 
301
        /* Get the Namespace Node */
302
 
303
        node = walk_state->op->common.node;
304
 
305
        /*
306
         * If the region object is already attached to this node,
307
         * just return
308
         */
309
        if (acpi_ns_get_attached_object (node)) {
310
                return_ACPI_STATUS (AE_OK);
311
        }
312
 
313
        /*
314
         * Space ID must be one of the predefined IDs, or in the user-defined
315
         * range
316
         */
317
        if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
318
                (region_space < ACPI_USER_REGION_BEGIN)) {
319
                ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space));
320
                return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
321
        }
322
 
323
        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
324
                          acpi_ut_get_region_name (region_space), region_space));
325
 
326
        /* Create the region descriptor */
327
 
328
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
329
        if (!obj_desc) {
330
                status = AE_NO_MEMORY;
331
                goto cleanup;
332
        }
333
 
334
        /*
335
         * Remember location in AML stream of address & length
336
         * operands since they need to be evaluated at run time.
337
         */
338
        region_obj2                 = obj_desc->common.next_object;
339
        region_obj2->extra.aml_start = aml_start;
340
        region_obj2->extra.aml_length = aml_length;
341
 
342
        /* Init the region from the operands */
343
 
344
        obj_desc->region.space_id = region_space;
345
        obj_desc->region.address = 0;
346
        obj_desc->region.length = 0;
347
        obj_desc->region.node   = node;
348
 
349
        /* Install the new region object in the parent Node */
350
 
351
        status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
352
 
353
 
354
cleanup:
355
 
356
        /* Remove local reference to the object */
357
 
358
        acpi_ut_remove_reference (obj_desc);
359
        return_ACPI_STATUS (status);
360
}
361
 
362
 
363
/*****************************************************************************
364
 *
365
 * FUNCTION:    acpi_ex_create_table_region
366
 *
367
 * PARAMETERS:  walk_state          - Current state
368
 *
369
 * RETURN:      Status
370
 *
371
 * DESCRIPTION: Create a new data_table_region object
372
 *
373
 ****************************************************************************/
374
 
375
acpi_status
376
acpi_ex_create_table_region (
377
        struct acpi_walk_state          *walk_state)
378
{
379
        acpi_status                     status;
380
        union acpi_operand_object       **operand = &walk_state->operands[0];
381
        union acpi_operand_object       *obj_desc;
382
        struct acpi_namespace_node      *node;
383
        struct acpi_table_header        *table;
384
        union acpi_operand_object       *region_obj2;
385
 
386
 
387
        ACPI_FUNCTION_TRACE ("ex_create_table_region");
388
 
389
 
390
        /* Get the Node from the object stack  */
391
 
392
        node = walk_state->op->common.node;
393
 
394
        /*
395
         * If the region object is already attached to this node,
396
         * just return
397
         */
398
        if (acpi_ns_get_attached_object (node)) {
399
                return_ACPI_STATUS (AE_OK);
400
        }
401
 
402
        /* Find the ACPI table */
403
 
404
        status = acpi_tb_find_table (operand[1]->string.pointer,
405
                           operand[2]->string.pointer,
406
                           operand[3]->string.pointer, &table);
407
        if (ACPI_FAILURE (status)) {
408
                return_ACPI_STATUS (status);
409
        }
410
 
411
        /* Create the region descriptor */
412
 
413
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
414
        if (!obj_desc) {
415
                return_ACPI_STATUS (AE_NO_MEMORY);
416
        }
417
 
418
        region_obj2                     = obj_desc->common.next_object;
419
        region_obj2->extra.region_context = NULL;
420
 
421
        /* Init the region from the operands */
422
 
423
        obj_desc->region.space_id = REGION_DATA_TABLE;
424
        obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table);
425
        obj_desc->region.length = table->length;
426
        obj_desc->region.node   = node;
427
        obj_desc->region.flags  = AOPOBJ_DATA_VALID;
428
 
429
        /* Install the new region object in the parent Node */
430
 
431
        status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
432
        if (ACPI_FAILURE (status)) {
433
                goto cleanup;
434
        }
435
 
436
        status = acpi_ev_initialize_region (obj_desc, FALSE);
437
        if (ACPI_FAILURE (status)) {
438
                if (status == AE_NOT_EXIST) {
439
                        status = AE_OK;
440
                }
441
                else {
442
                        goto cleanup;
443
                }
444
        }
445
 
446
        obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
447
 
448
 
449
cleanup:
450
 
451
        /* Remove local reference to the object */
452
 
453
        acpi_ut_remove_reference (obj_desc);
454
        return_ACPI_STATUS (status);
455
}
456
 
457
 
458
/*****************************************************************************
459
 *
460
 * FUNCTION:    acpi_ex_create_processor
461
 *
462
 * PARAMETERS:  walk_state          - Current state
463
 *
464
 * RETURN:      Status
465
 *
466
 * DESCRIPTION: Create a new processor object and populate the fields
467
 *
468
 *              Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3])
469
 *
470
 ****************************************************************************/
471
 
472
acpi_status
473
acpi_ex_create_processor (
474
        struct acpi_walk_state          *walk_state)
475
{
476
        union acpi_operand_object       **operand = &walk_state->operands[0];
477
        union acpi_operand_object       *obj_desc;
478
        acpi_status                     status;
479
 
480
 
481
        ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state);
482
 
483
 
484
        /* Create the processor object */
485
 
486
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR);
487
        if (!obj_desc) {
488
                return_ACPI_STATUS (AE_NO_MEMORY);
489
        }
490
 
491
        /*
492
         * Initialize the processor object from the operands
493
         */
494
        obj_desc->processor.proc_id = (u8)          operand[1]->integer.value;
495
        obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value;
496
        obj_desc->processor.length = (u8)           operand[3]->integer.value;
497
 
498
        /* Install the processor object in the parent Node */
499
 
500
        status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
501
                          obj_desc, ACPI_TYPE_PROCESSOR);
502
 
503
        /* Remove local reference to the object */
504
 
505
        acpi_ut_remove_reference (obj_desc);
506
        return_ACPI_STATUS (status);
507
}
508
 
509
 
510
/*****************************************************************************
511
 *
512
 * FUNCTION:    acpi_ex_create_power_resource
513
 *
514
 * PARAMETERS:  walk_state          - Current state
515
 *
516
 * RETURN:      Status
517
 *
518
 * DESCRIPTION: Create a new power_resource object and populate the fields
519
 *
520
 *              power_resource (Name[0], system_level[1], resource_order[2])
521
 *
522
 ****************************************************************************/
523
 
524
acpi_status
525
acpi_ex_create_power_resource (
526
        struct acpi_walk_state          *walk_state)
527
{
528
        union acpi_operand_object       **operand = &walk_state->operands[0];
529
        acpi_status                     status;
530
        union acpi_operand_object       *obj_desc;
531
 
532
 
533
        ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state);
534
 
535
 
536
        /* Create the power resource object */
537
 
538
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER);
539
        if (!obj_desc) {
540
                return_ACPI_STATUS (AE_NO_MEMORY);
541
        }
542
 
543
        /* Initialize the power object from the operands */
544
 
545
        obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
546
        obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value;
547
 
548
        /* Install the  power resource object in the parent Node */
549
 
550
        status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
551
                          obj_desc, ACPI_TYPE_POWER);
552
 
553
        /* Remove local reference to the object */
554
 
555
        acpi_ut_remove_reference (obj_desc);
556
        return_ACPI_STATUS (status);
557
}
558
 
559
#endif
560
 
561
/*****************************************************************************
562
 *
563
 * FUNCTION:    acpi_ex_create_method
564
 *
565
 * PARAMETERS:  aml_start       - First byte of the method's AML
566
 *              aml_length      - AML byte count for this method
567
 *              walk_state      - Current state
568
 *
569
 * RETURN:      Status
570
 *
571
 * DESCRIPTION: Create a new method object
572
 *
573
 ****************************************************************************/
574
 
575
acpi_status
576
acpi_ex_create_method (
577
        u8                              *aml_start,
578
        u32                             aml_length,
579
        struct acpi_walk_state          *walk_state)
580
{
581
        union acpi_operand_object       **operand = &walk_state->operands[0];
582
        union acpi_operand_object       *obj_desc;
583
        acpi_status                     status;
584
        u8                              method_flags;
585
 
586
 
587
        ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state);
588
 
589
 
590
        /* Create a new method object */
591
 
592
        obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD);
593
        if (!obj_desc) {
594
           return_ACPI_STATUS (AE_NO_MEMORY);
595
        }
596
 
597
        /* Save the method's AML pointer and length  */
598
 
599
        obj_desc->method.aml_start = aml_start;
600
        obj_desc->method.aml_length = aml_length;
601
 
602
        /*
603
         * Disassemble the method flags.  Split off the Arg Count
604
         * for efficiency
605
         */
606
        method_flags = (u8) operand[1]->integer.value;
607
 
608
        obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
609
        obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
610
 
611
        /*
612
         * Get the concurrency count.  If required, a semaphore will be
613
         * created for this method when it is parsed.
614
         */
615
        if (acpi_gbl_all_methods_serialized) {
616
                obj_desc->method.concurrency = 1;
617
                obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
618
        }
619
        else if (method_flags & AML_METHOD_SERIALIZED) {
620
                /*
621
                 * ACPI 1.0: Concurrency = 1
622
                 * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
623
                 */
624
                obj_desc->method.concurrency = (u8)
625
                                  (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
626
        }
627
        else {
628
                obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
629
        }
630
 
631
        /* Attach the new object to the method Node */
632
 
633
        status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
634
                          obj_desc, ACPI_TYPE_METHOD);
635
 
636
        /* Remove local reference to the object */
637
 
638
        acpi_ut_remove_reference (obj_desc);
639
 
640
        /* Remove a reference to the operand */
641
 
642
        acpi_ut_remove_reference (operand[1]);
643
        return_ACPI_STATUS (status);
644
}
645
 
646
 

powered by: WebSVN 2.1.0

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