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