xref: /titanic_44/usr/src/uts/intel/io/acpica/resources/rscalc.c (revision cb56572868bfc488bbd3ab847b09db2a25554d44)
1ae115bc7Smrj /*******************************************************************************
2ae115bc7Smrj  *
3ae115bc7Smrj  * Module Name: rscalc - Calculate stream and list lengths
4ae115bc7Smrj  *
5ae115bc7Smrj  ******************************************************************************/
6ae115bc7Smrj 
726f3cdf0SGordon Ross /*
8*cb565728SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj  * All rights reserved.
10ae115bc7Smrj  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
25ae115bc7Smrj  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
29ae115bc7Smrj  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
43ae115bc7Smrj 
44ae115bc7Smrj #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46ae115bc7Smrj #include "acresrc.h"
47ae115bc7Smrj #include "acnamesp.h"
48ae115bc7Smrj 
49db2bae30SDana Myers 
50ae115bc7Smrj #define _COMPONENT          ACPI_RESOURCES
51ae115bc7Smrj         ACPI_MODULE_NAME    ("rscalc")
52ae115bc7Smrj 
53ae115bc7Smrj 
54ae115bc7Smrj /* Local prototypes */
55ae115bc7Smrj 
56ae115bc7Smrj static UINT8
57ae115bc7Smrj AcpiRsCountSetBits (
58ae115bc7Smrj     UINT16                  BitField);
59ae115bc7Smrj 
60ae115bc7Smrj static ACPI_RS_LENGTH
61ae115bc7Smrj AcpiRsStructOptionLength (
62ae115bc7Smrj     ACPI_RESOURCE_SOURCE    *ResourceSource);
63ae115bc7Smrj 
64ae115bc7Smrj static UINT32
65ae115bc7Smrj AcpiRsStreamOptionLength (
66ae115bc7Smrj     UINT32                  ResourceLength,
67ae115bc7Smrj     UINT32                  MinimumTotalLength);
68ae115bc7Smrj 
69ae115bc7Smrj 
70ae115bc7Smrj /*******************************************************************************
71ae115bc7Smrj  *
72ae115bc7Smrj  * FUNCTION:    AcpiRsCountSetBits
73ae115bc7Smrj  *
74ae115bc7Smrj  * PARAMETERS:  BitField        - Field in which to count bits
75ae115bc7Smrj  *
76ae115bc7Smrj  * RETURN:      Number of bits set within the field
77ae115bc7Smrj  *
78ae115bc7Smrj  * DESCRIPTION: Count the number of bits set in a resource field. Used for
79ae115bc7Smrj  *              (Short descriptor) interrupt and DMA lists.
80ae115bc7Smrj  *
81ae115bc7Smrj  ******************************************************************************/
82ae115bc7Smrj 
83ae115bc7Smrj static UINT8
AcpiRsCountSetBits(UINT16 BitField)84ae115bc7Smrj AcpiRsCountSetBits (
85ae115bc7Smrj     UINT16                  BitField)
86ae115bc7Smrj {
87ae115bc7Smrj     UINT8                   BitsSet;
88ae115bc7Smrj 
89ae115bc7Smrj 
90ae115bc7Smrj     ACPI_FUNCTION_ENTRY ();
91ae115bc7Smrj 
92ae115bc7Smrj 
93ae115bc7Smrj     for (BitsSet = 0; BitField; BitsSet++)
94ae115bc7Smrj     {
95ae115bc7Smrj         /* Zero the least significant bit that is set */
96ae115bc7Smrj 
97db2bae30SDana Myers         BitField &= (UINT16) (BitField - 1);
98ae115bc7Smrj     }
99ae115bc7Smrj 
100ae115bc7Smrj     return (BitsSet);
101ae115bc7Smrj }
102ae115bc7Smrj 
103ae115bc7Smrj 
104ae115bc7Smrj /*******************************************************************************
105ae115bc7Smrj  *
106ae115bc7Smrj  * FUNCTION:    AcpiRsStructOptionLength
107ae115bc7Smrj  *
108ae115bc7Smrj  * PARAMETERS:  ResourceSource      - Pointer to optional descriptor field
109ae115bc7Smrj  *
110ae115bc7Smrj  * RETURN:      Status
111ae115bc7Smrj  *
112ae115bc7Smrj  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
113ae115bc7Smrj  *              ResourceSource fields in some Large descriptors. Used during
114ae115bc7Smrj  *              list-to-stream conversion
115ae115bc7Smrj  *
116ae115bc7Smrj  ******************************************************************************/
117ae115bc7Smrj 
118ae115bc7Smrj static ACPI_RS_LENGTH
AcpiRsStructOptionLength(ACPI_RESOURCE_SOURCE * ResourceSource)119ae115bc7Smrj AcpiRsStructOptionLength (
120ae115bc7Smrj     ACPI_RESOURCE_SOURCE    *ResourceSource)
121ae115bc7Smrj {
122ae115bc7Smrj     ACPI_FUNCTION_ENTRY ();
123ae115bc7Smrj 
124ae115bc7Smrj 
125ae115bc7Smrj     /*
126ae115bc7Smrj      * If the ResourceSource string is valid, return the size of the string
127ae115bc7Smrj      * (StringLength includes the NULL terminator) plus the size of the
128ae115bc7Smrj      * ResourceSourceIndex (1).
129ae115bc7Smrj      */
130ae115bc7Smrj     if (ResourceSource->StringPtr)
131ae115bc7Smrj     {
132ae115bc7Smrj         return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1));
133ae115bc7Smrj     }
134ae115bc7Smrj 
135ae115bc7Smrj     return (0);
136ae115bc7Smrj }
137ae115bc7Smrj 
138ae115bc7Smrj 
139ae115bc7Smrj /*******************************************************************************
140ae115bc7Smrj  *
141ae115bc7Smrj  * FUNCTION:    AcpiRsStreamOptionLength
142ae115bc7Smrj  *
143ae115bc7Smrj  * PARAMETERS:  ResourceLength      - Length from the resource header
144ae115bc7Smrj  *              MinimumTotalLength  - Minimum length of this resource, before
145ae115bc7Smrj  *                                    any optional fields. Includes header size
146ae115bc7Smrj  *
147ae115bc7Smrj  * RETURN:      Length of optional string (0 if no string present)
148ae115bc7Smrj  *
149ae115bc7Smrj  * DESCRIPTION: Common code to handle optional ResourceSourceIndex and
150ae115bc7Smrj  *              ResourceSource fields in some Large descriptors. Used during
151ae115bc7Smrj  *              stream-to-list conversion
152ae115bc7Smrj  *
153ae115bc7Smrj  ******************************************************************************/
154ae115bc7Smrj 
155ae115bc7Smrj static UINT32
AcpiRsStreamOptionLength(UINT32 ResourceLength,UINT32 MinimumAmlResourceLength)156ae115bc7Smrj AcpiRsStreamOptionLength (
157ae115bc7Smrj     UINT32                  ResourceLength,
158ae115bc7Smrj     UINT32                  MinimumAmlResourceLength)
159ae115bc7Smrj {
160ae115bc7Smrj     UINT32                  StringLength = 0;
161ae115bc7Smrj 
162ae115bc7Smrj 
163ae115bc7Smrj     ACPI_FUNCTION_ENTRY ();
164ae115bc7Smrj 
165ae115bc7Smrj 
166ae115bc7Smrj     /*
167*cb565728SJerry Jelinek      * The ResourceSourceIndex and ResourceSource are optional elements of
168*cb565728SJerry Jelinek      * some Large-type resource descriptors.
169ae115bc7Smrj      */
170ae115bc7Smrj 
171ae115bc7Smrj     /*
172*cb565728SJerry Jelinek      * If the length of the actual resource descriptor is greater than the
173*cb565728SJerry Jelinek      * ACPI spec-defined minimum length, it means that a ResourceSourceIndex
174*cb565728SJerry Jelinek      * exists and is followed by a (required) null terminated string. The
175*cb565728SJerry Jelinek      * string length (including the null terminator) is the resource length
176*cb565728SJerry Jelinek      * minus the minimum length, minus one byte for the ResourceSourceIndex
177*cb565728SJerry Jelinek      * itself.
178ae115bc7Smrj      */
179ae115bc7Smrj     if (ResourceLength > MinimumAmlResourceLength)
180ae115bc7Smrj     {
181ae115bc7Smrj         /* Compute the length of the optional string */
182ae115bc7Smrj 
183ae115bc7Smrj         StringLength = ResourceLength - MinimumAmlResourceLength - 1;
184ae115bc7Smrj     }
185ae115bc7Smrj 
186ae115bc7Smrj     /*
187ae115bc7Smrj      * Round the length up to a multiple of the native word in order to
188ae115bc7Smrj      * guarantee that the entire resource descriptor is native word aligned
189ae115bc7Smrj      */
190ae115bc7Smrj     return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength));
191ae115bc7Smrj }
192ae115bc7Smrj 
193ae115bc7Smrj 
194ae115bc7Smrj /*******************************************************************************
195ae115bc7Smrj  *
196ae115bc7Smrj  * FUNCTION:    AcpiRsGetAmlLength
197ae115bc7Smrj  *
198ae115bc7Smrj  * PARAMETERS:  Resource            - Pointer to the resource linked list
199*cb565728SJerry Jelinek  *              ResourceListSize    - Size of the resource linked list
200ae115bc7Smrj  *              SizeNeeded          - Where the required size is returned
201ae115bc7Smrj  *
202ae115bc7Smrj  * RETURN:      Status
203ae115bc7Smrj  *
204ae115bc7Smrj  * DESCRIPTION: Takes a linked list of internal resource descriptors and
205ae115bc7Smrj  *              calculates the size buffer needed to hold the corresponding
206ae115bc7Smrj  *              external resource byte stream.
207ae115bc7Smrj  *
208ae115bc7Smrj  ******************************************************************************/
209ae115bc7Smrj 
210ae115bc7Smrj ACPI_STATUS
AcpiRsGetAmlLength(ACPI_RESOURCE * Resource,ACPI_SIZE ResourceListSize,ACPI_SIZE * SizeNeeded)211ae115bc7Smrj AcpiRsGetAmlLength (
212ae115bc7Smrj     ACPI_RESOURCE           *Resource,
213*cb565728SJerry Jelinek     ACPI_SIZE               ResourceListSize,
214ae115bc7Smrj     ACPI_SIZE               *SizeNeeded)
215ae115bc7Smrj {
216ae115bc7Smrj     ACPI_SIZE               AmlSizeNeeded = 0;
217*cb565728SJerry Jelinek     ACPI_RESOURCE           *ResourceEnd;
218ae115bc7Smrj     ACPI_RS_LENGTH          TotalSize;
219ae115bc7Smrj 
220ae115bc7Smrj 
221ae115bc7Smrj     ACPI_FUNCTION_TRACE (RsGetAmlLength);
222ae115bc7Smrj 
223ae115bc7Smrj 
224ae115bc7Smrj     /* Traverse entire list of internal resource descriptors */
225ae115bc7Smrj 
226*cb565728SJerry Jelinek     ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize);
227*cb565728SJerry Jelinek     while (Resource < ResourceEnd)
228ae115bc7Smrj     {
229ae115bc7Smrj         /* Validate the descriptor type */
230ae115bc7Smrj 
231ae115bc7Smrj         if (Resource->Type > ACPI_RESOURCE_TYPE_MAX)
232ae115bc7Smrj         {
233ae115bc7Smrj             return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
234ae115bc7Smrj         }
235ae115bc7Smrj 
236*cb565728SJerry Jelinek         /* Sanity check the length. It must not be zero, or we loop forever */
237*cb565728SJerry Jelinek 
238*cb565728SJerry Jelinek         if (!Resource->Length)
239*cb565728SJerry Jelinek         {
240*cb565728SJerry Jelinek             return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
241*cb565728SJerry Jelinek         }
242*cb565728SJerry Jelinek 
243ae115bc7Smrj         /* Get the base size of the (external stream) resource descriptor */
244ae115bc7Smrj 
245ae115bc7Smrj         TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type];
246ae115bc7Smrj 
247ae115bc7Smrj         /*
248ae115bc7Smrj          * Augment the base size for descriptors with optional and/or
249ae115bc7Smrj          * variable-length fields
250ae115bc7Smrj          */
251ae115bc7Smrj         switch (Resource->Type)
252ae115bc7Smrj         {
253db2bae30SDana Myers         case ACPI_RESOURCE_TYPE_IRQ:
254db2bae30SDana Myers 
255db2bae30SDana Myers             /* Length can be 3 or 2 */
256db2bae30SDana Myers 
257db2bae30SDana Myers             if (Resource->Data.Irq.DescriptorLength == 2)
258db2bae30SDana Myers             {
259db2bae30SDana Myers                 TotalSize--;
260db2bae30SDana Myers             }
261db2bae30SDana Myers             break;
262db2bae30SDana Myers 
263db2bae30SDana Myers 
264db2bae30SDana Myers         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
265db2bae30SDana Myers 
266db2bae30SDana Myers             /* Length can be 1 or 0 */
267db2bae30SDana Myers 
268db2bae30SDana Myers             if (Resource->Data.Irq.DescriptorLength == 0)
269db2bae30SDana Myers             {
270db2bae30SDana Myers                 TotalSize--;
271db2bae30SDana Myers             }
272db2bae30SDana Myers             break;
273db2bae30SDana Myers 
274db2bae30SDana Myers 
275ae115bc7Smrj         case ACPI_RESOURCE_TYPE_VENDOR:
276ae115bc7Smrj             /*
277ae115bc7Smrj              * Vendor Defined Resource:
278ae115bc7Smrj              * For a Vendor Specific resource, if the Length is between 1 and 7
279ae115bc7Smrj              * it will be created as a Small Resource data type, otherwise it
280ae115bc7Smrj              * is a Large Resource data type.
281ae115bc7Smrj              */
282ae115bc7Smrj             if (Resource->Data.Vendor.ByteLength > 7)
283ae115bc7Smrj             {
284ae115bc7Smrj                 /* Base size of a Large resource descriptor */
285ae115bc7Smrj 
286ae115bc7Smrj                 TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER);
287ae115bc7Smrj             }
288ae115bc7Smrj 
289ae115bc7Smrj             /* Add the size of the vendor-specific data */
290ae115bc7Smrj 
291ae115bc7Smrj             TotalSize = (ACPI_RS_LENGTH)
292ae115bc7Smrj                 (TotalSize + Resource->Data.Vendor.ByteLength);
293ae115bc7Smrj             break;
294ae115bc7Smrj 
295ae115bc7Smrj 
296ae115bc7Smrj         case ACPI_RESOURCE_TYPE_END_TAG:
297ae115bc7Smrj             /*
298ae115bc7Smrj              * End Tag:
299ae115bc7Smrj              * We are done -- return the accumulated total size.
300ae115bc7Smrj              */
301ae115bc7Smrj             *SizeNeeded = AmlSizeNeeded + TotalSize;
302ae115bc7Smrj 
303ae115bc7Smrj             /* Normal exit */
304ae115bc7Smrj 
305ae115bc7Smrj             return_ACPI_STATUS (AE_OK);
306ae115bc7Smrj 
307ae115bc7Smrj 
308ae115bc7Smrj         case ACPI_RESOURCE_TYPE_ADDRESS16:
309ae115bc7Smrj             /*
310ae115bc7Smrj              * 16-Bit Address Resource:
311ae115bc7Smrj              * Add the size of the optional ResourceSource info
312ae115bc7Smrj              */
313*cb565728SJerry Jelinek             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
314*cb565728SJerry Jelinek                 AcpiRsStructOptionLength (
315ae115bc7Smrj                     &Resource->Data.Address16.ResourceSource));
316ae115bc7Smrj             break;
317ae115bc7Smrj 
318ae115bc7Smrj 
319ae115bc7Smrj         case ACPI_RESOURCE_TYPE_ADDRESS32:
320ae115bc7Smrj             /*
321ae115bc7Smrj              * 32-Bit Address Resource:
322ae115bc7Smrj              * Add the size of the optional ResourceSource info
323ae115bc7Smrj              */
324*cb565728SJerry Jelinek             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
325*cb565728SJerry Jelinek                 AcpiRsStructOptionLength (
326ae115bc7Smrj                     &Resource->Data.Address32.ResourceSource));
327ae115bc7Smrj             break;
328ae115bc7Smrj 
329ae115bc7Smrj 
330ae115bc7Smrj         case ACPI_RESOURCE_TYPE_ADDRESS64:
331ae115bc7Smrj             /*
332ae115bc7Smrj              * 64-Bit Address Resource:
333ae115bc7Smrj              * Add the size of the optional ResourceSource info
334ae115bc7Smrj              */
335*cb565728SJerry Jelinek             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
336*cb565728SJerry Jelinek                 AcpiRsStructOptionLength (
337ae115bc7Smrj                     &Resource->Data.Address64.ResourceSource));
338ae115bc7Smrj             break;
339ae115bc7Smrj 
340ae115bc7Smrj 
341ae115bc7Smrj         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
342ae115bc7Smrj             /*
343ae115bc7Smrj              * Extended IRQ Resource:
344ae115bc7Smrj              * Add the size of each additional optional interrupt beyond the
345ae115bc7Smrj              * required 1 (4 bytes for each UINT32 interrupt number)
346ae115bc7Smrj              */
347*cb565728SJerry Jelinek             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
348ae115bc7Smrj                 ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) +
349ae115bc7Smrj 
350ae115bc7Smrj                 /* Add the size of the optional ResourceSource info */
351ae115bc7Smrj 
352ae115bc7Smrj                 AcpiRsStructOptionLength (
353ae115bc7Smrj                     &Resource->Data.ExtendedIrq.ResourceSource));
354ae115bc7Smrj             break;
355ae115bc7Smrj 
356ae115bc7Smrj 
357*cb565728SJerry Jelinek         case ACPI_RESOURCE_TYPE_GPIO:
358*cb565728SJerry Jelinek 
359*cb565728SJerry Jelinek             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
360*cb565728SJerry Jelinek                 (Resource->Data.Gpio.PinTableLength * 2) +
361*cb565728SJerry Jelinek                 Resource->Data.Gpio.ResourceSource.StringLength +
362*cb565728SJerry Jelinek                 Resource->Data.Gpio.VendorLength);
363*cb565728SJerry Jelinek 
364*cb565728SJerry Jelinek             break;
365*cb565728SJerry Jelinek 
366*cb565728SJerry Jelinek 
367*cb565728SJerry Jelinek         case ACPI_RESOURCE_TYPE_SERIAL_BUS:
368*cb565728SJerry Jelinek 
369*cb565728SJerry Jelinek             TotalSize = AcpiGbl_AmlResourceSerialBusSizes [
370*cb565728SJerry Jelinek                 Resource->Data.CommonSerialBus.Type];
371*cb565728SJerry Jelinek 
372*cb565728SJerry Jelinek             TotalSize = (ACPI_RS_LENGTH) (TotalSize +
373*cb565728SJerry Jelinek                 Resource->Data.I2cSerialBus.ResourceSource.StringLength +
374*cb565728SJerry Jelinek                 Resource->Data.I2cSerialBus.VendorLength);
375*cb565728SJerry Jelinek 
376*cb565728SJerry Jelinek             break;
377*cb565728SJerry Jelinek 
378ae115bc7Smrj         default:
379*cb565728SJerry Jelinek 
380ae115bc7Smrj             break;
381ae115bc7Smrj         }
382ae115bc7Smrj 
383ae115bc7Smrj         /* Update the total */
384ae115bc7Smrj 
385ae115bc7Smrj         AmlSizeNeeded += TotalSize;
386ae115bc7Smrj 
387ae115bc7Smrj         /* Point to the next object */
388ae115bc7Smrj 
389ae115bc7Smrj         Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length);
390ae115bc7Smrj     }
391ae115bc7Smrj 
392ae115bc7Smrj     /* Did not find an EndTag resource descriptor */
393ae115bc7Smrj 
394ae115bc7Smrj     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
395ae115bc7Smrj }
396ae115bc7Smrj 
397ae115bc7Smrj 
398ae115bc7Smrj /*******************************************************************************
399ae115bc7Smrj  *
400ae115bc7Smrj  * FUNCTION:    AcpiRsGetListLength
401ae115bc7Smrj  *
402ae115bc7Smrj  * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
403ae115bc7Smrj  *              AmlBufferLength     - Size of AmlBuffer
404ae115bc7Smrj  *              SizeNeeded          - Where the size needed is returned
405ae115bc7Smrj  *
406ae115bc7Smrj  * RETURN:      Status
407ae115bc7Smrj  *
408ae115bc7Smrj  * DESCRIPTION: Takes an external resource byte stream and calculates the size
409ae115bc7Smrj  *              buffer needed to hold the corresponding internal resource
410ae115bc7Smrj  *              descriptor linked list.
411ae115bc7Smrj  *
412ae115bc7Smrj  ******************************************************************************/
413ae115bc7Smrj 
414ae115bc7Smrj ACPI_STATUS
AcpiRsGetListLength(UINT8 * AmlBuffer,UINT32 AmlBufferLength,ACPI_SIZE * SizeNeeded)415ae115bc7Smrj AcpiRsGetListLength (
416ae115bc7Smrj     UINT8                   *AmlBuffer,
417ae115bc7Smrj     UINT32                  AmlBufferLength,
418ae115bc7Smrj     ACPI_SIZE               *SizeNeeded)
419ae115bc7Smrj {
420ae115bc7Smrj     ACPI_STATUS             Status;
421ae115bc7Smrj     UINT8                   *EndAml;
422ae115bc7Smrj     UINT8                   *Buffer;
423ae115bc7Smrj     UINT32                  BufferSize;
424ae115bc7Smrj     UINT16                  Temp16;
425ae115bc7Smrj     UINT16                  ResourceLength;
426ae115bc7Smrj     UINT32                  ExtraStructBytes;
427ae115bc7Smrj     UINT8                   ResourceIndex;
428ae115bc7Smrj     UINT8                   MinimumAmlResourceLength;
429*cb565728SJerry Jelinek     AML_RESOURCE            *AmlResource;
430ae115bc7Smrj 
431ae115bc7Smrj 
432ae115bc7Smrj     ACPI_FUNCTION_TRACE (RsGetListLength);
433ae115bc7Smrj 
434ae115bc7Smrj 
435*cb565728SJerry Jelinek     *SizeNeeded = ACPI_RS_SIZE_MIN;         /* Minimum size is one EndTag */
436ae115bc7Smrj     EndAml = AmlBuffer + AmlBufferLength;
437ae115bc7Smrj 
438ae115bc7Smrj     /* Walk the list of AML resource descriptors */
439ae115bc7Smrj 
440ae115bc7Smrj     while (AmlBuffer < EndAml)
441ae115bc7Smrj     {
442ae115bc7Smrj         /* Validate the Resource Type and Resource Length */
443ae115bc7Smrj 
444*cb565728SJerry Jelinek         Status = AcpiUtValidateResource (NULL, AmlBuffer, &ResourceIndex);
445ae115bc7Smrj         if (ACPI_FAILURE (Status))
446ae115bc7Smrj         {
447*cb565728SJerry Jelinek             /*
448*cb565728SJerry Jelinek              * Exit on failure. Cannot continue because the descriptor length
449*cb565728SJerry Jelinek              * may be bogus also.
450*cb565728SJerry Jelinek              */
451ae115bc7Smrj             return_ACPI_STATUS (Status);
452ae115bc7Smrj         }
453ae115bc7Smrj 
454*cb565728SJerry Jelinek         AmlResource = (void *) AmlBuffer;
455*cb565728SJerry Jelinek 
456ae115bc7Smrj         /* Get the resource length and base (minimum) AML size */
457ae115bc7Smrj 
458ae115bc7Smrj         ResourceLength = AcpiUtGetResourceLength (AmlBuffer);
459ae115bc7Smrj         MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex];
460ae115bc7Smrj 
461ae115bc7Smrj         /*
462ae115bc7Smrj          * Augment the size for descriptors with optional
463ae115bc7Smrj          * and/or variable length fields
464ae115bc7Smrj          */
465ae115bc7Smrj         ExtraStructBytes = 0;
466ae115bc7Smrj         Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer);
467ae115bc7Smrj 
468ae115bc7Smrj         switch (AcpiUtGetResourceType (AmlBuffer))
469ae115bc7Smrj         {
470ae115bc7Smrj         case ACPI_RESOURCE_NAME_IRQ:
471ae115bc7Smrj             /*
472ae115bc7Smrj              * IRQ Resource:
473ae115bc7Smrj              * Get the number of bits set in the 16-bit IRQ mask
474ae115bc7Smrj              */
475ae115bc7Smrj             ACPI_MOVE_16_TO_16 (&Temp16, Buffer);
476ae115bc7Smrj             ExtraStructBytes = AcpiRsCountSetBits (Temp16);
477ae115bc7Smrj             break;
478ae115bc7Smrj 
479ae115bc7Smrj 
480ae115bc7Smrj         case ACPI_RESOURCE_NAME_DMA:
481ae115bc7Smrj             /*
482ae115bc7Smrj              * DMA Resource:
483ae115bc7Smrj              * Get the number of bits set in the 8-bit DMA mask
484ae115bc7Smrj              */
485ae115bc7Smrj             ExtraStructBytes = AcpiRsCountSetBits (*Buffer);
486ae115bc7Smrj             break;
487ae115bc7Smrj 
488ae115bc7Smrj 
489ae115bc7Smrj         case ACPI_RESOURCE_NAME_VENDOR_SMALL:
490ae115bc7Smrj         case ACPI_RESOURCE_NAME_VENDOR_LARGE:
491ae115bc7Smrj             /*
492ae115bc7Smrj              * Vendor Resource:
493ae115bc7Smrj              * Get the number of vendor data bytes
494ae115bc7Smrj              */
495ae115bc7Smrj             ExtraStructBytes = ResourceLength;
496*cb565728SJerry Jelinek 
497*cb565728SJerry Jelinek             /*
498*cb565728SJerry Jelinek              * There is already one byte included in the minimum
499*cb565728SJerry Jelinek              * descriptor size. If there are extra struct bytes,
500*cb565728SJerry Jelinek              * subtract one from the count.
501*cb565728SJerry Jelinek              */
502*cb565728SJerry Jelinek             if (ExtraStructBytes)
503*cb565728SJerry Jelinek             {
504*cb565728SJerry Jelinek                 ExtraStructBytes--;
505*cb565728SJerry Jelinek             }
506ae115bc7Smrj             break;
507ae115bc7Smrj 
508ae115bc7Smrj 
509ae115bc7Smrj         case ACPI_RESOURCE_NAME_END_TAG:
510ae115bc7Smrj             /*
511*cb565728SJerry Jelinek              * End Tag: This is the normal exit
512ae115bc7Smrj              */
513ae115bc7Smrj             return_ACPI_STATUS (AE_OK);
514ae115bc7Smrj 
515ae115bc7Smrj 
516ae115bc7Smrj         case ACPI_RESOURCE_NAME_ADDRESS32:
517ae115bc7Smrj         case ACPI_RESOURCE_NAME_ADDRESS16:
518ae115bc7Smrj         case ACPI_RESOURCE_NAME_ADDRESS64:
519ae115bc7Smrj             /*
520ae115bc7Smrj              * Address Resource:
521ae115bc7Smrj              * Add the size of the optional ResourceSource
522ae115bc7Smrj              */
523ae115bc7Smrj             ExtraStructBytes = AcpiRsStreamOptionLength (
524ae115bc7Smrj                 ResourceLength, MinimumAmlResourceLength);
525ae115bc7Smrj             break;
526ae115bc7Smrj 
527ae115bc7Smrj 
528ae115bc7Smrj         case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
529ae115bc7Smrj             /*
530ae115bc7Smrj              * Extended IRQ Resource:
531ae115bc7Smrj              * Using the InterruptTableLength, add 4 bytes for each additional
532ae115bc7Smrj              * interrupt. Note: at least one interrupt is required and is
533ae115bc7Smrj              * included in the minimum descriptor size (reason for the -1)
534ae115bc7Smrj              */
535ae115bc7Smrj             ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32);
536ae115bc7Smrj 
537ae115bc7Smrj             /* Add the size of the optional ResourceSource */
538ae115bc7Smrj 
539ae115bc7Smrj             ExtraStructBytes += AcpiRsStreamOptionLength (
540ae115bc7Smrj                 ResourceLength - ExtraStructBytes, MinimumAmlResourceLength);
541ae115bc7Smrj             break;
542ae115bc7Smrj 
543*cb565728SJerry Jelinek         case ACPI_RESOURCE_NAME_GPIO:
544*cb565728SJerry Jelinek 
545*cb565728SJerry Jelinek             /* Vendor data is optional */
546*cb565728SJerry Jelinek 
547*cb565728SJerry Jelinek             if (AmlResource->Gpio.VendorLength)
548*cb565728SJerry Jelinek             {
549*cb565728SJerry Jelinek                 ExtraStructBytes +=
550*cb565728SJerry Jelinek                     AmlResource->Gpio.VendorOffset -
551*cb565728SJerry Jelinek                     AmlResource->Gpio.PinTableOffset +
552*cb565728SJerry Jelinek                     AmlResource->Gpio.VendorLength;
553*cb565728SJerry Jelinek             }
554*cb565728SJerry Jelinek             else
555*cb565728SJerry Jelinek             {
556*cb565728SJerry Jelinek                 ExtraStructBytes +=
557*cb565728SJerry Jelinek                     AmlResource->LargeHeader.ResourceLength +
558*cb565728SJerry Jelinek                     sizeof (AML_RESOURCE_LARGE_HEADER) -
559*cb565728SJerry Jelinek                     AmlResource->Gpio.PinTableOffset;
560*cb565728SJerry Jelinek             }
561*cb565728SJerry Jelinek             break;
562*cb565728SJerry Jelinek 
563*cb565728SJerry Jelinek         case ACPI_RESOURCE_NAME_SERIAL_BUS:
564*cb565728SJerry Jelinek 
565*cb565728SJerry Jelinek             MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[
566*cb565728SJerry Jelinek                 AmlResource->CommonSerialBus.Type];
567*cb565728SJerry Jelinek             ExtraStructBytes +=
568*cb565728SJerry Jelinek                 AmlResource->CommonSerialBus.ResourceLength -
569*cb565728SJerry Jelinek                 MinimumAmlResourceLength;
570*cb565728SJerry Jelinek             break;
571ae115bc7Smrj 
572ae115bc7Smrj         default:
573*cb565728SJerry Jelinek 
574ae115bc7Smrj             break;
575ae115bc7Smrj         }
576ae115bc7Smrj 
577ae115bc7Smrj         /*
578ae115bc7Smrj          * Update the required buffer size for the internal descriptor structs
579ae115bc7Smrj          *
580ae115bc7Smrj          * Important: Round the size up for the appropriate alignment. This
581ae115bc7Smrj          * is a requirement on IA64.
582ae115bc7Smrj          */
583*cb565728SJerry Jelinek         if (AcpiUtGetResourceType (AmlBuffer) ==
584*cb565728SJerry Jelinek             ACPI_RESOURCE_NAME_SERIAL_BUS)
585*cb565728SJerry Jelinek         {
586*cb565728SJerry Jelinek             BufferSize = AcpiGbl_ResourceStructSerialBusSizes[
587*cb565728SJerry Jelinek                 AmlResource->CommonSerialBus.Type] + ExtraStructBytes;
588*cb565728SJerry Jelinek         }
589*cb565728SJerry Jelinek         else
590*cb565728SJerry Jelinek         {
591ae115bc7Smrj             BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] +
592ae115bc7Smrj                 ExtraStructBytes;
593*cb565728SJerry Jelinek         }
594ae115bc7Smrj 
595*cb565728SJerry Jelinek         BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize);
596ae115bc7Smrj         *SizeNeeded += BufferSize;
597ae115bc7Smrj 
598ae115bc7Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES,
599ae115bc7Smrj             "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
600ae115bc7Smrj             AcpiUtGetResourceType (AmlBuffer),
601ae115bc7Smrj             AcpiUtGetDescriptorLength (AmlBuffer), BufferSize));
602ae115bc7Smrj 
603ae115bc7Smrj         /*
604ae115bc7Smrj          * Point to the next resource within the AML stream using the length
605ae115bc7Smrj          * contained in the resource descriptor header
606ae115bc7Smrj          */
607ae115bc7Smrj         AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer);
608ae115bc7Smrj     }
609ae115bc7Smrj 
610ae115bc7Smrj     /* Did not find an EndTag resource descriptor */
611ae115bc7Smrj 
612ae115bc7Smrj     return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG);
613ae115bc7Smrj }
614ae115bc7Smrj 
615ae115bc7Smrj 
616ae115bc7Smrj /*******************************************************************************
617ae115bc7Smrj  *
618ae115bc7Smrj  * FUNCTION:    AcpiRsGetPciRoutingTableLength
619ae115bc7Smrj  *
620ae115bc7Smrj  * PARAMETERS:  PackageObject           - Pointer to the package object
621ae115bc7Smrj  *              BufferSizeNeeded        - UINT32 pointer of the size buffer
622ae115bc7Smrj  *                                        needed to properly return the
623ae115bc7Smrj  *                                        parsed data
624ae115bc7Smrj  *
625ae115bc7Smrj  * RETURN:      Status
626ae115bc7Smrj  *
627ae115bc7Smrj  * DESCRIPTION: Given a package representing a PCI routing table, this
628ae115bc7Smrj  *              calculates the size of the corresponding linked list of
629ae115bc7Smrj  *              descriptions.
630ae115bc7Smrj  *
631ae115bc7Smrj  ******************************************************************************/
632ae115bc7Smrj 
633ae115bc7Smrj ACPI_STATUS
AcpiRsGetPciRoutingTableLength(ACPI_OPERAND_OBJECT * PackageObject,ACPI_SIZE * BufferSizeNeeded)634ae115bc7Smrj AcpiRsGetPciRoutingTableLength (
635ae115bc7Smrj     ACPI_OPERAND_OBJECT     *PackageObject,
636ae115bc7Smrj     ACPI_SIZE               *BufferSizeNeeded)
637ae115bc7Smrj {
638ae115bc7Smrj     UINT32                  NumberOfElements;
639ae115bc7Smrj     ACPI_SIZE               TempSizeNeeded = 0;
640ae115bc7Smrj     ACPI_OPERAND_OBJECT     **TopObjectList;
641ae115bc7Smrj     UINT32                  Index;
642ae115bc7Smrj     ACPI_OPERAND_OBJECT     *PackageElement;
643ae115bc7Smrj     ACPI_OPERAND_OBJECT     **SubObjectList;
644ae115bc7Smrj     BOOLEAN                 NameFound;
645ae115bc7Smrj     UINT32                  TableIndex;
646ae115bc7Smrj 
647ae115bc7Smrj 
648ae115bc7Smrj     ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);
649ae115bc7Smrj 
650ae115bc7Smrj 
651ae115bc7Smrj     NumberOfElements = PackageObject->Package.Count;
652ae115bc7Smrj 
653ae115bc7Smrj     /*
654ae115bc7Smrj      * Calculate the size of the return buffer.
655ae115bc7Smrj      * The base size is the number of elements * the sizes of the
656ae115bc7Smrj      * structures. Additional space for the strings is added below.
657ae115bc7Smrj      * The minus one is to subtract the size of the UINT8 Source[1]
658ae115bc7Smrj      * member because it is added below.
659ae115bc7Smrj      *
660ae115bc7Smrj      * But each PRT_ENTRY structure has a pointer to a string and
661ae115bc7Smrj      * the size of that string must be found.
662ae115bc7Smrj      */
663ae115bc7Smrj     TopObjectList = PackageObject->Package.Elements;
664ae115bc7Smrj 
665ae115bc7Smrj     for (Index = 0; Index < NumberOfElements; Index++)
666ae115bc7Smrj     {
667*cb565728SJerry Jelinek         /* Dereference the subpackage */
668ae115bc7Smrj 
669ae115bc7Smrj         PackageElement = *TopObjectList;
670ae115bc7Smrj 
671aa2aa9a6SDana Myers         /* We must have a valid Package object */
672aa2aa9a6SDana Myers 
673aa2aa9a6SDana Myers         if (!PackageElement ||
674aa2aa9a6SDana Myers             (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
675aa2aa9a6SDana Myers         {
676aa2aa9a6SDana Myers             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
677aa2aa9a6SDana Myers         }
678aa2aa9a6SDana Myers 
679ae115bc7Smrj         /*
680ae115bc7Smrj          * The SubObjectList will now point to an array of the
681ae115bc7Smrj          * four IRQ elements: Address, Pin, Source and SourceIndex
682ae115bc7Smrj          */
683ae115bc7Smrj         SubObjectList = PackageElement->Package.Elements;
684ae115bc7Smrj 
685ae115bc7Smrj         /* Scan the IrqTableElements for the Source Name String */
686ae115bc7Smrj 
687ae115bc7Smrj         NameFound = FALSE;
688ae115bc7Smrj 
689*cb565728SJerry Jelinek         for (TableIndex = 0;
690*cb565728SJerry Jelinek              TableIndex < PackageElement->Package.Count && !NameFound;
691*cb565728SJerry Jelinek              TableIndex++)
692ae115bc7Smrj         {
693ae115bc7Smrj             if (*SubObjectList && /* Null object allowed */
694ae115bc7Smrj 
695ae115bc7Smrj                 ((ACPI_TYPE_STRING ==
696aa2aa9a6SDana Myers                     (*SubObjectList)->Common.Type) ||
697ae115bc7Smrj 
698ae115bc7Smrj                 ((ACPI_TYPE_LOCAL_REFERENCE ==
699aa2aa9a6SDana Myers                     (*SubObjectList)->Common.Type) &&
700ae115bc7Smrj 
701db2bae30SDana Myers                     ((*SubObjectList)->Reference.Class ==
702db2bae30SDana Myers                         ACPI_REFCLASS_NAME))))
703ae115bc7Smrj             {
704ae115bc7Smrj                 NameFound = TRUE;
705ae115bc7Smrj             }
706ae115bc7Smrj             else
707ae115bc7Smrj             {
708ae115bc7Smrj                 /* Look at the next element */
709ae115bc7Smrj 
710ae115bc7Smrj                 SubObjectList++;
711ae115bc7Smrj             }
712ae115bc7Smrj         }
713ae115bc7Smrj 
714ae115bc7Smrj         TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
715ae115bc7Smrj 
716ae115bc7Smrj         /* Was a String type found? */
717ae115bc7Smrj 
718ae115bc7Smrj         if (NameFound)
719ae115bc7Smrj         {
720aa2aa9a6SDana Myers             if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
721ae115bc7Smrj             {
722ae115bc7Smrj                 /*
723ae115bc7Smrj                  * The length String.Length field does not include the
724ae115bc7Smrj                  * terminating NULL, add 1
725ae115bc7Smrj                  */
726ae115bc7Smrj                 TempSizeNeeded += ((ACPI_SIZE)
727ae115bc7Smrj                     (*SubObjectList)->String.Length + 1);
728ae115bc7Smrj             }
729ae115bc7Smrj             else
730ae115bc7Smrj             {
731ae115bc7Smrj                 TempSizeNeeded += AcpiNsGetPathnameLength (
732ae115bc7Smrj                     (*SubObjectList)->Reference.Node);
733ae115bc7Smrj             }
734ae115bc7Smrj         }
735ae115bc7Smrj         else
736ae115bc7Smrj         {
737ae115bc7Smrj             /*
738ae115bc7Smrj              * If no name was found, then this is a NULL, which is
739ae115bc7Smrj              * translated as a UINT32 zero.
740ae115bc7Smrj              */
741ae115bc7Smrj             TempSizeNeeded += sizeof (UINT32);
742ae115bc7Smrj         }
743ae115bc7Smrj 
744ae115bc7Smrj         /* Round up the size since each element must be aligned */
745ae115bc7Smrj 
746ae115bc7Smrj         TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);
747ae115bc7Smrj 
748ae115bc7Smrj         /* Point to the next ACPI_OPERAND_OBJECT */
749ae115bc7Smrj 
750ae115bc7Smrj         TopObjectList++;
751ae115bc7Smrj     }
752ae115bc7Smrj 
753ae115bc7Smrj     /*
754ae115bc7Smrj      * Add an extra element to the end of the list, essentially a
755ae115bc7Smrj      * NULL terminator
756ae115bc7Smrj      */
757ae115bc7Smrj     *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
758ae115bc7Smrj     return_ACPI_STATUS (AE_OK);
759ae115bc7Smrj }
760