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