xref: /freebsd/sys/contrib/dev/acpica/components/resources/rscreate.c (revision a159c266a93c3c4f229864954c5f963acd8f60f2)
1*a159c266SJung-uk Kim /*******************************************************************************
2*a159c266SJung-uk Kim  *
3*a159c266SJung-uk Kim  * Module Name: rscreate - Create resource lists/tables
4*a159c266SJung-uk Kim  *
5*a159c266SJung-uk Kim  ******************************************************************************/
6*a159c266SJung-uk Kim 
7*a159c266SJung-uk Kim /*
8*a159c266SJung-uk Kim  * Copyright (C) 2000 - 2012, Intel Corp.
9*a159c266SJung-uk Kim  * All rights reserved.
10*a159c266SJung-uk Kim  *
11*a159c266SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12*a159c266SJung-uk Kim  * modification, are permitted provided that the following conditions
13*a159c266SJung-uk Kim  * are met:
14*a159c266SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15*a159c266SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16*a159c266SJung-uk Kim  *    without modification.
17*a159c266SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*a159c266SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19*a159c266SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20*a159c266SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21*a159c266SJung-uk Kim  *    binary redistribution.
22*a159c266SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23*a159c266SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24*a159c266SJung-uk Kim  *    from this software without specific prior written permission.
25*a159c266SJung-uk Kim  *
26*a159c266SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27*a159c266SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28*a159c266SJung-uk Kim  * Software Foundation.
29*a159c266SJung-uk Kim  *
30*a159c266SJung-uk Kim  * NO WARRANTY
31*a159c266SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*a159c266SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*a159c266SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*a159c266SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*a159c266SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*a159c266SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*a159c266SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*a159c266SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*a159c266SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*a159c266SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*a159c266SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42*a159c266SJung-uk Kim  */
43*a159c266SJung-uk Kim 
44*a159c266SJung-uk Kim #define __RSCREATE_C__
45*a159c266SJung-uk Kim 
46*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acresrc.h>
49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
50*a159c266SJung-uk Kim 
51*a159c266SJung-uk Kim #define _COMPONENT          ACPI_RESOURCES
52*a159c266SJung-uk Kim         ACPI_MODULE_NAME    ("rscreate")
53*a159c266SJung-uk Kim 
54*a159c266SJung-uk Kim 
55*a159c266SJung-uk Kim /*******************************************************************************
56*a159c266SJung-uk Kim  *
57*a159c266SJung-uk Kim  * FUNCTION:    AcpiBufferToResource
58*a159c266SJung-uk Kim  *
59*a159c266SJung-uk Kim  * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
60*a159c266SJung-uk Kim  *              AmlBufferLength     - Length of the AmlBuffer
61*a159c266SJung-uk Kim  *              ResourcePtr         - Where the converted resource is returned
62*a159c266SJung-uk Kim  *
63*a159c266SJung-uk Kim  * RETURN:      Status
64*a159c266SJung-uk Kim  *
65*a159c266SJung-uk Kim  * DESCRIPTION: Convert a raw AML buffer to a resource list
66*a159c266SJung-uk Kim  *
67*a159c266SJung-uk Kim  ******************************************************************************/
68*a159c266SJung-uk Kim 
69*a159c266SJung-uk Kim ACPI_STATUS
70*a159c266SJung-uk Kim AcpiBufferToResource (
71*a159c266SJung-uk Kim     UINT8                   *AmlBuffer,
72*a159c266SJung-uk Kim     UINT16                  AmlBufferLength,
73*a159c266SJung-uk Kim     ACPI_RESOURCE           **ResourcePtr)
74*a159c266SJung-uk Kim {
75*a159c266SJung-uk Kim     ACPI_STATUS             Status;
76*a159c266SJung-uk Kim     ACPI_SIZE               ListSizeNeeded;
77*a159c266SJung-uk Kim     void                    *Resource;
78*a159c266SJung-uk Kim     void                    *CurrentResourcePtr;
79*a159c266SJung-uk Kim 
80*a159c266SJung-uk Kim     /*
81*a159c266SJung-uk Kim      * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag
82*a159c266SJung-uk Kim      * is not required here.
83*a159c266SJung-uk Kim      */
84*a159c266SJung-uk Kim 
85*a159c266SJung-uk Kim     /* Get the required length for the converted resource */
86*a159c266SJung-uk Kim 
87*a159c266SJung-uk Kim     Status = AcpiRsGetListLength (AmlBuffer, AmlBufferLength,
88*a159c266SJung-uk Kim                 &ListSizeNeeded);
89*a159c266SJung-uk Kim     if (Status == AE_AML_NO_RESOURCE_END_TAG)
90*a159c266SJung-uk Kim     {
91*a159c266SJung-uk Kim         Status = AE_OK;
92*a159c266SJung-uk Kim     }
93*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
94*a159c266SJung-uk Kim     {
95*a159c266SJung-uk Kim         return (Status);
96*a159c266SJung-uk Kim     }
97*a159c266SJung-uk Kim 
98*a159c266SJung-uk Kim     /* Allocate a buffer for the converted resource */
99*a159c266SJung-uk Kim 
100*a159c266SJung-uk Kim     Resource = ACPI_ALLOCATE_ZEROED (ListSizeNeeded);
101*a159c266SJung-uk Kim     CurrentResourcePtr = Resource;
102*a159c266SJung-uk Kim     if (!Resource)
103*a159c266SJung-uk Kim     {
104*a159c266SJung-uk Kim         return (AE_NO_MEMORY);
105*a159c266SJung-uk Kim     }
106*a159c266SJung-uk Kim 
107*a159c266SJung-uk Kim     /* Perform the AML-to-Resource conversion */
108*a159c266SJung-uk Kim 
109*a159c266SJung-uk Kim     Status = AcpiUtWalkAmlResources (AmlBuffer, AmlBufferLength,
110*a159c266SJung-uk Kim                 AcpiRsConvertAmlToResources, &CurrentResourcePtr);
111*a159c266SJung-uk Kim     if (Status == AE_AML_NO_RESOURCE_END_TAG)
112*a159c266SJung-uk Kim     {
113*a159c266SJung-uk Kim         Status = AE_OK;
114*a159c266SJung-uk Kim     }
115*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
116*a159c266SJung-uk Kim     {
117*a159c266SJung-uk Kim         ACPI_FREE (Resource);
118*a159c266SJung-uk Kim     }
119*a159c266SJung-uk Kim     else
120*a159c266SJung-uk Kim     {
121*a159c266SJung-uk Kim         *ResourcePtr = Resource;
122*a159c266SJung-uk Kim     }
123*a159c266SJung-uk Kim 
124*a159c266SJung-uk Kim     return (Status);
125*a159c266SJung-uk Kim }
126*a159c266SJung-uk Kim 
127*a159c266SJung-uk Kim 
128*a159c266SJung-uk Kim /*******************************************************************************
129*a159c266SJung-uk Kim  *
130*a159c266SJung-uk Kim  * FUNCTION:    AcpiRsCreateResourceList
131*a159c266SJung-uk Kim  *
132*a159c266SJung-uk Kim  * PARAMETERS:  AmlBuffer           - Pointer to the resource byte stream
133*a159c266SJung-uk Kim  *              OutputBuffer        - Pointer to the user's buffer
134*a159c266SJung-uk Kim  *
135*a159c266SJung-uk Kim  * RETURN:      Status: AE_OK if okay, else a valid ACPI_STATUS code
136*a159c266SJung-uk Kim  *              If OutputBuffer is not large enough, OutputBufferLength
137*a159c266SJung-uk Kim  *              indicates how large OutputBuffer should be, else it
138*a159c266SJung-uk Kim  *              indicates how may UINT8 elements of OutputBuffer are valid.
139*a159c266SJung-uk Kim  *
140*a159c266SJung-uk Kim  * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method
141*a159c266SJung-uk Kim  *              execution and parses the stream to create a linked list
142*a159c266SJung-uk Kim  *              of device resources.
143*a159c266SJung-uk Kim  *
144*a159c266SJung-uk Kim  ******************************************************************************/
145*a159c266SJung-uk Kim 
146*a159c266SJung-uk Kim ACPI_STATUS
147*a159c266SJung-uk Kim AcpiRsCreateResourceList (
148*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *AmlBuffer,
149*a159c266SJung-uk Kim     ACPI_BUFFER             *OutputBuffer)
150*a159c266SJung-uk Kim {
151*a159c266SJung-uk Kim 
152*a159c266SJung-uk Kim     ACPI_STATUS             Status;
153*a159c266SJung-uk Kim     UINT8                   *AmlStart;
154*a159c266SJung-uk Kim     ACPI_SIZE               ListSizeNeeded = 0;
155*a159c266SJung-uk Kim     UINT32                  AmlBufferLength;
156*a159c266SJung-uk Kim     void                    *Resource;
157*a159c266SJung-uk Kim 
158*a159c266SJung-uk Kim 
159*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (RsCreateResourceList);
160*a159c266SJung-uk Kim 
161*a159c266SJung-uk Kim 
162*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AmlBuffer = %p\n",
163*a159c266SJung-uk Kim         AmlBuffer));
164*a159c266SJung-uk Kim 
165*a159c266SJung-uk Kim     /* Params already validated, so we don't re-validate here */
166*a159c266SJung-uk Kim 
167*a159c266SJung-uk Kim     AmlBufferLength = AmlBuffer->Buffer.Length;
168*a159c266SJung-uk Kim     AmlStart = AmlBuffer->Buffer.Pointer;
169*a159c266SJung-uk Kim 
170*a159c266SJung-uk Kim     /*
171*a159c266SJung-uk Kim      * Pass the AmlBuffer into a module that can calculate
172*a159c266SJung-uk Kim      * the buffer size needed for the linked list
173*a159c266SJung-uk Kim      */
174*a159c266SJung-uk Kim     Status = AcpiRsGetListLength (AmlStart, AmlBufferLength,
175*a159c266SJung-uk Kim                 &ListSizeNeeded);
176*a159c266SJung-uk Kim 
177*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n",
178*a159c266SJung-uk Kim         Status, (UINT32) ListSizeNeeded));
179*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
180*a159c266SJung-uk Kim     {
181*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
182*a159c266SJung-uk Kim     }
183*a159c266SJung-uk Kim 
184*a159c266SJung-uk Kim     /* Validate/Allocate/Clear caller buffer */
185*a159c266SJung-uk Kim 
186*a159c266SJung-uk Kim     Status = AcpiUtInitializeBuffer (OutputBuffer, ListSizeNeeded);
187*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
188*a159c266SJung-uk Kim     {
189*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
190*a159c266SJung-uk Kim     }
191*a159c266SJung-uk Kim 
192*a159c266SJung-uk Kim     /* Do the conversion */
193*a159c266SJung-uk Kim 
194*a159c266SJung-uk Kim     Resource = OutputBuffer->Pointer;
195*a159c266SJung-uk Kim     Status = AcpiUtWalkAmlResources (AmlStart, AmlBufferLength,
196*a159c266SJung-uk Kim                 AcpiRsConvertAmlToResources, &Resource);
197*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
198*a159c266SJung-uk Kim     {
199*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
200*a159c266SJung-uk Kim     }
201*a159c266SJung-uk Kim 
202*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
203*a159c266SJung-uk Kim             OutputBuffer->Pointer, (UINT32) OutputBuffer->Length));
204*a159c266SJung-uk Kim     return_ACPI_STATUS (AE_OK);
205*a159c266SJung-uk Kim }
206*a159c266SJung-uk Kim 
207*a159c266SJung-uk Kim 
208*a159c266SJung-uk Kim /*******************************************************************************
209*a159c266SJung-uk Kim  *
210*a159c266SJung-uk Kim  * FUNCTION:    AcpiRsCreatePciRoutingTable
211*a159c266SJung-uk Kim  *
212*a159c266SJung-uk Kim  * PARAMETERS:  PackageObject           - Pointer to an ACPI_OPERAND_OBJECT
213*a159c266SJung-uk Kim  *                                        package
214*a159c266SJung-uk Kim  *              OutputBuffer            - Pointer to the user's buffer
215*a159c266SJung-uk Kim  *
216*a159c266SJung-uk Kim  * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code.
217*a159c266SJung-uk Kim  *              If the OutputBuffer is too small, the error will be
218*a159c266SJung-uk Kim  *              AE_BUFFER_OVERFLOW and OutputBuffer->Length will point
219*a159c266SJung-uk Kim  *              to the size buffer needed.
220*a159c266SJung-uk Kim  *
221*a159c266SJung-uk Kim  * DESCRIPTION: Takes the ACPI_OPERAND_OBJECT  package and creates a
222*a159c266SJung-uk Kim  *              linked list of PCI interrupt descriptions
223*a159c266SJung-uk Kim  *
224*a159c266SJung-uk Kim  * NOTE: It is the caller's responsibility to ensure that the start of the
225*a159c266SJung-uk Kim  * output buffer is aligned properly (if necessary).
226*a159c266SJung-uk Kim  *
227*a159c266SJung-uk Kim  ******************************************************************************/
228*a159c266SJung-uk Kim 
229*a159c266SJung-uk Kim ACPI_STATUS
230*a159c266SJung-uk Kim AcpiRsCreatePciRoutingTable (
231*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *PackageObject,
232*a159c266SJung-uk Kim     ACPI_BUFFER             *OutputBuffer)
233*a159c266SJung-uk Kim {
234*a159c266SJung-uk Kim     UINT8                   *Buffer;
235*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     **TopObjectList;
236*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     **SubObjectList;
237*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
238*a159c266SJung-uk Kim     ACPI_SIZE               BufferSizeNeeded = 0;
239*a159c266SJung-uk Kim     UINT32                  NumberOfElements;
240*a159c266SJung-uk Kim     UINT32                  Index;
241*a159c266SJung-uk Kim     ACPI_PCI_ROUTING_TABLE  *UserPrt;
242*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
243*a159c266SJung-uk Kim     ACPI_STATUS             Status;
244*a159c266SJung-uk Kim     ACPI_BUFFER             PathBuffer;
245*a159c266SJung-uk Kim 
246*a159c266SJung-uk Kim 
247*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (RsCreatePciRoutingTable);
248*a159c266SJung-uk Kim 
249*a159c266SJung-uk Kim 
250*a159c266SJung-uk Kim     /* Params already validated, so we don't re-validate here */
251*a159c266SJung-uk Kim 
252*a159c266SJung-uk Kim     /* Get the required buffer length */
253*a159c266SJung-uk Kim 
254*a159c266SJung-uk Kim     Status = AcpiRsGetPciRoutingTableLength (PackageObject,
255*a159c266SJung-uk Kim                 &BufferSizeNeeded);
256*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
257*a159c266SJung-uk Kim     {
258*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
259*a159c266SJung-uk Kim     }
260*a159c266SJung-uk Kim 
261*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
262*a159c266SJung-uk Kim         (UINT32) BufferSizeNeeded));
263*a159c266SJung-uk Kim 
264*a159c266SJung-uk Kim     /* Validate/Allocate/Clear caller buffer */
265*a159c266SJung-uk Kim 
266*a159c266SJung-uk Kim     Status = AcpiUtInitializeBuffer (OutputBuffer, BufferSizeNeeded);
267*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
268*a159c266SJung-uk Kim     {
269*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
270*a159c266SJung-uk Kim     }
271*a159c266SJung-uk Kim 
272*a159c266SJung-uk Kim     /*
273*a159c266SJung-uk Kim      * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a
274*a159c266SJung-uk Kim      * package that in turn contains an UINT64 Address, a UINT8 Pin,
275*a159c266SJung-uk Kim      * a Name, and a UINT8 SourceIndex.
276*a159c266SJung-uk Kim      */
277*a159c266SJung-uk Kim     TopObjectList    = PackageObject->Package.Elements;
278*a159c266SJung-uk Kim     NumberOfElements = PackageObject->Package.Count;
279*a159c266SJung-uk Kim     Buffer           = OutputBuffer->Pointer;
280*a159c266SJung-uk Kim     UserPrt          = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer);
281*a159c266SJung-uk Kim 
282*a159c266SJung-uk Kim     for (Index = 0; Index < NumberOfElements; Index++)
283*a159c266SJung-uk Kim     {
284*a159c266SJung-uk Kim         /*
285*a159c266SJung-uk Kim          * Point UserPrt past this current structure
286*a159c266SJung-uk Kim          *
287*a159c266SJung-uk Kim          * NOTE: On the first iteration, UserPrt->Length will
288*a159c266SJung-uk Kim          * be zero because we cleared the return buffer earlier
289*a159c266SJung-uk Kim          */
290*a159c266SJung-uk Kim         Buffer += UserPrt->Length;
291*a159c266SJung-uk Kim         UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer);
292*a159c266SJung-uk Kim 
293*a159c266SJung-uk Kim         /*
294*a159c266SJung-uk Kim          * Fill in the Length field with the information we have at this point.
295*a159c266SJung-uk Kim          * The minus four is to subtract the size of the UINT8 Source[4] member
296*a159c266SJung-uk Kim          * because it is added below.
297*a159c266SJung-uk Kim          */
298*a159c266SJung-uk Kim         UserPrt->Length = (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);
299*a159c266SJung-uk Kim 
300*a159c266SJung-uk Kim         /* Each element of the top-level package must also be a package */
301*a159c266SJung-uk Kim 
302*a159c266SJung-uk Kim         if ((*TopObjectList)->Common.Type != ACPI_TYPE_PACKAGE)
303*a159c266SJung-uk Kim         {
304*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO,
305*a159c266SJung-uk Kim                 "(PRT[%u]) Need sub-package, found %s",
306*a159c266SJung-uk Kim                 Index, AcpiUtGetObjectTypeName (*TopObjectList)));
307*a159c266SJung-uk Kim             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
308*a159c266SJung-uk Kim         }
309*a159c266SJung-uk Kim 
310*a159c266SJung-uk Kim         /* Each sub-package must be of length 4 */
311*a159c266SJung-uk Kim 
312*a159c266SJung-uk Kim         if ((*TopObjectList)->Package.Count != 4)
313*a159c266SJung-uk Kim         {
314*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO,
315*a159c266SJung-uk Kim                 "(PRT[%u]) Need package of length 4, found length %u",
316*a159c266SJung-uk Kim                 Index, (*TopObjectList)->Package.Count));
317*a159c266SJung-uk Kim             return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT);
318*a159c266SJung-uk Kim         }
319*a159c266SJung-uk Kim 
320*a159c266SJung-uk Kim         /*
321*a159c266SJung-uk Kim          * Dereference the sub-package.
322*a159c266SJung-uk Kim          * The SubObjectList will now point to an array of the four IRQ
323*a159c266SJung-uk Kim          * elements: [Address, Pin, Source, SourceIndex]
324*a159c266SJung-uk Kim          */
325*a159c266SJung-uk Kim         SubObjectList = (*TopObjectList)->Package.Elements;
326*a159c266SJung-uk Kim 
327*a159c266SJung-uk Kim         /* 1) First subobject: Dereference the PRT.Address */
328*a159c266SJung-uk Kim 
329*a159c266SJung-uk Kim         ObjDesc = SubObjectList[0];
330*a159c266SJung-uk Kim         if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
331*a159c266SJung-uk Kim         {
332*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO, "(PRT[%u].Address) Need Integer, found %s",
333*a159c266SJung-uk Kim                 Index, AcpiUtGetObjectTypeName (ObjDesc)));
334*a159c266SJung-uk Kim             return_ACPI_STATUS (AE_BAD_DATA);
335*a159c266SJung-uk Kim         }
336*a159c266SJung-uk Kim 
337*a159c266SJung-uk Kim         UserPrt->Address = ObjDesc->Integer.Value;
338*a159c266SJung-uk Kim 
339*a159c266SJung-uk Kim         /* 2) Second subobject: Dereference the PRT.Pin */
340*a159c266SJung-uk Kim 
341*a159c266SJung-uk Kim         ObjDesc = SubObjectList[1];
342*a159c266SJung-uk Kim         if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
343*a159c266SJung-uk Kim         {
344*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s",
345*a159c266SJung-uk Kim                 Index, AcpiUtGetObjectTypeName (ObjDesc)));
346*a159c266SJung-uk Kim             return_ACPI_STATUS (AE_BAD_DATA);
347*a159c266SJung-uk Kim         }
348*a159c266SJung-uk Kim 
349*a159c266SJung-uk Kim         UserPrt->Pin = (UINT32) ObjDesc->Integer.Value;
350*a159c266SJung-uk Kim 
351*a159c266SJung-uk Kim         /*
352*a159c266SJung-uk Kim          * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
353*a159c266SJung-uk Kim          * and the SourceIndex (index 3), fix it. _PRT is important enough to
354*a159c266SJung-uk Kim          * workaround this BIOS error. This also provides compatibility with
355*a159c266SJung-uk Kim          * other ACPI implementations.
356*a159c266SJung-uk Kim          */
357*a159c266SJung-uk Kim         ObjDesc = SubObjectList[3];
358*a159c266SJung-uk Kim         if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
359*a159c266SJung-uk Kim         {
360*a159c266SJung-uk Kim             SubObjectList[3] = SubObjectList[2];
361*a159c266SJung-uk Kim             SubObjectList[2] = ObjDesc;
362*a159c266SJung-uk Kim 
363*a159c266SJung-uk Kim             ACPI_WARNING ((AE_INFO,
364*a159c266SJung-uk Kim                 "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed",
365*a159c266SJung-uk Kim                 Index));
366*a159c266SJung-uk Kim         }
367*a159c266SJung-uk Kim 
368*a159c266SJung-uk Kim         /*
369*a159c266SJung-uk Kim          * 3) Third subobject: Dereference the PRT.SourceName
370*a159c266SJung-uk Kim          * The name may be unresolved (slack mode), so allow a null object
371*a159c266SJung-uk Kim          */
372*a159c266SJung-uk Kim         ObjDesc = SubObjectList[2];
373*a159c266SJung-uk Kim         if (ObjDesc)
374*a159c266SJung-uk Kim         {
375*a159c266SJung-uk Kim             switch (ObjDesc->Common.Type)
376*a159c266SJung-uk Kim             {
377*a159c266SJung-uk Kim             case ACPI_TYPE_LOCAL_REFERENCE:
378*a159c266SJung-uk Kim 
379*a159c266SJung-uk Kim                 if (ObjDesc->Reference.Class != ACPI_REFCLASS_NAME)
380*a159c266SJung-uk Kim                 {
381*a159c266SJung-uk Kim                     ACPI_ERROR ((AE_INFO,
382*a159c266SJung-uk Kim                         "(PRT[%u].Source) Need name, found Reference Class 0x%X",
383*a159c266SJung-uk Kim                         Index, ObjDesc->Reference.Class));
384*a159c266SJung-uk Kim                     return_ACPI_STATUS (AE_BAD_DATA);
385*a159c266SJung-uk Kim                 }
386*a159c266SJung-uk Kim 
387*a159c266SJung-uk Kim                 Node = ObjDesc->Reference.Node;
388*a159c266SJung-uk Kim 
389*a159c266SJung-uk Kim                 /* Use *remaining* length of the buffer as max for pathname */
390*a159c266SJung-uk Kim 
391*a159c266SJung-uk Kim                 PathBuffer.Length = OutputBuffer->Length -
392*a159c266SJung-uk Kim                                     (UINT32) ((UINT8 *) UserPrt->Source -
393*a159c266SJung-uk Kim                                     (UINT8 *) OutputBuffer->Pointer);
394*a159c266SJung-uk Kim                 PathBuffer.Pointer = UserPrt->Source;
395*a159c266SJung-uk Kim 
396*a159c266SJung-uk Kim                 Status = AcpiNsHandleToPathname ((ACPI_HANDLE) Node, &PathBuffer);
397*a159c266SJung-uk Kim 
398*a159c266SJung-uk Kim                 /* +1 to include null terminator */
399*a159c266SJung-uk Kim 
400*a159c266SJung-uk Kim                 UserPrt->Length += (UINT32) ACPI_STRLEN (UserPrt->Source) + 1;
401*a159c266SJung-uk Kim                 break;
402*a159c266SJung-uk Kim 
403*a159c266SJung-uk Kim 
404*a159c266SJung-uk Kim             case ACPI_TYPE_STRING:
405*a159c266SJung-uk Kim 
406*a159c266SJung-uk Kim                 ACPI_STRCPY (UserPrt->Source, ObjDesc->String.Pointer);
407*a159c266SJung-uk Kim 
408*a159c266SJung-uk Kim                 /*
409*a159c266SJung-uk Kim                  * Add to the Length field the length of the string
410*a159c266SJung-uk Kim                  * (add 1 for terminator)
411*a159c266SJung-uk Kim                  */
412*a159c266SJung-uk Kim                 UserPrt->Length += ObjDesc->String.Length + 1;
413*a159c266SJung-uk Kim                 break;
414*a159c266SJung-uk Kim 
415*a159c266SJung-uk Kim 
416*a159c266SJung-uk Kim             case ACPI_TYPE_INTEGER:
417*a159c266SJung-uk Kim                 /*
418*a159c266SJung-uk Kim                  * If this is a number, then the Source Name is NULL, since the
419*a159c266SJung-uk Kim                  * entire buffer was zeroed out, we can leave this alone.
420*a159c266SJung-uk Kim                  *
421*a159c266SJung-uk Kim                  * Add to the Length field the length of the UINT32 NULL
422*a159c266SJung-uk Kim                  */
423*a159c266SJung-uk Kim                 UserPrt->Length += sizeof (UINT32);
424*a159c266SJung-uk Kim                 break;
425*a159c266SJung-uk Kim 
426*a159c266SJung-uk Kim 
427*a159c266SJung-uk Kim             default:
428*a159c266SJung-uk Kim 
429*a159c266SJung-uk Kim                ACPI_ERROR ((AE_INFO,
430*a159c266SJung-uk Kim                    "(PRT[%u].Source) Need Ref/String/Integer, found %s",
431*a159c266SJung-uk Kim                    Index, AcpiUtGetObjectTypeName (ObjDesc)));
432*a159c266SJung-uk Kim                return_ACPI_STATUS (AE_BAD_DATA);
433*a159c266SJung-uk Kim             }
434*a159c266SJung-uk Kim         }
435*a159c266SJung-uk Kim 
436*a159c266SJung-uk Kim         /* Now align the current length */
437*a159c266SJung-uk Kim 
438*a159c266SJung-uk Kim         UserPrt->Length = (UINT32) ACPI_ROUND_UP_TO_64BIT (UserPrt->Length);
439*a159c266SJung-uk Kim 
440*a159c266SJung-uk Kim         /* 4) Fourth subobject: Dereference the PRT.SourceIndex */
441*a159c266SJung-uk Kim 
442*a159c266SJung-uk Kim         ObjDesc = SubObjectList[3];
443*a159c266SJung-uk Kim         if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
444*a159c266SJung-uk Kim         {
445*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO,
446*a159c266SJung-uk Kim                 "(PRT[%u].SourceIndex) Need Integer, found %s",
447*a159c266SJung-uk Kim                 Index, AcpiUtGetObjectTypeName (ObjDesc)));
448*a159c266SJung-uk Kim             return_ACPI_STATUS (AE_BAD_DATA);
449*a159c266SJung-uk Kim         }
450*a159c266SJung-uk Kim 
451*a159c266SJung-uk Kim         UserPrt->SourceIndex = (UINT32) ObjDesc->Integer.Value;
452*a159c266SJung-uk Kim 
453*a159c266SJung-uk Kim         /* Point to the next ACPI_OPERAND_OBJECT in the top level package */
454*a159c266SJung-uk Kim 
455*a159c266SJung-uk Kim         TopObjectList++;
456*a159c266SJung-uk Kim     }
457*a159c266SJung-uk Kim 
458*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
459*a159c266SJung-uk Kim             OutputBuffer->Pointer, (UINT32) OutputBuffer->Length));
460*a159c266SJung-uk Kim     return_ACPI_STATUS (AE_OK);
461*a159c266SJung-uk Kim }
462*a159c266SJung-uk Kim 
463*a159c266SJung-uk Kim 
464*a159c266SJung-uk Kim /*******************************************************************************
465*a159c266SJung-uk Kim  *
466*a159c266SJung-uk Kim  * FUNCTION:    AcpiRsCreateAmlResources
467*a159c266SJung-uk Kim  *
468*a159c266SJung-uk Kim  * PARAMETERS:  LinkedListBuffer        - Pointer to the resource linked list
469*a159c266SJung-uk Kim  *              OutputBuffer            - Pointer to the user's buffer
470*a159c266SJung-uk Kim  *
471*a159c266SJung-uk Kim  * RETURN:      Status  AE_OK if okay, else a valid ACPI_STATUS code.
472*a159c266SJung-uk Kim  *              If the OutputBuffer is too small, the error will be
473*a159c266SJung-uk Kim  *              AE_BUFFER_OVERFLOW and OutputBuffer->Length will point
474*a159c266SJung-uk Kim  *              to the size buffer needed.
475*a159c266SJung-uk Kim  *
476*a159c266SJung-uk Kim  * DESCRIPTION: Takes the linked list of device resources and
477*a159c266SJung-uk Kim  *              creates a bytestream to be used as input for the
478*a159c266SJung-uk Kim  *              _SRS control method.
479*a159c266SJung-uk Kim  *
480*a159c266SJung-uk Kim  ******************************************************************************/
481*a159c266SJung-uk Kim 
482*a159c266SJung-uk Kim ACPI_STATUS
483*a159c266SJung-uk Kim AcpiRsCreateAmlResources (
484*a159c266SJung-uk Kim     ACPI_RESOURCE           *LinkedListBuffer,
485*a159c266SJung-uk Kim     ACPI_BUFFER             *OutputBuffer)
486*a159c266SJung-uk Kim {
487*a159c266SJung-uk Kim     ACPI_STATUS             Status;
488*a159c266SJung-uk Kim     ACPI_SIZE               AmlSizeNeeded = 0;
489*a159c266SJung-uk Kim 
490*a159c266SJung-uk Kim 
491*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (RsCreateAmlResources);
492*a159c266SJung-uk Kim 
493*a159c266SJung-uk Kim 
494*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "LinkedListBuffer = %p\n",
495*a159c266SJung-uk Kim         LinkedListBuffer));
496*a159c266SJung-uk Kim 
497*a159c266SJung-uk Kim     /*
498*a159c266SJung-uk Kim      * Params already validated, so we don't re-validate here
499*a159c266SJung-uk Kim      *
500*a159c266SJung-uk Kim      * Pass the LinkedListBuffer into a module that calculates
501*a159c266SJung-uk Kim      * the buffer size needed for the byte stream.
502*a159c266SJung-uk Kim      */
503*a159c266SJung-uk Kim     Status = AcpiRsGetAmlLength (LinkedListBuffer,
504*a159c266SJung-uk Kim                 &AmlSizeNeeded);
505*a159c266SJung-uk Kim 
506*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
507*a159c266SJung-uk Kim         (UINT32) AmlSizeNeeded, AcpiFormatException (Status)));
508*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
509*a159c266SJung-uk Kim     {
510*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
511*a159c266SJung-uk Kim     }
512*a159c266SJung-uk Kim 
513*a159c266SJung-uk Kim     /* Validate/Allocate/Clear caller buffer */
514*a159c266SJung-uk Kim 
515*a159c266SJung-uk Kim     Status = AcpiUtInitializeBuffer (OutputBuffer, AmlSizeNeeded);
516*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
517*a159c266SJung-uk Kim     {
518*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
519*a159c266SJung-uk Kim     }
520*a159c266SJung-uk Kim 
521*a159c266SJung-uk Kim     /* Do the conversion */
522*a159c266SJung-uk Kim 
523*a159c266SJung-uk Kim     Status = AcpiRsConvertResourcesToAml (LinkedListBuffer, AmlSizeNeeded,
524*a159c266SJung-uk Kim                     OutputBuffer->Pointer);
525*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
526*a159c266SJung-uk Kim     {
527*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
528*a159c266SJung-uk Kim     }
529*a159c266SJung-uk Kim 
530*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
531*a159c266SJung-uk Kim             OutputBuffer->Pointer, (UINT32) OutputBuffer->Length));
532*a159c266SJung-uk Kim     return_ACPI_STATUS (AE_OK);
533*a159c266SJung-uk Kim }
534*a159c266SJung-uk Kim 
535