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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [resources/] [rscalc.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: rscalc - Calculate stream and list lengths
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/acresrc.h>
46
#include <acpi/amlcode.h>
47
#include <acpi/acnamesp.h>
48
 
49
#define _COMPONENT          ACPI_RESOURCES
50
ACPI_MODULE_NAME("rscalc")
51
 
52
/* Local prototypes */
53
static u8 acpi_rs_count_set_bits(u16 bit_field);
54
 
55
static acpi_rs_length
56
acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
57
 
58
static u32
59
acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
60
 
61
/*******************************************************************************
62
 *
63
 * FUNCTION:    acpi_rs_count_set_bits
64
 *
65
 * PARAMETERS:  bit_field       - Field in which to count bits
66
 *
67
 * RETURN:      Number of bits set within the field
68
 *
69
 * DESCRIPTION: Count the number of bits set in a resource field. Used for
70
 *              (Short descriptor) interrupt and DMA lists.
71
 *
72
 ******************************************************************************/
73
 
74
static u8 acpi_rs_count_set_bits(u16 bit_field)
75
{
76
        u8 bits_set;
77
 
78
        ACPI_FUNCTION_ENTRY();
79
 
80
        for (bits_set = 0; bit_field; bits_set++) {
81
 
82
                /* Zero the least significant bit that is set */
83
 
84
                bit_field &= (bit_field - 1);
85
        }
86
 
87
        return (bits_set);
88
}
89
 
90
/*******************************************************************************
91
 *
92
 * FUNCTION:    acpi_rs_struct_option_length
93
 *
94
 * PARAMETERS:  resource_source     - Pointer to optional descriptor field
95
 *
96
 * RETURN:      Status
97
 *
98
 * DESCRIPTION: Common code to handle optional resource_source_index and
99
 *              resource_source fields in some Large descriptors. Used during
100
 *              list-to-stream conversion
101
 *
102
 ******************************************************************************/
103
 
104
static acpi_rs_length
105
acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
106
{
107
        ACPI_FUNCTION_ENTRY();
108
 
109
        /*
110
         * If the resource_source string is valid, return the size of the string
111
         * (string_length includes the NULL terminator) plus the size of the
112
         * resource_source_index (1).
113
         */
114
        if (resource_source->string_ptr) {
115
                return ((acpi_rs_length) (resource_source->string_length + 1));
116
        }
117
 
118
        return (0);
119
}
120
 
121
/*******************************************************************************
122
 *
123
 * FUNCTION:    acpi_rs_stream_option_length
124
 *
125
 * PARAMETERS:  resource_length     - Length from the resource header
126
 *              minimum_total_length - Minimum length of this resource, before
127
 *                                    any optional fields. Includes header size
128
 *
129
 * RETURN:      Length of optional string (0 if no string present)
130
 *
131
 * DESCRIPTION: Common code to handle optional resource_source_index and
132
 *              resource_source fields in some Large descriptors. Used during
133
 *              stream-to-list conversion
134
 *
135
 ******************************************************************************/
136
 
137
static u32
138
acpi_rs_stream_option_length(u32 resource_length,
139
                             u32 minimum_aml_resource_length)
140
{
141
        u32 string_length = 0;
142
 
143
        ACPI_FUNCTION_ENTRY();
144
 
145
        /*
146
         * The resource_source_index and resource_source are optional elements of some
147
         * Large-type resource descriptors.
148
         */
149
 
150
        /*
151
         * If the length of the actual resource descriptor is greater than the ACPI
152
         * spec-defined minimum length, it means that a resource_source_index exists
153
         * and is followed by a (required) null terminated string. The string length
154
         * (including the null terminator) is the resource length minus the minimum
155
         * length, minus one byte for the resource_source_index itself.
156
         */
157
        if (resource_length > minimum_aml_resource_length) {
158
 
159
                /* Compute the length of the optional string */
160
 
161
                string_length =
162
                    resource_length - minimum_aml_resource_length - 1;
163
        }
164
 
165
        /*
166
         * Round the length up to a multiple of the native word in order to
167
         * guarantee that the entire resource descriptor is native word aligned
168
         */
169
        return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
170
}
171
 
172
/*******************************************************************************
173
 *
174
 * FUNCTION:    acpi_rs_get_aml_length
175
 *
176
 * PARAMETERS:  Resource            - Pointer to the resource linked list
177
 *              size_needed         - Where the required size is returned
178
 *
179
 * RETURN:      Status
180
 *
181
 * DESCRIPTION: Takes a linked list of internal resource descriptors and
182
 *              calculates the size buffer needed to hold the corresponding
183
 *              external resource byte stream.
184
 *
185
 ******************************************************************************/
186
 
187
acpi_status
188
acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
189
{
190
        acpi_size aml_size_needed = 0;
191
        acpi_rs_length total_size;
192
 
193
        ACPI_FUNCTION_TRACE(rs_get_aml_length);
194
 
195
        /* Traverse entire list of internal resource descriptors */
196
 
197
        while (resource) {
198
 
199
                /* Validate the descriptor type */
200
 
201
                if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
202
                        return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
203
                }
204
 
205
                /* Get the base size of the (external stream) resource descriptor */
206
 
207
                total_size = acpi_gbl_aml_resource_sizes[resource->type];
208
 
209
                /*
210
                 * Augment the base size for descriptors with optional and/or
211
                 * variable-length fields
212
                 */
213
                switch (resource->type) {
214
                case ACPI_RESOURCE_TYPE_VENDOR:
215
                        /*
216
                         * Vendor Defined Resource:
217
                         * For a Vendor Specific resource, if the Length is between 1 and 7
218
                         * it will be created as a Small Resource data type, otherwise it
219
                         * is a Large Resource data type.
220
                         */
221
                        if (resource->data.vendor.byte_length > 7) {
222
 
223
                                /* Base size of a Large resource descriptor */
224
 
225
                                total_size =
226
                                    sizeof(struct aml_resource_large_header);
227
                        }
228
 
229
                        /* Add the size of the vendor-specific data */
230
 
231
                        total_size = (acpi_rs_length)
232
                            (total_size + resource->data.vendor.byte_length);
233
                        break;
234
 
235
                case ACPI_RESOURCE_TYPE_END_TAG:
236
                        /*
237
                         * End Tag:
238
                         * We are done -- return the accumulated total size.
239
                         */
240
                        *size_needed = aml_size_needed + total_size;
241
 
242
                        /* Normal exit */
243
 
244
                        return_ACPI_STATUS(AE_OK);
245
 
246
                case ACPI_RESOURCE_TYPE_ADDRESS16:
247
                        /*
248
                         * 16-Bit Address Resource:
249
                         * Add the size of the optional resource_source info
250
                         */
251
                        total_size = (acpi_rs_length)
252
                            (total_size +
253
                             acpi_rs_struct_option_length(&resource->data.
254
                                                          address16.
255
                                                          resource_source));
256
                        break;
257
 
258
                case ACPI_RESOURCE_TYPE_ADDRESS32:
259
                        /*
260
                         * 32-Bit Address Resource:
261
                         * Add the size of the optional resource_source info
262
                         */
263
                        total_size = (acpi_rs_length)
264
                            (total_size +
265
                             acpi_rs_struct_option_length(&resource->data.
266
                                                          address32.
267
                                                          resource_source));
268
                        break;
269
 
270
                case ACPI_RESOURCE_TYPE_ADDRESS64:
271
                        /*
272
                         * 64-Bit Address Resource:
273
                         * Add the size of the optional resource_source info
274
                         */
275
                        total_size = (acpi_rs_length)
276
                            (total_size +
277
                             acpi_rs_struct_option_length(&resource->data.
278
                                                          address64.
279
                                                          resource_source));
280
                        break;
281
 
282
                case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
283
                        /*
284
                         * Extended IRQ Resource:
285
                         * Add the size of each additional optional interrupt beyond the
286
                         * required 1 (4 bytes for each u32 interrupt number)
287
                         */
288
                        total_size = (acpi_rs_length)
289
                            (total_size +
290
                             ((resource->data.extended_irq.interrupt_count -
291
                               1) * 4) +
292
                             /* Add the size of the optional resource_source info */
293
                             acpi_rs_struct_option_length(&resource->data.
294
                                                          extended_irq.
295
                                                          resource_source));
296
                        break;
297
 
298
                default:
299
                        break;
300
                }
301
 
302
                /* Update the total */
303
 
304
                aml_size_needed += total_size;
305
 
306
                /* Point to the next object */
307
 
308
                resource =
309
                    ACPI_ADD_PTR(struct acpi_resource, resource,
310
                                 resource->length);
311
        }
312
 
313
        /* Did not find an end_tag resource descriptor */
314
 
315
        return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
316
}
317
 
318
/*******************************************************************************
319
 *
320
 * FUNCTION:    acpi_rs_get_list_length
321
 *
322
 * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
323
 *              aml_buffer_length   - Size of aml_buffer
324
 *              size_needed         - Where the size needed is returned
325
 *
326
 * RETURN:      Status
327
 *
328
 * DESCRIPTION: Takes an external resource byte stream and calculates the size
329
 *              buffer needed to hold the corresponding internal resource
330
 *              descriptor linked list.
331
 *
332
 ******************************************************************************/
333
 
334
acpi_status
335
acpi_rs_get_list_length(u8 * aml_buffer,
336
                        u32 aml_buffer_length, acpi_size * size_needed)
337
{
338
        acpi_status status;
339
        u8 *end_aml;
340
        u8 *buffer;
341
        u32 buffer_size;
342
        u16 temp16;
343
        u16 resource_length;
344
        u32 extra_struct_bytes;
345
        u8 resource_index;
346
        u8 minimum_aml_resource_length;
347
 
348
        ACPI_FUNCTION_TRACE(rs_get_list_length);
349
 
350
        *size_needed = 0;
351
        end_aml = aml_buffer + aml_buffer_length;
352
 
353
        /* Walk the list of AML resource descriptors */
354
 
355
        while (aml_buffer < end_aml) {
356
 
357
                /* Validate the Resource Type and Resource Length */
358
 
359
                status = acpi_ut_validate_resource(aml_buffer, &resource_index);
360
                if (ACPI_FAILURE(status)) {
361
                        return_ACPI_STATUS(status);
362
                }
363
 
364
                /* Get the resource length and base (minimum) AML size */
365
 
366
                resource_length = acpi_ut_get_resource_length(aml_buffer);
367
                minimum_aml_resource_length =
368
                    acpi_gbl_resource_aml_sizes[resource_index];
369
 
370
                /*
371
                 * Augment the size for descriptors with optional
372
                 * and/or variable length fields
373
                 */
374
                extra_struct_bytes = 0;
375
                buffer =
376
                    aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
377
 
378
                switch (acpi_ut_get_resource_type(aml_buffer)) {
379
                case ACPI_RESOURCE_NAME_IRQ:
380
                        /*
381
                         * IRQ Resource:
382
                         * Get the number of bits set in the 16-bit IRQ mask
383
                         */
384
                        ACPI_MOVE_16_TO_16(&temp16, buffer);
385
                        extra_struct_bytes = acpi_rs_count_set_bits(temp16);
386
                        break;
387
 
388
                case ACPI_RESOURCE_NAME_DMA:
389
                        /*
390
                         * DMA Resource:
391
                         * Get the number of bits set in the 8-bit DMA mask
392
                         */
393
                        extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
394
                        break;
395
 
396
                case ACPI_RESOURCE_NAME_VENDOR_SMALL:
397
                case ACPI_RESOURCE_NAME_VENDOR_LARGE:
398
                        /*
399
                         * Vendor Resource:
400
                         * Get the number of vendor data bytes
401
                         */
402
                        extra_struct_bytes = resource_length;
403
                        break;
404
 
405
                case ACPI_RESOURCE_NAME_END_TAG:
406
                        /*
407
                         * End Tag:
408
                         * This is the normal exit, add size of end_tag
409
                         */
410
                        *size_needed += ACPI_RS_SIZE_MIN;
411
                        return_ACPI_STATUS(AE_OK);
412
 
413
                case ACPI_RESOURCE_NAME_ADDRESS32:
414
                case ACPI_RESOURCE_NAME_ADDRESS16:
415
                case ACPI_RESOURCE_NAME_ADDRESS64:
416
                        /*
417
                         * Address Resource:
418
                         * Add the size of the optional resource_source
419
                         */
420
                        extra_struct_bytes =
421
                            acpi_rs_stream_option_length(resource_length,
422
                                                         minimum_aml_resource_length);
423
                        break;
424
 
425
                case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
426
                        /*
427
                         * Extended IRQ Resource:
428
                         * Using the interrupt_table_length, add 4 bytes for each additional
429
                         * interrupt. Note: at least one interrupt is required and is
430
                         * included in the minimum descriptor size (reason for the -1)
431
                         */
432
                        extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
433
 
434
                        /* Add the size of the optional resource_source */
435
 
436
                        extra_struct_bytes +=
437
                            acpi_rs_stream_option_length(resource_length -
438
                                                         extra_struct_bytes,
439
                                                         minimum_aml_resource_length);
440
                        break;
441
 
442
                default:
443
                        break;
444
                }
445
 
446
                /*
447
                 * Update the required buffer size for the internal descriptor structs
448
                 *
449
                 * Important: Round the size up for the appropriate alignment. This
450
                 * is a requirement on IA64.
451
                 */
452
                buffer_size = acpi_gbl_resource_struct_sizes[resource_index] +
453
                    extra_struct_bytes;
454
                buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
455
 
456
                *size_needed += buffer_size;
457
 
458
                ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
459
                                  "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
460
                                  acpi_ut_get_resource_type(aml_buffer),
461
                                  acpi_ut_get_descriptor_length(aml_buffer),
462
                                  buffer_size));
463
 
464
                /*
465
                 * Point to the next resource within the AML stream using the length
466
                 * contained in the resource descriptor header
467
                 */
468
                aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
469
        }
470
 
471
        /* Did not find an end_tag resource descriptor */
472
 
473
        return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
474
}
475
 
476
/*******************************************************************************
477
 *
478
 * FUNCTION:    acpi_rs_get_pci_routing_table_length
479
 *
480
 * PARAMETERS:  package_object          - Pointer to the package object
481
 *              buffer_size_needed      - u32 pointer of the size buffer
482
 *                                        needed to properly return the
483
 *                                        parsed data
484
 *
485
 * RETURN:      Status
486
 *
487
 * DESCRIPTION: Given a package representing a PCI routing table, this
488
 *              calculates the size of the corresponding linked list of
489
 *              descriptions.
490
 *
491
 ******************************************************************************/
492
 
493
acpi_status
494
acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
495
                                     acpi_size * buffer_size_needed)
496
{
497
        u32 number_of_elements;
498
        acpi_size temp_size_needed = 0;
499
        union acpi_operand_object **top_object_list;
500
        u32 index;
501
        union acpi_operand_object *package_element;
502
        union acpi_operand_object **sub_object_list;
503
        u8 name_found;
504
        u32 table_index;
505
 
506
        ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
507
 
508
        number_of_elements = package_object->package.count;
509
 
510
        /*
511
         * Calculate the size of the return buffer.
512
         * The base size is the number of elements * the sizes of the
513
         * structures.  Additional space for the strings is added below.
514
         * The minus one is to subtract the size of the u8 Source[1]
515
         * member because it is added below.
516
         *
517
         * But each PRT_ENTRY structure has a pointer to a string and
518
         * the size of that string must be found.
519
         */
520
        top_object_list = package_object->package.elements;
521
 
522
        for (index = 0; index < number_of_elements; index++) {
523
 
524
                /* Dereference the sub-package */
525
 
526
                package_element = *top_object_list;
527
 
528
                /*
529
                 * The sub_object_list will now point to an array of the
530
                 * four IRQ elements: Address, Pin, Source and source_index
531
                 */
532
                sub_object_list = package_element->package.elements;
533
 
534
                /* Scan the irq_table_elements for the Source Name String */
535
 
536
                name_found = FALSE;
537
 
538
                for (table_index = 0; table_index < 4 && !name_found;
539
                     table_index++) {
540
                        if (*sub_object_list && /* Null object allowed */
541
                            ((ACPI_TYPE_STRING ==
542
                              ACPI_GET_OBJECT_TYPE(*sub_object_list)) ||
543
                             ((ACPI_TYPE_LOCAL_REFERENCE ==
544
                               ACPI_GET_OBJECT_TYPE(*sub_object_list)) &&
545
                              ((*sub_object_list)->reference.opcode ==
546
                               AML_INT_NAMEPATH_OP)))) {
547
                                name_found = TRUE;
548
                        } else {
549
                                /* Look at the next element */
550
 
551
                                sub_object_list++;
552
                        }
553
                }
554
 
555
                temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
556
 
557
                /* Was a String type found? */
558
 
559
                if (name_found) {
560
                        if (ACPI_GET_OBJECT_TYPE(*sub_object_list) ==
561
                            ACPI_TYPE_STRING) {
562
                                /*
563
                                 * The length String.Length field does not include the
564
                                 * terminating NULL, add 1
565
                                 */
566
                                temp_size_needed += ((acpi_size)
567
                                                     (*sub_object_list)->string.
568
                                                     length + 1);
569
                        } else {
570
                                temp_size_needed +=
571
                                    acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
572
                        }
573
                } else {
574
                        /*
575
                         * If no name was found, then this is a NULL, which is
576
                         * translated as a u32 zero.
577
                         */
578
                        temp_size_needed += sizeof(u32);
579
                }
580
 
581
                /* Round up the size since each element must be aligned */
582
 
583
                temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
584
 
585
                /* Point to the next union acpi_operand_object */
586
 
587
                top_object_list++;
588
        }
589
 
590
        /*
591
         * Add an extra element to the end of the list, essentially a
592
         * NULL terminator
593
         */
594
        *buffer_size_needed =
595
            temp_size_needed + sizeof(struct acpi_pci_routing_table);
596
        return_ACPI_STATUS(AE_OK);
597
}

powered by: WebSVN 2.1.0

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