Merge /spare/repo/linux-2.6/
[pandora-kernel.git] / drivers / acpi / resources / rscalc.c
1 /*******************************************************************************
2  *
3  * Module Name: rscalc - Calculate stream and list lengths
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, 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/acresrc.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acnamesp.h>
49
50 #define _COMPONENT          ACPI_RESOURCES
51          ACPI_MODULE_NAME    ("rscalc")
52
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_rs_get_byte_stream_length
57  *
58  * PARAMETERS:  linked_list         - Pointer to the resource linked list
59  *              size_needed         - u32 pointer of the size buffer needed
60  *                                    to properly return the parsed data
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
65  *              the size buffer needed to hold the linked list that conveys
66  *              the resource data.
67  *
68  ******************************************************************************/
69
70 acpi_status
71 acpi_rs_get_byte_stream_length (
72         struct acpi_resource            *linked_list,
73         acpi_size                       *size_needed)
74 {
75         acpi_size                       byte_stream_size_needed = 0;
76         acpi_size                       segment_size;
77         u8                              done = FALSE;
78
79
80         ACPI_FUNCTION_TRACE ("rs_get_byte_stream_length");
81
82
83         while (!done) {
84                 /* Init the variable that will hold the size to add to the total. */
85
86                 segment_size = 0;
87
88                 switch (linked_list->id) {
89                 case ACPI_RSTYPE_IRQ:
90                         /*
91                          * IRQ Resource
92                          * For an IRQ Resource, Byte 3, although optional, will always be
93                          * created - it holds IRQ information.
94                          */
95                         segment_size = 4;
96                         break;
97
98                 case ACPI_RSTYPE_DMA:
99                         /*
100                          * DMA Resource
101                          * For this resource the size is static
102                          */
103                         segment_size = 3;
104                         break;
105
106                 case ACPI_RSTYPE_START_DPF:
107                         /*
108                          * Start Dependent Functions Resource
109                          * For a start_dependent_functions Resource, Byte 1, although
110                          * optional, will always be created.
111                          */
112                         segment_size = 2;
113                         break;
114
115                 case ACPI_RSTYPE_END_DPF:
116                         /*
117                          * End Dependent Functions Resource
118                          * For this resource the size is static
119                          */
120                         segment_size = 1;
121                         break;
122
123                 case ACPI_RSTYPE_IO:
124                         /*
125                          * IO Port Resource
126                          * For this resource the size is static
127                          */
128                         segment_size = 8;
129                         break;
130
131                 case ACPI_RSTYPE_FIXED_IO:
132                         /*
133                          * Fixed IO Port Resource
134                          * For this resource the size is static
135                          */
136                         segment_size = 4;
137                         break;
138
139                 case ACPI_RSTYPE_VENDOR:
140                         /*
141                          * Vendor Defined Resource
142                          * For a Vendor Specific resource, if the Length is between 1 and 7
143                          * it will be created as a Small Resource data type, otherwise it
144                          * is a Large Resource data type.
145                          */
146                         if (linked_list->data.vendor_specific.length > 7) {
147                                 segment_size = 3;
148                         }
149                         else {
150                                 segment_size = 1;
151                         }
152                         segment_size += linked_list->data.vendor_specific.length;
153                         break;
154
155                 case ACPI_RSTYPE_END_TAG:
156                         /*
157                          * End Tag
158                          * For this resource the size is static
159                          */
160                         segment_size = 2;
161                         done = TRUE;
162                         break;
163
164                 case ACPI_RSTYPE_MEM24:
165                         /*
166                          * 24-Bit Memory Resource
167                          * For this resource the size is static
168                          */
169                         segment_size = 12;
170                         break;
171
172                 case ACPI_RSTYPE_MEM32:
173                         /*
174                          * 32-Bit Memory Range Resource
175                          * For this resource the size is static
176                          */
177                         segment_size = 20;
178                         break;
179
180                 case ACPI_RSTYPE_FIXED_MEM32:
181                         /*
182                          * 32-Bit Fixed Memory Resource
183                          * For this resource the size is static
184                          */
185                         segment_size = 12;
186                         break;
187
188                 case ACPI_RSTYPE_ADDRESS16:
189                         /*
190                          * 16-Bit Address Resource
191                          * The base size of this byte stream is 16. If a Resource Source
192                          * string is not NULL, add 1 for the Index + the length of the null
193                          * terminated string Resource Source + 1 for the null.
194                          */
195                         segment_size = 16;
196
197                         if (linked_list->data.address16.resource_source.string_ptr) {
198                                 segment_size +=
199                                         linked_list->data.address16.resource_source.string_length;
200                                 segment_size++;
201                         }
202                         break;
203
204                 case ACPI_RSTYPE_ADDRESS32:
205                         /*
206                          * 32-Bit Address Resource
207                          * The base size of this byte stream is 26. If a Resource
208                          * Source string is not NULL, add 1 for the Index + the
209                          * length of the null terminated string Resource Source +
210                          * 1 for the null.
211                          */
212                         segment_size = 26;
213
214                         if (linked_list->data.address32.resource_source.string_ptr) {
215                                 segment_size +=
216                                         linked_list->data.address32.resource_source.string_length;
217                                 segment_size++;
218                         }
219                         break;
220
221                 case ACPI_RSTYPE_ADDRESS64:
222                         /*
223                          * 64-Bit Address Resource
224                          * The base size of this byte stream is 46. If a resource_source
225                          * string is not NULL, add 1 for the Index + the length of the null
226                          * terminated string Resource Source + 1 for the null.
227                          */
228                         segment_size = 46;
229
230                         if (linked_list->data.address64.resource_source.string_ptr) {
231                                 segment_size +=
232                                         linked_list->data.address64.resource_source.string_length;
233                                 segment_size++;
234                         }
235                         break;
236
237                 case ACPI_RSTYPE_EXT_IRQ:
238                         /*
239                          * Extended IRQ Resource
240                          * The base size of this byte stream is 9. This is for an Interrupt
241                          * table length of 1.  For each additional interrupt, add 4.
242                          * If a Resource Source string is not NULL, add 1 for the
243                          * Index + the length of the null terminated string
244                          * Resource Source + 1 for the null.
245                          */
246                         segment_size = 9 + (((acpi_size)
247                                 linked_list->data.extended_irq.number_of_interrupts - 1) * 4);
248
249                         if (linked_list->data.extended_irq.resource_source.string_ptr) {
250                                 segment_size +=
251                                         linked_list->data.extended_irq.resource_source.string_length;
252                                 segment_size++;
253                         }
254                         break;
255
256                 default:
257
258                         /* If we get here, everything is out of sync, exit with error */
259
260                         return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
261
262                 } /* switch (linked_list->Id) */
263
264                 /* Update the total */
265
266                 byte_stream_size_needed += segment_size;
267
268                 /* Point to the next object */
269
270                 linked_list = ACPI_PTR_ADD (struct acpi_resource,
271                                   linked_list, linked_list->length);
272         }
273
274         /* This is the data the caller needs */
275
276         *size_needed = byte_stream_size_needed;
277         return_ACPI_STATUS (AE_OK);
278 }
279
280
281 /*******************************************************************************
282  *
283  * FUNCTION:    acpi_rs_get_list_length
284  *
285  * PARAMETERS:  byte_stream_buffer      - Pointer to the resource byte stream
286  *              byte_stream_buffer_length - Size of byte_stream_buffer
287  *              size_needed             - u32 pointer of the size buffer
288  *                                        needed to properly return the
289  *                                        parsed data
290  *
291  * RETURN:      Status
292  *
293  * DESCRIPTION: Takes the resource byte stream and parses it once, calculating
294  *              the size buffer needed to hold the linked list that conveys
295  *              the resource data.
296  *
297  ******************************************************************************/
298
299 acpi_status
300 acpi_rs_get_list_length (
301         u8                              *byte_stream_buffer,
302         u32                             byte_stream_buffer_length,
303         acpi_size                       *size_needed)
304 {
305         u32                             buffer_size = 0;
306         u32                             bytes_parsed = 0;
307         u8                              number_of_interrupts = 0;
308         u8                              number_of_channels = 0;
309         u8                              resource_type;
310         u32                             structure_size;
311         u32                             bytes_consumed;
312         u8                              *buffer;
313         u8                              temp8;
314         u16                             temp16;
315         u8                              index;
316         u8                              additional_bytes;
317
318
319         ACPI_FUNCTION_TRACE ("rs_get_list_length");
320
321
322         while (bytes_parsed < byte_stream_buffer_length) {
323                 /* The next byte in the stream is the resource type */
324
325                 resource_type = acpi_rs_get_resource_type (*byte_stream_buffer);
326
327                 switch (resource_type) {
328                 case ACPI_RDESC_TYPE_MEMORY_24:
329                         /*
330                          * 24-Bit Memory Resource
331                          */
332                         bytes_consumed = 12;
333
334                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem24);
335                         break;
336
337
338                 case ACPI_RDESC_TYPE_LARGE_VENDOR:
339                         /*
340                          * Vendor Defined Resource
341                          */
342                         buffer = byte_stream_buffer;
343                         ++buffer;
344
345                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
346                         bytes_consumed = temp16 + 3;
347
348                         /* Ensure a 32-bit boundary for the structure */
349
350                         temp16 = (u16) ACPI_ROUND_UP_to_32_bITS (temp16);
351
352                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
353                                            (temp16 * sizeof (u8));
354                         break;
355
356
357                 case ACPI_RDESC_TYPE_MEMORY_32:
358                         /*
359                          * 32-Bit Memory Range Resource
360                          */
361                         bytes_consumed = 20;
362
363                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32);
364                         break;
365
366
367                 case ACPI_RDESC_TYPE_FIXED_MEMORY_32:
368                         /*
369                          * 32-Bit Fixed Memory Resource
370                          */
371                         bytes_consumed = 12;
372
373                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_mem32);
374                         break;
375
376
377                 case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
378                         /*
379                          * 64-Bit Address Resource
380                          */
381                         buffer = byte_stream_buffer;
382
383                         ++buffer;
384                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
385
386                         bytes_consumed = temp16 + 3;
387                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
388                         break;
389
390
391                 case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
392                         /*
393                          * 64-Bit Address Resource
394                          */
395                         buffer = byte_stream_buffer;
396
397                         ++buffer;
398                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
399
400                         bytes_consumed = temp16 + 3;
401
402                         /*
403                          * Resource Source Index and Resource Source are optional elements.
404                          * Check the length of the Bytestream.  If it is greater than 43,
405                          * that means that an Index exists and is followed by a null
406                          * terminated string.  Therefore, set the temp variable to the
407                          * length minus the minimum byte stream length plus the byte for
408                          * the Index to determine the size of the NULL terminated string.
409                          */
410                         if (43 < temp16) {
411                                 temp8 = (u8) (temp16 - 44);
412                         }
413                         else {
414                                 temp8 = 0;
415                         }
416
417                         /* Ensure a 64-bit boundary for the structure */
418
419                         temp8 = (u8) ACPI_ROUND_UP_to_64_bITS (temp8);
420
421                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64) +
422                                            (temp8 * sizeof (u8));
423                         break;
424
425
426                 case ACPI_RDESC_TYPE_DWORD_ADDRESS_SPACE:
427                         /*
428                          * 32-Bit Address Resource
429                          */
430                         buffer = byte_stream_buffer;
431
432                         ++buffer;
433                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
434
435                         bytes_consumed = temp16 + 3;
436
437                         /*
438                          * Resource Source Index and Resource Source are optional elements.
439                          * Check the length of the Bytestream.  If it is greater than 23,
440                          * that means that an Index exists and is followed by a null
441                          * terminated string.  Therefore, set the temp variable to the
442                          * length minus the minimum byte stream length plus the byte for
443                          * the Index to determine the size of the NULL terminated string.
444                          */
445                         if (23 < temp16) {
446                                 temp8 = (u8) (temp16 - 24);
447                         }
448                         else {
449                                 temp8 = 0;
450                         }
451
452                         /* Ensure a 32-bit boundary for the structure */
453
454                         temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
455
456                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address32) +
457                                            (temp8 * sizeof (u8));
458                         break;
459
460
461                 case ACPI_RDESC_TYPE_WORD_ADDRESS_SPACE:
462                         /*
463                          * 16-Bit Address Resource
464                          */
465                         buffer = byte_stream_buffer;
466
467                         ++buffer;
468                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
469
470                         bytes_consumed = temp16 + 3;
471
472                         /*
473                          * Resource Source Index and Resource Source are optional elements.
474                          * Check the length of the Bytestream.  If it is greater than 13,
475                          * that means that an Index exists and is followed by a null
476                          * terminated string.  Therefore, set the temp variable to the
477                          * length minus the minimum byte stream length plus the byte for
478                          * the Index to determine the size of the NULL terminated string.
479                          */
480                         if (13 < temp16) {
481                                 temp8 = (u8) (temp16 - 14);
482                         }
483                         else {
484                                 temp8 = 0;
485                         }
486
487                         /* Ensure a 32-bit boundary for the structure */
488
489                         temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
490
491                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address16) +
492                                            (temp8 * sizeof (u8));
493                         break;
494
495
496                 case ACPI_RDESC_TYPE_EXTENDED_XRUPT:
497                         /*
498                          * Extended IRQ
499                          */
500                         buffer = byte_stream_buffer;
501
502                         ++buffer;
503                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
504
505                         bytes_consumed = temp16 + 3;
506
507                         /*
508                          * Point past the length field and the Interrupt vector flags to
509                          * save off the Interrupt table length to the Temp8 variable.
510                          */
511                         buffer += 3;
512                         temp8 = *buffer;
513
514                         /*
515                          * To compensate for multiple interrupt numbers, add 4 bytes for
516                          * each additional interrupts greater than 1
517                          */
518                         additional_bytes = (u8) ((temp8 - 1) * 4);
519
520                         /*
521                          * Resource Source Index and Resource Source are optional elements.
522                          * Check the length of the Bytestream.  If it is greater than 9,
523                          * that means that an Index exists and is followed by a null
524                          * terminated string.  Therefore, set the temp variable to the
525                          * length minus the minimum byte stream length plus the byte for
526                          * the Index to determine the size of the NULL terminated string.
527                          */
528                         if (9 + additional_bytes < temp16) {
529                                 temp8 = (u8) (temp16 - (9 + additional_bytes));
530                         }
531                         else {
532                                 temp8 = 0;
533                         }
534
535                         /* Ensure a 32-bit boundary for the structure */
536
537                         temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
538
539                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_ext_irq) +
540                                            (additional_bytes * sizeof (u8)) +
541                                            (temp8 * sizeof (u8));
542                         break;
543
544
545                 case ACPI_RDESC_TYPE_IRQ_FORMAT:
546                         /*
547                          * IRQ Resource.
548                          * Determine if it there are two or three trailing bytes
549                          */
550                         buffer = byte_stream_buffer;
551                         temp8 = *buffer;
552
553                         if(temp8 & 0x01) {
554                                 bytes_consumed = 4;
555                         }
556                         else {
557                                 bytes_consumed = 3;
558                         }
559
560                         /* Point past the descriptor */
561
562                         ++buffer;
563
564                         /* Look at the number of bits set */
565
566                         ACPI_MOVE_16_TO_16 (&temp16, buffer);
567
568                         for (index = 0; index < 16; index++) {
569                                 if (temp16 & 0x1) {
570                                         ++number_of_interrupts;
571                                 }
572
573                                 temp16 >>= 1;
574                         }
575
576                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io) +
577                                            (number_of_interrupts * sizeof (u32));
578                         break;
579
580
581                 case ACPI_RDESC_TYPE_DMA_FORMAT:
582                         /*
583                          * DMA Resource
584                          */
585                         buffer = byte_stream_buffer;
586                         bytes_consumed = 3;
587
588                         /* Point past the descriptor */
589
590                         ++buffer;
591
592                         /* Look at the number of bits set */
593
594                         temp8 = *buffer;
595
596                         for(index = 0; index < 8; index++) {
597                                 if(temp8 & 0x1) {
598                                         ++number_of_channels;
599                                 }
600
601                                 temp8 >>= 1;
602                         }
603
604                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_dma) +
605                                            (number_of_channels * sizeof (u32));
606                         break;
607
608
609                 case ACPI_RDESC_TYPE_START_DEPENDENT:
610                         /*
611                          * Start Dependent Functions Resource
612                          * Determine if it there are two or three trailing bytes
613                          */
614                         buffer = byte_stream_buffer;
615                         temp8 = *buffer;
616
617                         if(temp8 & 0x01) {
618                                 bytes_consumed = 2;
619                         }
620                         else {
621                                 bytes_consumed = 1;
622                         }
623
624                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_start_dpf);
625                         break;
626
627
628                 case ACPI_RDESC_TYPE_END_DEPENDENT:
629                         /*
630                          * End Dependent Functions Resource
631                          */
632                         bytes_consumed = 1;
633                         structure_size = ACPI_RESOURCE_LENGTH;
634                         break;
635
636
637                 case ACPI_RDESC_TYPE_IO_PORT:
638                         /*
639                          * IO Port Resource
640                          */
641                         bytes_consumed = 8;
642                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_io);
643                         break;
644
645
646                 case ACPI_RDESC_TYPE_FIXED_IO_PORT:
647                         /*
648                          * Fixed IO Port Resource
649                          */
650                         bytes_consumed = 4;
651                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_fixed_io);
652                         break;
653
654
655                 case ACPI_RDESC_TYPE_SMALL_VENDOR:
656                         /*
657                          * Vendor Specific Resource
658                          */
659                         buffer = byte_stream_buffer;
660
661                         temp8 = *buffer;
662                         temp8 = (u8) (temp8 & 0x7);
663                         bytes_consumed = temp8 + 1;
664
665                         /* Ensure a 32-bit boundary for the structure */
666
667                         temp8 = (u8) ACPI_ROUND_UP_to_32_bITS (temp8);
668                         structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_vendor) +
669                                            (temp8 * sizeof (u8));
670                         break;
671
672
673                 case ACPI_RDESC_TYPE_END_TAG:
674                         /*
675                          * End Tag
676                          */
677                         bytes_consumed = 2;
678                         structure_size = ACPI_RESOURCE_LENGTH;
679                         byte_stream_buffer_length = bytes_parsed;
680                         break;
681
682
683                 default:
684                         /*
685                          * If we get here, everything is out of sync,
686                          * exit with an error
687                          */
688                         return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
689                 }
690
691                 /* Update the return value and counter */
692
693                 buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE (structure_size);
694                 bytes_parsed += bytes_consumed;
695
696                 /* Set the byte stream to point to the next resource */
697
698                 byte_stream_buffer += bytes_consumed;
699         }
700
701         /* This is the data the caller needs */
702
703         *size_needed = buffer_size;
704         return_ACPI_STATUS (AE_OK);
705 }
706
707
708 /*******************************************************************************
709  *
710  * FUNCTION:    acpi_rs_get_pci_routing_table_length
711  *
712  * PARAMETERS:  package_object          - Pointer to the package object
713  *              buffer_size_needed      - u32 pointer of the size buffer
714  *                                        needed to properly return the
715  *                                        parsed data
716  *
717  * RETURN:      Status
718  *
719  * DESCRIPTION: Given a package representing a PCI routing table, this
720  *              calculates the size of the corresponding linked list of
721  *              descriptions.
722  *
723  ******************************************************************************/
724
725 acpi_status
726 acpi_rs_get_pci_routing_table_length (
727         union acpi_operand_object       *package_object,
728         acpi_size                       *buffer_size_needed)
729 {
730         u32                             number_of_elements;
731         acpi_size                       temp_size_needed = 0;
732         union acpi_operand_object       **top_object_list;
733         u32                             index;
734         union acpi_operand_object       *package_element;
735         union acpi_operand_object       **sub_object_list;
736         u8                              name_found;
737         u32                             table_index;
738
739
740         ACPI_FUNCTION_TRACE ("rs_get_pci_routing_table_length");
741
742
743         number_of_elements = package_object->package.count;
744
745         /*
746          * Calculate the size of the return buffer.
747          * The base size is the number of elements * the sizes of the
748          * structures.  Additional space for the strings is added below.
749          * The minus one is to subtract the size of the u8 Source[1]
750          * member because it is added below.
751          *
752          * But each PRT_ENTRY structure has a pointer to a string and
753          * the size of that string must be found.
754          */
755         top_object_list = package_object->package.elements;
756
757         for (index = 0; index < number_of_elements; index++) {
758                 /* Dereference the sub-package */
759
760                 package_element = *top_object_list;
761
762                 /*
763                  * The sub_object_list will now point to an array of the
764                  * four IRQ elements: Address, Pin, Source and source_index
765                  */
766                 sub_object_list = package_element->package.elements;
767
768                 /* Scan the irq_table_elements for the Source Name String */
769
770                 name_found = FALSE;
771
772                 for (table_index = 0; table_index < 4 && !name_found; table_index++) {
773                         if ((ACPI_TYPE_STRING ==
774                                         ACPI_GET_OBJECT_TYPE (*sub_object_list)) ||
775
776                                 ((ACPI_TYPE_LOCAL_REFERENCE ==
777                                         ACPI_GET_OBJECT_TYPE (*sub_object_list)) &&
778
779                                         ((*sub_object_list)->reference.opcode ==
780                                                 AML_INT_NAMEPATH_OP))) {
781                                 name_found = TRUE;
782                         }
783                         else {
784                                 /* Look at the next element */
785
786                                 sub_object_list++;
787                         }
788                 }
789
790                 temp_size_needed += (sizeof (struct acpi_pci_routing_table) - 4);
791
792                 /* Was a String type found? */
793
794                 if (name_found) {
795                         if (ACPI_GET_OBJECT_TYPE (*sub_object_list) == ACPI_TYPE_STRING) {
796                                 /*
797                                  * The length String.Length field does not include the
798                                  * terminating NULL, add 1
799                                  */
800                                 temp_size_needed += ((acpi_size)
801                                         (*sub_object_list)->string.length + 1);
802                         }
803                         else {
804                                 temp_size_needed += acpi_ns_get_pathname_length (
805                                                    (*sub_object_list)->reference.node);
806                         }
807                 }
808                 else {
809                         /*
810                          * If no name was found, then this is a NULL, which is
811                          * translated as a u32 zero.
812                          */
813                         temp_size_needed += sizeof (u32);
814                 }
815
816                 /* Round up the size since each element must be aligned */
817
818                 temp_size_needed = ACPI_ROUND_UP_to_64_bITS (temp_size_needed);
819
820                 /* Point to the next union acpi_operand_object */
821
822                 top_object_list++;
823         }
824
825         /*
826          * Adding an extra element to the end of the list, essentially a
827          * NULL terminator
828          */
829         *buffer_size_needed = temp_size_needed + sizeof (struct acpi_pci_routing_table);
830         return_ACPI_STATUS (AE_OK);
831 }