rscalc.c revision 193267
167754Smsmith/*******************************************************************************
267754Smsmith *
377424Smsmith * Module Name: rscalc - Calculate stream and list lengths
467754Smsmith *
567754Smsmith ******************************************************************************/
667754Smsmith
767754Smsmith/******************************************************************************
867754Smsmith *
967754Smsmith * 1. Copyright Notice
1067754Smsmith *
11193267Sjkim * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
1270243Smsmith * All rights reserved.
1367754Smsmith *
1467754Smsmith * 2. License
1567754Smsmith *
1667754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property
1767754Smsmith * rights.  You may have additional license terms from the party that provided
1867754Smsmith * you this software, covering your right to use that party's intellectual
1967754Smsmith * property rights.
2067754Smsmith *
2167754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2267754Smsmith * copy of the source code appearing in this file ("Covered Code") an
2367754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2467754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
2567754Smsmith * make derivatives, distribute, use and display any portion of the Covered
2667754Smsmith * Code in any form, with the right to sublicense such rights; and
2767754Smsmith *
2867754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
2967754Smsmith * license (with the right to sublicense), under only those claims of Intel
3067754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell,
3167754Smsmith * offer to sell, and import the Covered Code and derivative works thereof
3267754Smsmith * solely to the minimum extent necessary to exercise the above copyright
3367754Smsmith * license, and in no event shall the patent license extend to any additions
3467754Smsmith * to or modifications of the Original Intel Code.  No other license or right
3567754Smsmith * is granted directly or by implication, estoppel or otherwise;
3667754Smsmith *
3767754Smsmith * The above copyright and patent license is granted only if the following
3867754Smsmith * conditions are met:
3967754Smsmith *
4067754Smsmith * 3. Conditions
4167754Smsmith *
4267754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4367754Smsmith * Redistribution of source code of any substantial portion of the Covered
4467754Smsmith * Code or modification with rights to further distribute source must include
4567754Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4667754Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
4767754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
4867754Smsmith * contain a file documenting the changes Licensee made to create that Covered
4967754Smsmith * Code and the date of any change.  Licensee must include in that file the
5067754Smsmith * documentation of any changes made by any predecessor Licensee.  Licensee
5167754Smsmith * must include a prominent statement that the modification is derived,
5267754Smsmith * directly or indirectly, from Original Intel Code.
5367754Smsmith *
5467754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5567754Smsmith * Redistribution of source code of any substantial portion of the Covered
5667754Smsmith * Code or modification without rights to further distribute source must
5767754Smsmith * include the following Disclaimer and Export Compliance provision in the
5867754Smsmith * documentation and/or other materials provided with distribution.  In
5967754Smsmith * addition, Licensee may not authorize further sublicense of source of any
6067754Smsmith * portion of the Covered Code, and must include terms to the effect that the
6167754Smsmith * license from Licensee to its licensee is limited to the intellectual
6267754Smsmith * property embodied in the software Licensee provides to its licensee, and
6367754Smsmith * not to intellectual property embodied in modifications its licensee may
6467754Smsmith * make.
6567754Smsmith *
6667754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any
6767754Smsmith * substantial portion of the Covered Code or modification must reproduce the
6867754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance
6967754Smsmith * provision in the documentation and/or other materials provided with the
7067754Smsmith * distribution.
7167754Smsmith *
7267754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original
7367754Smsmith * Intel Code.
7467754Smsmith *
7567754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7667754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or
7767754Smsmith * other dealings in products derived from or relating to the Covered Code
7867754Smsmith * without prior written authorization from Intel.
7967754Smsmith *
8067754Smsmith * 4. Disclaimer and Export Compliance
8167754Smsmith *
8267754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8367754Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8467754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8567754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8667754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8767754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8867754Smsmith * PARTICULAR PURPOSE.
8967754Smsmith *
9067754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9167754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9267754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9367754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9467754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9567754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9667754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9767754Smsmith * LIMITED REMEDY.
9867754Smsmith *
9967754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this
10067754Smsmith * software or system incorporating such software without first obtaining any
10167754Smsmith * required license or other approval from the U. S. Department of Commerce or
10267754Smsmith * any other agency or department of the United States Government.  In the
10367754Smsmith * event Licensee exports any such software from the United States or
10467754Smsmith * re-exports any such software from a foreign destination, Licensee shall
10567754Smsmith * ensure that the distribution and export/re-export of the software is in
10667754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the
10767754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10867754Smsmith * any of its subsidiaries will export/re-export any technical data, process,
10967754Smsmith * software, or service, directly or indirectly, to any country for which the
11067754Smsmith * United States government or any agency thereof requires an export license,
11167754Smsmith * other governmental approval, or letter of assurance, without first obtaining
11267754Smsmith * such license, approval or letter.
11367754Smsmith *
11467754Smsmith *****************************************************************************/
11567754Smsmith
11667754Smsmith#define __RSCALC_C__
11767754Smsmith
118193251Sjkim#include "acpi.h"
119193267Sjkim#include "accommon.h"
120193251Sjkim#include "acresrc.h"
121193251Sjkim#include "acnamesp.h"
12267754Smsmith
123193267Sjkim
12477424Smsmith#define _COMPONENT          ACPI_RESOURCES
12591116Smsmith        ACPI_MODULE_NAME    ("rscalc")
12667754Smsmith
12767754Smsmith
128151937Sjkim/* Local prototypes */
129151937Sjkim
130151937Sjkimstatic UINT8
131151937SjkimAcpiRsCountSetBits (
132151937Sjkim    UINT16                  BitField);
133151937Sjkim
134151937Sjkimstatic ACPI_RS_LENGTH
135151937SjkimAcpiRsStructOptionLength (
136151937Sjkim    ACPI_RESOURCE_SOURCE    *ResourceSource);
137151937Sjkim
138151937Sjkimstatic UINT32
139151937SjkimAcpiRsStreamOptionLength (
140151937Sjkim    UINT32                  ResourceLength,
141151937Sjkim    UINT32                  MinimumTotalLength);
142151937Sjkim
143151937Sjkim
14467754Smsmith/*******************************************************************************
14567754Smsmith *
146151937Sjkim * FUNCTION:    AcpiRsCountSetBits
14767754Smsmith *
148151937Sjkim * PARAMETERS:  BitField        - Field in which to count bits
14967754Smsmith *
150151937Sjkim * RETURN:      Number of bits set within the field
15167754Smsmith *
152151937Sjkim * DESCRIPTION: Count the number of bits set in a resource field. Used for
153151937Sjkim *              (Short descriptor) interrupt and DMA lists.
15467754Smsmith *
15567754Smsmith ******************************************************************************/
15667754Smsmith
157151937Sjkimstatic UINT8
158151937SjkimAcpiRsCountSetBits (
159151937Sjkim    UINT16                  BitField)
16067754Smsmith{
161151937Sjkim    UINT8                   BitsSet;
16267754Smsmith
16367754Smsmith
164151937Sjkim    ACPI_FUNCTION_ENTRY ();
16567754Smsmith
16667754Smsmith
167151937Sjkim    for (BitsSet = 0; BitField; BitsSet++)
16867754Smsmith    {
169151937Sjkim        /* Zero the least significant bit that is set */
17067754Smsmith
171193267Sjkim        BitField &= (UINT16) (BitField - 1);
172151937Sjkim    }
17367754Smsmith
174151937Sjkim    return (BitsSet);
175151937Sjkim}
17667754Smsmith
17767754Smsmith
178151937Sjkim/*******************************************************************************
179151937Sjkim *
180151937Sjkim * FUNCTION:    AcpiRsStructOptionLength
181151937Sjkim *
182151937Sjkim * PARAMETERS:  ResourceSource      - Pointer to optional descriptor field
183151937Sjkim *
184151937Sjkim * RETURN:      Status
185151937Sjkim *
186151937Sjkim * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
187151937Sjkim *              ResourceSource fields in some Large descriptors. Used during
188151937Sjkim *              list-to-stream conversion
189151937Sjkim *
190151937Sjkim ******************************************************************************/
19167754Smsmith
192151937Sjkimstatic ACPI_RS_LENGTH
193151937SjkimAcpiRsStructOptionLength (
194151937Sjkim    ACPI_RESOURCE_SOURCE    *ResourceSource)
195151937Sjkim{
196151937Sjkim    ACPI_FUNCTION_ENTRY ();
19767754Smsmith
19867754Smsmith
199151937Sjkim    /*
200151937Sjkim     * If the ResourceSource string is valid, return the size of the string
201151937Sjkim     * (StringLength includes the NULL terminator) plus the size of the
202151937Sjkim     * ResourceSourceIndex (1).
203151937Sjkim     */
204151937Sjkim    if (ResourceSource->StringPtr)
205151937Sjkim    {
206151937Sjkim        return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
207151937Sjkim    }
20867754Smsmith
209151937Sjkim    return (0);
210151937Sjkim}
21167754Smsmith
21267754Smsmith
213151937Sjkim/*******************************************************************************
214151937Sjkim *
215151937Sjkim * FUNCTION:    AcpiRsStreamOptionLength
216151937Sjkim *
217151937Sjkim * PARAMETERS:  ResourceLength      - Length from the resource header
218151937Sjkim *              MinimumTotalLength  - Minimum length of this resource, before
219151937Sjkim *                                    any optional fields. Includes header size
220151937Sjkim *
221151937Sjkim * RETURN:      Length of optional string (0 if no string present)
222151937Sjkim *
223151937Sjkim * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
224151937Sjkim *              ResourceSource fields in some Large descriptors. Used during
225151937Sjkim *              stream-to-list conversion
226151937Sjkim *
227151937Sjkim ******************************************************************************/
22867754Smsmith
229151937Sjkimstatic UINT32
230151937SjkimAcpiRsStreamOptionLength (
231151937Sjkim    UINT32                  ResourceLength,
232151937Sjkim    UINT32                  MinimumAmlResourceLength)
233151937Sjkim{
234151937Sjkim    UINT32                  StringLength = 0;
23567754Smsmith
23667754Smsmith
237151937Sjkim    ACPI_FUNCTION_ENTRY ();
23867754Smsmith
23967754Smsmith
240151937Sjkim    /*
241151937Sjkim     * The ResourceSourceIndex and ResourceSource are optional elements of some
242151937Sjkim     * Large-type resource descriptors.
243151937Sjkim     */
24467754Smsmith
245151937Sjkim    /*
246151937Sjkim     * If the length of the actual resource descriptor is greater than the ACPI
247151937Sjkim     * spec-defined minimum length, it means that a ResourceSourceIndex exists
248151937Sjkim     * and is followed by a (required) null terminated string. The string length
249151937Sjkim     * (including the null terminator) is the resource length minus the minimum
250151937Sjkim     * length, minus one byte for the ResourceSourceIndex itself.
251151937Sjkim     */
252151937Sjkim    if (ResourceLength > MinimumAmlResourceLength)
253151937Sjkim    {
254151937Sjkim        /* Compute the length of the optional string */
25577424Smsmith
256151937Sjkim        StringLength = ResourceLength - MinimumAmlResourceLength - 1;
257151937Sjkim    }
25877424Smsmith
259167802Sjkim    /*
260167802Sjkim     * Round the length up to a multiple of the native word in order to
261167802Sjkim     * guarantee that the entire resource descriptor is native word aligned
262167802Sjkim     */
263167802Sjkim    return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
26467754Smsmith}
26567754Smsmith
26667754Smsmith
26767754Smsmith/*******************************************************************************
26867754Smsmith *
269151937Sjkim * FUNCTION:    AcpiRsGetAmlLength
27067754Smsmith *
271151937Sjkim * PARAMETERS:  Resource            - Pointer to the resource linked list
272151937Sjkim *              SizeNeeded          - Where the required size is returned
27367754Smsmith *
27477424Smsmith * RETURN:      Status
27567754Smsmith *
276151937Sjkim * DESCRIPTION: Takes a linked list of internal resource descriptors and
277151937Sjkim *              calculates the size buffer needed to hold the corresponding
278151937Sjkim *              external resource byte stream.
27967754Smsmith *
28067754Smsmith ******************************************************************************/
28167754Smsmith
28267754SmsmithACPI_STATUS
283151937SjkimAcpiRsGetAmlLength (
284151937Sjkim    ACPI_RESOURCE           *Resource,
28591116Smsmith    ACPI_SIZE               *SizeNeeded)
28667754Smsmith{
287151937Sjkim    ACPI_SIZE               AmlSizeNeeded = 0;
288167802Sjkim    ACPI_RS_LENGTH          TotalSize;
28967754Smsmith
29067754Smsmith
291167802Sjkim    ACPI_FUNCTION_TRACE (RsGetAmlLength);
29267754Smsmith
29367754Smsmith
294151937Sjkim    /* Traverse entire list of internal resource descriptors */
295151937Sjkim
296151937Sjkim    while (Resource)
29767754Smsmith    {
298151937Sjkim        /* Validate the descriptor type */
29967754Smsmith
300151937Sjkim        if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
30167754Smsmith        {
302151937Sjkim            return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
303151937Sjkim        }
30467754Smsmith
305151937Sjkim        /* Get the base size of the (external stream) resource descriptor */
30667754Smsmith
307151937Sjkim        TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
30867754Smsmith
309151937Sjkim        /*
310151937Sjkim         * Augment the base size for descriptors with optional and/or
311151937Sjkim         * variable-length fields
312151937Sjkim         */
313151937Sjkim        switch (Resource->Type)
314151937Sjkim        {
315193267Sjkim        case ACPI_RESOURCE_TYPE_IRQ:
316193267Sjkim
317193267Sjkim            /* Length can be 3 or 2 */
318193267Sjkim
319193267Sjkim            if (Resource->Data.Irq.DescriptorLength == 2)
320193267Sjkim            {
321193267Sjkim                TotalSize--;
322193267Sjkim            }
323193267Sjkim            break;
324193267Sjkim
325193267Sjkim
326193267Sjkim        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
327193267Sjkim
328193267Sjkim            /* Length can be 1 or 0 */
329193267Sjkim
330193267Sjkim            if (Resource->Data.Irq.DescriptorLength == 0)
331193267Sjkim            {
332193267Sjkim                TotalSize--;
333193267Sjkim            }
334193267Sjkim            break;
335193267Sjkim
336193267Sjkim
337151937Sjkim        case ACPI_RESOURCE_TYPE_VENDOR:
33877424Smsmith            /*
339151937Sjkim             * Vendor Defined Resource:
340151937Sjkim             * For a Vendor Specific resource, if the Length is between 1 and 7
341151937Sjkim             * it will be created as a Small Resource data type, otherwise it
342151937Sjkim             * is a Large Resource data type.
34377424Smsmith             */
344151937Sjkim            if (Resource->Data.Vendor.ByteLength > 7)
345151937Sjkim            {
346151937Sjkim                /* Base size of a Large resource descriptor */
34767754Smsmith
348151937Sjkim                TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
349151937Sjkim            }
35067754Smsmith
351151937Sjkim            /* Add the size of the vendor-specific data */
35277424Smsmith
353151937Sjkim            TotalSize = (ACPI_RS_LENGTH)
354151937Sjkim                (TotalSize + Resource->Data.Vendor.ByteLength);
35577424Smsmith            break;
35667754Smsmith
35767754Smsmith
358151937Sjkim        case ACPI_RESOURCE_TYPE_END_TAG:
35977424Smsmith            /*
360151937Sjkim             * End Tag:
361151937Sjkim             * We are done -- return the accumulated total size.
36277424Smsmith             */
363151937Sjkim            *SizeNeeded = AmlSizeNeeded + TotalSize;
36467754Smsmith
365151937Sjkim            /* Normal exit */
36667754Smsmith
367151937Sjkim            return_ACPI_STATUS (AE_OK);
36867754Smsmith
369151937Sjkim
370151937Sjkim        case ACPI_RESOURCE_TYPE_ADDRESS16:
37177424Smsmith            /*
372151937Sjkim             * 16-Bit Address Resource:
373151937Sjkim             * Add the size of the optional ResourceSource info
37477424Smsmith             */
375151937Sjkim            TotalSize = (ACPI_RS_LENGTH)
376151937Sjkim                (TotalSize + AcpiRsStructOptionLength (
377151937Sjkim                                &Resource->Data.Address16.ResourceSource));
37877424Smsmith            break;
37967754Smsmith
38067754Smsmith
381151937Sjkim        case ACPI_RESOURCE_TYPE_ADDRESS32:
38277424Smsmith            /*
383151937Sjkim             * 32-Bit Address Resource:
384151937Sjkim             * Add the size of the optional ResourceSource info
38577424Smsmith             */
386151937Sjkim            TotalSize = (ACPI_RS_LENGTH)
387151937Sjkim                (TotalSize + AcpiRsStructOptionLength (
388151937Sjkim                                &Resource->Data.Address32.ResourceSource));
389151937Sjkim            break;
39067754Smsmith
39167754Smsmith
392151937Sjkim        case ACPI_RESOURCE_TYPE_ADDRESS64:
39377424Smsmith            /*
394151937Sjkim             * 64-Bit Address Resource:
395151937Sjkim             * Add the size of the optional ResourceSource info
39677424Smsmith             */
397151937Sjkim            TotalSize = (ACPI_RS_LENGTH)
398151937Sjkim                (TotalSize + AcpiRsStructOptionLength (
399151937Sjkim                                &Resource->Data.Address64.ResourceSource));
40077424Smsmith            break;
40167754Smsmith
40267754Smsmith
403151937Sjkim        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
40477424Smsmith            /*
405151937Sjkim             * Extended IRQ Resource:
406151937Sjkim             * Add the size of each additional optional interrupt beyond the
407151937Sjkim             * required 1 (4 bytes for each UINT32 interrupt number)
40877424Smsmith             */
409151937Sjkim            TotalSize = (ACPI_RS_LENGTH)
410151937Sjkim                (TotalSize +
411151937Sjkim                ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
41267754Smsmith
413151937Sjkim                /* Add the size of the optional ResourceSource info */
41467754Smsmith
415151937Sjkim                AcpiRsStructOptionLength (
416151937Sjkim                    &Resource->Data.ExtendedIrq.ResourceSource));
417151937Sjkim            break;
41867754Smsmith
41967754Smsmith
420151937Sjkim        default:
42177424Smsmith            break;
422151937Sjkim        }
42367754Smsmith
424151937Sjkim        /* Update the total */
42567754Smsmith
426151937Sjkim        AmlSizeNeeded += TotalSize;
42767754Smsmith
428151937Sjkim        /* Point to the next object */
42967754Smsmith
430167802Sjkim        Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
431151937Sjkim    }
43267754Smsmith
433167802Sjkim    /* Did not find an EndTag resource descriptor */
43467754Smsmith
435167802Sjkim    return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
436151937Sjkim}
43767754Smsmith
43867754Smsmith
439151937Sjkim/*******************************************************************************
440151937Sjkim *
441151937Sjkim * FUNCTION:    AcpiRsGetListLength
442151937Sjkim *
443151937Sjkim * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
444151937Sjkim *              AmlBufferLength     - Size of AmlBuffer
445151937Sjkim *              SizeNeeded          - Where the size needed is returned
446151937Sjkim *
447151937Sjkim * RETURN:      Status
448151937Sjkim *
449151937Sjkim * DESCRIPTION: Takes an external resource byte stream and calculates the size
450151937Sjkim *              buffer needed to hold the corresponding internal resource
451151937Sjkim *              descriptor linked list.
452151937Sjkim *
453151937Sjkim ******************************************************************************/
45467754Smsmith
455151937SjkimACPI_STATUS
456151937SjkimAcpiRsGetListLength (
457151937Sjkim    UINT8                   *AmlBuffer,
458151937Sjkim    UINT32                  AmlBufferLength,
459151937Sjkim    ACPI_SIZE               *SizeNeeded)
460151937Sjkim{
461167802Sjkim    ACPI_STATUS             Status;
462167802Sjkim    UINT8                   *EndAml;
463151937Sjkim    UINT8                   *Buffer;
464167802Sjkim    UINT32                  BufferSize;
465151937Sjkim    UINT16                  Temp16;
466151937Sjkim    UINT16                  ResourceLength;
467151937Sjkim    UINT32                  ExtraStructBytes;
468167802Sjkim    UINT8                   ResourceIndex;
469167802Sjkim    UINT8                   MinimumAmlResourceLength;
47067754Smsmith
47167754Smsmith
472167802Sjkim    ACPI_FUNCTION_TRACE (RsGetListLength);
47367754Smsmith
47467754Smsmith
475167802Sjkim    *SizeNeeded = 0;
476167802Sjkim    EndAml = AmlBuffer + AmlBufferLength;
47767754Smsmith
478167802Sjkim    /* Walk the list of AML resource descriptors */
47967754Smsmith
480167802Sjkim    while (AmlBuffer < EndAml)
481167802Sjkim    {
482167802Sjkim        /* Validate the Resource Type and Resource Length */
48367754Smsmith
484167802Sjkim        Status = AcpiUtValidateResource (AmlBuffer, &ResourceIndex);
485167802Sjkim        if (ACPI_FAILURE (Status))
486151937Sjkim        {
487167802Sjkim            return_ACPI_STATUS (Status);
488151937Sjkim        }
48967754Smsmith
490167802Sjkim        /* Get the resource length and base (minimum) AML size */
49167754Smsmith
492151937Sjkim        ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
493167802Sjkim        MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
49467754Smsmith
495167802Sjkim        /*
496167802Sjkim         * Augment the size for descriptors with optional
497167802Sjkim         * and/or variable length fields
498167802Sjkim         */
499151937Sjkim        ExtraStructBytes = 0;
500167802Sjkim        Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
501138287Smarks
502167802Sjkim        switch (AcpiUtGetResourceType (AmlBuffer))
503151937Sjkim        {
504167802Sjkim        case ACPI_RESOURCE_NAME_IRQ:
50577424Smsmith            /*
506167802Sjkim             * IRQ Resource:
507167802Sjkim             * Get the number of bits set in the 16-bit IRQ mask
50877424Smsmith             */
509167802Sjkim            ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
510167802Sjkim            ExtraStructBytes = AcpiRsCountSetBits (Temp16);
511167802Sjkim            break;
51267754Smsmith
51367754Smsmith
514167802Sjkim        case ACPI_RESOURCE_NAME_DMA:
515167802Sjkim            /*
516167802Sjkim             * DMA Resource:
517167802Sjkim             * Get the number of bits set in the 8-bit DMA mask
518167802Sjkim             */
519167802Sjkim            ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
520167802Sjkim            break;
52167754Smsmith
52267754Smsmith
523167802Sjkim        case ACPI_RESOURCE_NAME_VENDOR_SMALL:
524167802Sjkim        case ACPI_RESOURCE_NAME_VENDOR_LARGE:
525167802Sjkim            /*
526167802Sjkim             * Vendor Resource:
527167802Sjkim             * Get the number of vendor data bytes
528167802Sjkim             */
529167802Sjkim            ExtraStructBytes = ResourceLength;
530167802Sjkim            break;
53167754Smsmith
53267754Smsmith
533167802Sjkim        case ACPI_RESOURCE_NAME_END_TAG:
534167802Sjkim            /*
535167802Sjkim             * End Tag:
536167802Sjkim             * This is the normal exit, add size of EndTag
537167802Sjkim             */
538167802Sjkim            *SizeNeeded += ACPI_RS_SIZE_MIN;
539167802Sjkim            return_ACPI_STATUS (AE_OK);
540138287Smarks
54177424Smsmith
542167802Sjkim        case ACPI_RESOURCE_NAME_ADDRESS32:
543167802Sjkim        case ACPI_RESOURCE_NAME_ADDRESS16:
544167802Sjkim        case ACPI_RESOURCE_NAME_ADDRESS64:
54577424Smsmith            /*
546167802Sjkim             * Address Resource:
547167802Sjkim             * Add the size of the optional ResourceSource
54877424Smsmith             */
549167802Sjkim            ExtraStructBytes = AcpiRsStreamOptionLength (
550167802Sjkim                ResourceLength, MinimumAmlResourceLength);
551167802Sjkim            break;
55267754Smsmith
55367754Smsmith
554167802Sjkim        case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
555167802Sjkim            /*
556167802Sjkim             * Extended IRQ Resource:
557167802Sjkim             * Using the InterruptTableLength, add 4 bytes for each additional
558167802Sjkim             * interrupt. Note: at least one interrupt is required and is
559167802Sjkim             * included in the minimum descriptor size (reason for the -1)
560167802Sjkim             */
561167802Sjkim            ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
56267754Smsmith
563167802Sjkim            /* Add the size of the optional ResourceSource */
56467754Smsmith
565167802Sjkim            ExtraStructBytes += AcpiRsStreamOptionLength (
566167802Sjkim                ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
567167802Sjkim            break;
56867754Smsmith
56967754Smsmith
570167802Sjkim        default:
571167802Sjkim            break;
572167802Sjkim        }
57367754Smsmith
574167802Sjkim        /*
575167802Sjkim         * Update the required buffer size for the internal descriptor structs
576167802Sjkim         *
577167802Sjkim         * Important: Round the size up for the appropriate alignment. This
578167802Sjkim         * is a requirement on IA64.
579167802Sjkim         */
580167802Sjkim        BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
581167802Sjkim                        ExtraStructBytes;
582167802Sjkim        BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
58367754Smsmith
584167802Sjkim        *SizeNeeded += BufferSize;
58567754Smsmith
586167802Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
587167802Sjkim            "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
588167802Sjkim            AcpiUtGetResourceType (AmlBuffer),
589167802Sjkim            AcpiUtGetDescriptorLength (AmlBuffer), BufferSize));
59067754Smsmith
59167754Smsmith        /*
592167802Sjkim         * Point to the next resource within the AML stream using the length
593167802Sjkim         * contained in the resource descriptor header
59467754Smsmith         */
595167802Sjkim        AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
59667754Smsmith    }
59767754Smsmith
598167802Sjkim    /* Did not find an EndTag resource descriptor */
599151937Sjkim
600167802Sjkim    return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
60167754Smsmith}
60267754Smsmith
60367754Smsmith
60467754Smsmith/*******************************************************************************
60567754Smsmith *
60699679Siwasaki * FUNCTION:    AcpiRsGetPciRoutingTableLength
60767754Smsmith *
60867754Smsmith * PARAMETERS:  PackageObject           - Pointer to the package object
60967754Smsmith *              BufferSizeNeeded        - UINT32 pointer of the size buffer
61077424Smsmith *                                        needed to properly return the
61177424Smsmith *                                        parsed data
61267754Smsmith *
61377424Smsmith * RETURN:      Status
61467754Smsmith *
61567754Smsmith * DESCRIPTION: Given a package representing a PCI routing table, this
61677424Smsmith *              calculates the size of the corresponding linked list of
61777424Smsmith *              descriptions.
61867754Smsmith *
61967754Smsmith ******************************************************************************/
62067754Smsmith
62167754SmsmithACPI_STATUS
62299679SiwasakiAcpiRsGetPciRoutingTableLength (
62367754Smsmith    ACPI_OPERAND_OBJECT     *PackageObject,
62491116Smsmith    ACPI_SIZE               *BufferSizeNeeded)
62567754Smsmith{
62667754Smsmith    UINT32                  NumberOfElements;
62799679Siwasaki    ACPI_SIZE               TempSizeNeeded = 0;
62867754Smsmith    ACPI_OPERAND_OBJECT     **TopObjectList;
62967754Smsmith    UINT32                  Index;
63067754Smsmith    ACPI_OPERAND_OBJECT     *PackageElement;
63167754Smsmith    ACPI_OPERAND_OBJECT     **SubObjectList;
63267754Smsmith    BOOLEAN                 NameFound;
63367754Smsmith    UINT32                  TableIndex;
63467754Smsmith
63567754Smsmith
636167802Sjkim    ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
63767754Smsmith
63867754Smsmith
63967754Smsmith    NumberOfElements = PackageObject->Package.Count;
64067754Smsmith
64167754Smsmith    /*
64267754Smsmith     * Calculate the size of the return buffer.
64367754Smsmith     * The base size is the number of elements * the sizes of the
64467754Smsmith     * structures.  Additional space for the strings is added below.
64567754Smsmith     * The minus one is to subtract the size of the UINT8 Source[1]
64667754Smsmith     * member because it is added below.
64767754Smsmith     *
64867754Smsmith     * But each PRT_ENTRY structure has a pointer to a string and
64967754Smsmith     * the size of that string must be found.
65067754Smsmith     */
65167754Smsmith    TopObjectList = PackageObject->Package.Elements;
65267754Smsmith
65367754Smsmith    for (Index = 0; Index < NumberOfElements; Index++)
65467754Smsmith    {
655151937Sjkim        /* Dereference the sub-package */
656151937Sjkim
65767754Smsmith        PackageElement = *TopObjectList;
65867754Smsmith
659193267Sjkim        /* We must have a valid Package object */
660193267Sjkim
661193267Sjkim        if (!PackageElement ||
662193267Sjkim            (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
663193267Sjkim        {
664193267Sjkim            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
665193267Sjkim        }
666193267Sjkim
66767754Smsmith        /*
66867754Smsmith         * The SubObjectList will now point to an array of the
66967754Smsmith         * four IRQ elements: Address, Pin, Source and SourceIndex
67067754Smsmith         */
67167754Smsmith        SubObjectList = PackageElement->Package.Elements;
67267754Smsmith
673151937Sjkim        /* Scan the IrqTableElements for the Source Name String */
674151937Sjkim
67567754Smsmith        NameFound = FALSE;
67667754Smsmith
67767754Smsmith        for (TableIndex = 0; TableIndex < 4 && !NameFound; TableIndex++)
67867754Smsmith        {
679167802Sjkim            if (*SubObjectList && /* Null object allowed */
680167802Sjkim
681167802Sjkim                ((ACPI_TYPE_STRING ==
682193267Sjkim                    (*SubObjectList)->Common.Type) ||
683151937Sjkim
684151937Sjkim                ((ACPI_TYPE_LOCAL_REFERENCE ==
685193267Sjkim                    (*SubObjectList)->Common.Type) &&
686151937Sjkim
687193267Sjkim                    ((*SubObjectList)->Reference.Class ==
688193267Sjkim                        ACPI_REFCLASS_NAME))))
68967754Smsmith            {
69067754Smsmith                NameFound = TRUE;
69167754Smsmith            }
69267754Smsmith            else
69367754Smsmith            {
694151937Sjkim                /* Look at the next element */
695151937Sjkim
69667754Smsmith                SubObjectList++;
69767754Smsmith            }
69867754Smsmith        }
69967754Smsmith
70091116Smsmith        TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
70169450Smsmith
702151937Sjkim        /* Was a String type found? */
703151937Sjkim
70499679Siwasaki        if (NameFound)
70567754Smsmith        {
706193267Sjkim            if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
70773561Smsmith            {
70873561Smsmith                /*
709114237Snjl                 * The length String.Length field does not include the
710114237Snjl                 * terminating NULL, add 1
71173561Smsmith                 */
712151937Sjkim                TempSizeNeeded += ((ACPI_SIZE)
713151937Sjkim                    (*SubObjectList)->String.Length + 1);
71473561Smsmith            }
71573561Smsmith            else
71673561Smsmith            {
71777424Smsmith                TempSizeNeeded += AcpiNsGetPathnameLength (
71877424Smsmith                                    (*SubObjectList)->Reference.Node);
71973561Smsmith            }
72067754Smsmith        }
72167754Smsmith        else
72267754Smsmith        {
72367754Smsmith            /*
72467754Smsmith             * If no name was found, then this is a NULL, which is
72577424Smsmith             * translated as a UINT32 zero.
72667754Smsmith             */
72777424Smsmith            TempSizeNeeded += sizeof (UINT32);
72867754Smsmith        }
72967754Smsmith
73069450Smsmith        /* Round up the size since each element must be aligned */
73169450Smsmith
732167802Sjkim        TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
73369450Smsmith
734151937Sjkim        /* Point to the next ACPI_OPERAND_OBJECT */
735151937Sjkim
73667754Smsmith        TopObjectList++;
73767754Smsmith    }
73867754Smsmith
73977424Smsmith    /*
740167802Sjkim     * Add an extra element to the end of the list, essentially a
741151937Sjkim     * NULL terminator
74277424Smsmith     */
74391116Smsmith    *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
74467754Smsmith    return_ACPI_STATUS (AE_OK);
74569450Smsmith}
746