167754Smsmith/*******************************************************************************
267754Smsmith *
377424Smsmith * Module Name: rsmisc - Miscellaneous resource descriptors
467754Smsmith *
567754Smsmith ******************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
4467754Smsmith#define __RSMISC_C__
4567754Smsmith
46193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
47193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
48193341Sjkim#include <contrib/dev/acpica/include/acresrc.h>
4967754Smsmith
5077424Smsmith#define _COMPONENT          ACPI_RESOURCES
5191116Smsmith        ACPI_MODULE_NAME    ("rsmisc")
5267754Smsmith
5367754Smsmith
54151937Sjkim#define INIT_RESOURCE_TYPE(i)       i->ResourceOffset
55151937Sjkim#define INIT_RESOURCE_LENGTH(i)     i->AmlOffset
56151937Sjkim#define INIT_TABLE_LENGTH(i)        i->Value
57151937Sjkim
58151937Sjkim#define COMPARE_OPCODE(i)           i->ResourceOffset
59151937Sjkim#define COMPARE_TARGET(i)           i->AmlOffset
60151937Sjkim#define COMPARE_VALUE(i)            i->Value
61151937Sjkim
62151937Sjkim
6367754Smsmith/*******************************************************************************
6467754Smsmith *
65151937Sjkim * FUNCTION:    AcpiRsConvertAmlToResource
6667754Smsmith *
67151937Sjkim * PARAMETERS:  Resource            - Pointer to the resource descriptor
68151937Sjkim *              Aml                 - Where the AML descriptor is returned
69151937Sjkim *              Info                - Pointer to appropriate conversion table
7067754Smsmith *
7177424Smsmith * RETURN:      Status
7267754Smsmith *
73151937Sjkim * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
74151937Sjkim *              internal resource descriptor
7567754Smsmith *
7667754Smsmith ******************************************************************************/
7767754Smsmith
7867754SmsmithACPI_STATUS
79151937SjkimAcpiRsConvertAmlToResource (
80151937Sjkim    ACPI_RESOURCE           *Resource,
81151937Sjkim    AML_RESOURCE            *Aml,
82151937Sjkim    ACPI_RSCONVERT_INFO     *Info)
8367754Smsmith{
84151937Sjkim    ACPI_RS_LENGTH          AmlResourceLength;
85151937Sjkim    void                    *Source;
86151937Sjkim    void                    *Destination;
87151937Sjkim    char                    *Target;
88151937Sjkim    UINT8                   Count;
89151937Sjkim    UINT8                   FlagsMode = FALSE;
90151937Sjkim    UINT16                  ItemCount = 0;
91151937Sjkim    UINT16                  Temp16 = 0;
9267754Smsmith
9367754Smsmith
94167802Sjkim    ACPI_FUNCTION_TRACE (RsConvertAmlToResource);
9567754Smsmith
9677424Smsmith
97228110Sjkim    if (!Info)
98228110Sjkim    {
99228110Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
100228110Sjkim    }
101228110Sjkim
102193267Sjkim    if (((ACPI_SIZE) Resource) & 0x3)
103151937Sjkim    {
104167802Sjkim        /* Each internal resource struct is expected to be 32-bit aligned */
105167802Sjkim
106167802Sjkim        ACPI_WARNING ((AE_INFO,
107204773Sjkim            "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u",
108167802Sjkim            Resource, Resource->Type, Resource->Length));
109151937Sjkim    }
11067754Smsmith
111151937Sjkim    /* Extract the resource Length field (does not include header length) */
11267754Smsmith
113151937Sjkim    AmlResourceLength = AcpiUtGetResourceLength (Aml);
11467754Smsmith
11567754Smsmith    /*
116151937Sjkim     * First table entry must be ACPI_RSC_INITxxx and must contain the
117151937Sjkim     * table length (# of table entries)
11867754Smsmith     */
119151937Sjkim    Count = INIT_TABLE_LENGTH (Info);
120151937Sjkim    while (Count)
121151937Sjkim    {
122151937Sjkim        /*
123151937Sjkim         * Source is the external AML byte stream buffer,
124151937Sjkim         * destination is the internal resource descriptor
125151937Sjkim         */
126167802Sjkim        Source      = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
127167802Sjkim        Destination = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
12867754Smsmith
129151937Sjkim        switch (Info->Opcode)
130151937Sjkim        {
131151937Sjkim        case ACPI_RSC_INITGET:
132151937Sjkim            /*
133151937Sjkim             * Get the resource type and the initial (minimum) length
134151937Sjkim             */
135151937Sjkim            ACPI_MEMSET (Resource, 0, INIT_RESOURCE_LENGTH (Info));
136151937Sjkim            Resource->Type = INIT_RESOURCE_TYPE (Info);
137151937Sjkim            Resource->Length = INIT_RESOURCE_LENGTH (Info);
138151937Sjkim            break;
13967754Smsmith
140151937Sjkim        case ACPI_RSC_INITSET:
141151937Sjkim            break;
14267754Smsmith
143151937Sjkim        case ACPI_RSC_FLAGINIT:
14477424Smsmith
145151937Sjkim            FlagsMode = TRUE;
146151937Sjkim            break;
14767754Smsmith
148151937Sjkim        case ACPI_RSC_1BITFLAG:
149151937Sjkim            /*
150151937Sjkim             * Mask and shift the flag bit
151151937Sjkim             */
152243347Sjkim            ACPI_SET8 (Destination,
153243347Sjkim                ((ACPI_GET8 (Source) >> Info->Value) & 0x01));
154151937Sjkim            break;
15567754Smsmith
156151937Sjkim        case ACPI_RSC_2BITFLAG:
157151937Sjkim            /*
158151937Sjkim             * Mask and shift the flag bits
159151937Sjkim             */
160243347Sjkim            ACPI_SET8 (Destination,
161243347Sjkim                ((ACPI_GET8 (Source) >> Info->Value) & 0x03));
162151937Sjkim            break;
16367754Smsmith
164228110Sjkim        case ACPI_RSC_3BITFLAG:
165228110Sjkim            /*
166228110Sjkim             * Mask and shift the flag bits
167228110Sjkim             */
168243347Sjkim            ACPI_SET8 (Destination,
169243347Sjkim                ((ACPI_GET8 (Source) >> Info->Value) & 0x07));
170228110Sjkim            break;
171228110Sjkim
172151937Sjkim        case ACPI_RSC_COUNT:
17367754Smsmith
174167802Sjkim            ItemCount = ACPI_GET8 (Source);
175243347Sjkim            ACPI_SET8 (Destination, ItemCount);
17667754Smsmith
177151937Sjkim            Resource->Length = Resource->Length +
178151937Sjkim                (Info->Value * (ItemCount - 1));
179151937Sjkim            break;
18067754Smsmith
181151937Sjkim        case ACPI_RSC_COUNT16:
18267754Smsmith
183151937Sjkim            ItemCount = AmlResourceLength;
184243347Sjkim            ACPI_SET16 (Destination, ItemCount);
18567754Smsmith
186151937Sjkim            Resource->Length = Resource->Length +
187151937Sjkim                (Info->Value * (ItemCount - 1));
188151937Sjkim            break;
18967754Smsmith
190228110Sjkim        case ACPI_RSC_COUNT_GPIO_PIN:
191228110Sjkim
192228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, Info->Value);
193228110Sjkim            ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
194228110Sjkim
195228110Sjkim            Resource->Length = Resource->Length + ItemCount;
196228110Sjkim            ItemCount = ItemCount / 2;
197243347Sjkim            ACPI_SET16 (Destination, ItemCount);
198228110Sjkim            break;
199228110Sjkim
200228110Sjkim        case ACPI_RSC_COUNT_GPIO_VEN:
201228110Sjkim
202228110Sjkim            ItemCount = ACPI_GET8 (Source);
203243347Sjkim            ACPI_SET8 (Destination, ItemCount);
204228110Sjkim
205228110Sjkim            Resource->Length = Resource->Length +
206228110Sjkim                (Info->Value * ItemCount);
207228110Sjkim            break;
208228110Sjkim
209228110Sjkim        case ACPI_RSC_COUNT_GPIO_RES:
210228110Sjkim            /*
211228110Sjkim             * Vendor data is optional (length/offset may both be zero)
212228110Sjkim             * Examine vendor data length field first
213228110Sjkim             */
214228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, (Info->Value + 2));
215228110Sjkim            if (ACPI_GET16 (Target))
216228110Sjkim            {
217228110Sjkim                /* Use vendor offset to get resource source length */
218228110Sjkim
219228110Sjkim                Target = ACPI_ADD_PTR (void, Aml, Info->Value);
220228110Sjkim                ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
221228110Sjkim            }
222228110Sjkim            else
223228110Sjkim            {
224228110Sjkim                /* No vendor data to worry about */
225228110Sjkim
226228110Sjkim                ItemCount = Aml->LargeHeader.ResourceLength +
227228110Sjkim                    sizeof (AML_RESOURCE_LARGE_HEADER) -
228228110Sjkim                    ACPI_GET16 (Source);
229228110Sjkim            }
230228110Sjkim
231228110Sjkim            Resource->Length = Resource->Length + ItemCount;
232243347Sjkim            ACPI_SET16 (Destination, ItemCount);
233228110Sjkim            break;
234228110Sjkim
235228110Sjkim        case ACPI_RSC_COUNT_SERIAL_VEN:
236228110Sjkim
237228110Sjkim            ItemCount = ACPI_GET16 (Source) - Info->Value;
238228110Sjkim
239228110Sjkim            Resource->Length = Resource->Length + ItemCount;
240243347Sjkim            ACPI_SET16 (Destination, ItemCount);
241228110Sjkim            break;
242228110Sjkim
243228110Sjkim        case ACPI_RSC_COUNT_SERIAL_RES:
244228110Sjkim
245228110Sjkim            ItemCount = (AmlResourceLength +
246228110Sjkim                sizeof (AML_RESOURCE_LARGE_HEADER)) -
247228110Sjkim                ACPI_GET16 (Source) - Info->Value;
248228110Sjkim
249228110Sjkim            Resource->Length = Resource->Length + ItemCount;
250243347Sjkim            ACPI_SET16 (Destination, ItemCount);
251228110Sjkim            break;
252228110Sjkim
253151937Sjkim        case ACPI_RSC_LENGTH:
25467754Smsmith
255151937Sjkim            Resource->Length = Resource->Length + Info->Value;
256151937Sjkim            break;
25767754Smsmith
258151937Sjkim        case ACPI_RSC_MOVE8:
259151937Sjkim        case ACPI_RSC_MOVE16:
260151937Sjkim        case ACPI_RSC_MOVE32:
261151937Sjkim        case ACPI_RSC_MOVE64:
262151937Sjkim            /*
263151937Sjkim             * Raw data move. Use the Info value field unless ItemCount has
264151937Sjkim             * been previously initialized via a COUNT opcode
265151937Sjkim             */
266151937Sjkim            if (Info->Value)
267151937Sjkim            {
268151937Sjkim                ItemCount = Info->Value;
269151937Sjkim            }
270167802Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
271151937Sjkim            break;
27267754Smsmith
273228110Sjkim        case ACPI_RSC_MOVE_GPIO_PIN:
274228110Sjkim
275228110Sjkim            /* Generate and set the PIN data pointer */
276228110Sjkim
277228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
278228110Sjkim                  (Resource->Length - ItemCount * 2));
279228110Sjkim            *(UINT16 **) Destination = ACPI_CAST_PTR (UINT16, Target);
280228110Sjkim
281228110Sjkim            /* Copy the PIN data */
282228110Sjkim
283228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
284228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
285228110Sjkim            break;
286228110Sjkim
287228110Sjkim        case ACPI_RSC_MOVE_GPIO_RES:
288228110Sjkim
289228110Sjkim            /* Generate and set the ResourceSource string pointer */
290228110Sjkim
291228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
292228110Sjkim                  (Resource->Length - ItemCount));
293228110Sjkim            *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
294228110Sjkim
295228110Sjkim            /* Copy the ResourceSource string */
296228110Sjkim
297228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
298228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
299228110Sjkim            break;
300228110Sjkim
301228110Sjkim        case ACPI_RSC_MOVE_SERIAL_VEN:
302228110Sjkim
303228110Sjkim            /* Generate and set the Vendor Data pointer */
304228110Sjkim
305228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
306228110Sjkim                  (Resource->Length - ItemCount));
307228110Sjkim            *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
308228110Sjkim
309228110Sjkim            /* Copy the Vendor Data */
310228110Sjkim
311228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, Info->Value);
312228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
313228110Sjkim            break;
314228110Sjkim
315228110Sjkim        case ACPI_RSC_MOVE_SERIAL_RES:
316228110Sjkim
317228110Sjkim            /* Generate and set the ResourceSource string pointer */
318228110Sjkim
319228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
320228110Sjkim                  (Resource->Length - ItemCount));
321228110Sjkim            *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
322228110Sjkim
323228110Sjkim            /* Copy the ResourceSource string */
324228110Sjkim
325228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, (ACPI_GET16 (Source) + Info->Value));
326228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
327228110Sjkim            break;
328228110Sjkim
329151937Sjkim        case ACPI_RSC_SET8:
33067754Smsmith
331151937Sjkim            ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value);
332151937Sjkim            break;
33367754Smsmith
334151937Sjkim        case ACPI_RSC_DATA8:
33567754Smsmith
336167802Sjkim            Target = ACPI_ADD_PTR (char, Resource, Info->Value);
337167802Sjkim            ACPI_MEMCPY (Destination, Source,  ACPI_GET16 (Target));
338151937Sjkim            break;
33967754Smsmith
340151937Sjkim        case ACPI_RSC_ADDRESS:
341151937Sjkim            /*
342151937Sjkim             * Common handler for address descriptor flags
343151937Sjkim             */
344151937Sjkim            if (!AcpiRsGetAddressCommon (Resource, Aml))
345151937Sjkim            {
346151937Sjkim                return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
347151937Sjkim            }
348151937Sjkim            break;
34967754Smsmith
350151937Sjkim        case ACPI_RSC_SOURCE:
351151937Sjkim            /*
352151937Sjkim             * Optional ResourceSource (Index and String)
353151937Sjkim             */
354151937Sjkim            Resource->Length +=
355151937Sjkim                AcpiRsGetResourceSource (AmlResourceLength, Info->Value,
356151937Sjkim                    Destination, Aml, NULL);
357151937Sjkim            break;
35867754Smsmith
359151937Sjkim        case ACPI_RSC_SOURCEX:
360151937Sjkim            /*
361151937Sjkim             * Optional ResourceSource (Index and String). This is the more
362151937Sjkim             * complicated case used by the Interrupt() macro
363151937Sjkim             */
364228110Sjkim            Target = ACPI_ADD_PTR (char, Resource,
365228110Sjkim                Info->AmlOffset + (ItemCount * 4));
36667754Smsmith
367151937Sjkim            Resource->Length +=
368228110Sjkim                AcpiRsGetResourceSource (AmlResourceLength, (ACPI_RS_LENGTH)
369228110Sjkim                    (((ItemCount - 1) * sizeof (UINT32)) + Info->Value),
370151937Sjkim                    Destination, Aml, Target);
371151937Sjkim            break;
37267754Smsmith
373151937Sjkim        case ACPI_RSC_BITMASK:
374151937Sjkim            /*
375151937Sjkim             * 8-bit encoded bitmask (DMA macro)
376151937Sjkim             */
377167802Sjkim            ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination);
378151937Sjkim            if (ItemCount)
379151937Sjkim            {
380152069Sjkim                Resource->Length += (ItemCount - 1);
381151937Sjkim            }
38277424Smsmith
383167802Sjkim            Target = ACPI_ADD_PTR (char, Resource, Info->Value);
384243347Sjkim            ACPI_SET8 (Target, ItemCount);
385151937Sjkim            break;
38667754Smsmith
387151937Sjkim        case ACPI_RSC_BITMASK16:
388151937Sjkim            /*
389151937Sjkim             * 16-bit encoded bitmask (IRQ macro)
390151937Sjkim             */
391151937Sjkim            ACPI_MOVE_16_TO_16 (&Temp16, Source);
39267754Smsmith
393151937Sjkim            ItemCount = AcpiRsDecodeBitmask (Temp16, Destination);
394151937Sjkim            if (ItemCount)
395151937Sjkim            {
396152069Sjkim                Resource->Length += (ItemCount - 1);
397151937Sjkim            }
398151937Sjkim
399167802Sjkim            Target = ACPI_ADD_PTR (char, Resource, Info->Value);
400243347Sjkim            ACPI_SET8 (Target, ItemCount);
401151937Sjkim            break;
402151937Sjkim
403151937Sjkim        case ACPI_RSC_EXIT_NE:
404151937Sjkim            /*
405151937Sjkim             * Control - Exit conversion if not equal
406151937Sjkim             */
407151937Sjkim            switch (Info->ResourceOffset)
408151937Sjkim            {
409151937Sjkim            case ACPI_RSC_COMPARE_AML_LENGTH:
410250838Sjkim
411151937Sjkim                if (AmlResourceLength != Info->Value)
412151937Sjkim                {
413151937Sjkim                    goto Exit;
414151937Sjkim                }
415151937Sjkim                break;
416151937Sjkim
417151937Sjkim            case ACPI_RSC_COMPARE_VALUE:
418250838Sjkim
419167802Sjkim                if (ACPI_GET8 (Source) != Info->Value)
420151937Sjkim                {
421151937Sjkim                    goto Exit;
422151937Sjkim                }
423151937Sjkim                break;
424151937Sjkim
425151937Sjkim            default:
426167802Sjkim
427167802Sjkim                ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
428151937Sjkim                return_ACPI_STATUS (AE_BAD_PARAMETER);
429151937Sjkim            }
430151937Sjkim            break;
431151937Sjkim
432151937Sjkim        default:
433151937Sjkim
434167802Sjkim            ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
435151937Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
436151937Sjkim        }
437151937Sjkim
438151937Sjkim        Count--;
439151937Sjkim        Info++;
44067754Smsmith    }
44167754Smsmith
442151937SjkimExit:
443151937Sjkim    if (!FlagsMode)
44467754Smsmith    {
445167802Sjkim        /* Round the resource struct length up to the next boundary (32 or 64) */
44667754Smsmith
447167802Sjkim        Resource->Length = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length);
44867754Smsmith    }
44967754Smsmith    return_ACPI_STATUS (AE_OK);
45067754Smsmith}
45167754Smsmith
45267754Smsmith
45367754Smsmith/*******************************************************************************
45467754Smsmith *
455151937Sjkim * FUNCTION:    AcpiRsConvertResourceToAml
45667754Smsmith *
457151937Sjkim * PARAMETERS:  Resource            - Pointer to the resource descriptor
458151937Sjkim *              Aml                 - Where the AML descriptor is returned
459151937Sjkim *              Info                - Pointer to appropriate conversion table
46067754Smsmith *
46177424Smsmith * RETURN:      Status
46267754Smsmith *
463151937Sjkim * DESCRIPTION: Convert an internal resource descriptor to the corresponding
464151937Sjkim *              external AML resource descriptor.
46567754Smsmith *
46667754Smsmith ******************************************************************************/
46767754Smsmith
46867754SmsmithACPI_STATUS
469151937SjkimAcpiRsConvertResourceToAml (
470151937Sjkim    ACPI_RESOURCE           *Resource,
471151937Sjkim    AML_RESOURCE            *Aml,
472151937Sjkim    ACPI_RSCONVERT_INFO     *Info)
47367754Smsmith{
474151937Sjkim    void                    *Source = NULL;
475151937Sjkim    void                    *Destination;
476228110Sjkim    char                    *Target;
477151937Sjkim    ACPI_RSDESC_SIZE        AmlLength = 0;
478151937Sjkim    UINT8                   Count;
479151937Sjkim    UINT16                  Temp16 = 0;
480151937Sjkim    UINT16                  ItemCount = 0;
48167754Smsmith
48267754Smsmith
483167802Sjkim    ACPI_FUNCTION_TRACE (RsConvertResourceToAml);
48467754Smsmith
48577424Smsmith
486228110Sjkim    if (!Info)
487228110Sjkim    {
488228110Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
489228110Sjkim    }
490228110Sjkim
49167754Smsmith    /*
492151937Sjkim     * First table entry must be ACPI_RSC_INITxxx and must contain the
493151937Sjkim     * table length (# of table entries)
49467754Smsmith     */
495151937Sjkim    Count = INIT_TABLE_LENGTH (Info);
496151937Sjkim
497151937Sjkim    while (Count)
49867754Smsmith    {
49967754Smsmith        /*
500151937Sjkim         * Source is the internal resource descriptor,
501151937Sjkim         * destination is the external AML byte stream buffer
50267754Smsmith         */
503167802Sjkim        Source      = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
504167802Sjkim        Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
50567754Smsmith
506151937Sjkim        switch (Info->Opcode)
50767754Smsmith        {
508151937Sjkim        case ACPI_RSC_INITSET:
50967754Smsmith
510151937Sjkim            ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info));
511151937Sjkim            AmlLength = INIT_RESOURCE_LENGTH (Info);
512151937Sjkim            AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml);
513151937Sjkim            break;
51467754Smsmith
515151937Sjkim        case ACPI_RSC_INITGET:
516151937Sjkim            break;
51767754Smsmith
518151937Sjkim        case ACPI_RSC_FLAGINIT:
519151937Sjkim            /*
520151937Sjkim             * Clear the flag byte
521151937Sjkim             */
522243347Sjkim            ACPI_SET8 (Destination, 0);
523151937Sjkim            break;
52467754Smsmith
525151937Sjkim        case ACPI_RSC_1BITFLAG:
526151937Sjkim            /*
527151937Sjkim             * Mask and shift the flag bit
528151937Sjkim             */
529243347Sjkim            ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
530243347Sjkim                ((ACPI_GET8 (Source) & 0x01) << Info->Value));
531151937Sjkim            break;
53267754Smsmith
533151937Sjkim        case ACPI_RSC_2BITFLAG:
534151937Sjkim            /*
535151937Sjkim             * Mask and shift the flag bits
536151937Sjkim             */
537243347Sjkim            ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
538243347Sjkim                ((ACPI_GET8 (Source) & 0x03) << Info->Value));
539151937Sjkim            break;
54067754Smsmith
541228110Sjkim        case ACPI_RSC_3BITFLAG:
542228110Sjkim            /*
543228110Sjkim             * Mask and shift the flag bits
544228110Sjkim             */
545243347Sjkim            ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
546243347Sjkim                ((ACPI_GET8 (Source) & 0x07) << Info->Value));
547228110Sjkim            break;
548228110Sjkim
549151937Sjkim        case ACPI_RSC_COUNT:
55077424Smsmith
551167802Sjkim            ItemCount = ACPI_GET8 (Source);
552243347Sjkim            ACPI_SET8 (Destination, ItemCount);
55367754Smsmith
554167802Sjkim            AmlLength = (UINT16) (AmlLength + (Info->Value * (ItemCount - 1)));
555151937Sjkim            break;
55667754Smsmith
557151937Sjkim        case ACPI_RSC_COUNT16:
55867754Smsmith
559167802Sjkim            ItemCount = ACPI_GET16 (Source);
560151937Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
561151937Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
562151937Sjkim            break;
56367754Smsmith
564228110Sjkim        case ACPI_RSC_COUNT_GPIO_PIN:
565228110Sjkim
566228110Sjkim            ItemCount = ACPI_GET16 (Source);
567243347Sjkim            ACPI_SET16 (Destination, AmlLength);
568228110Sjkim
569228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount * 2);
570228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, Info->Value);
571243347Sjkim            ACPI_SET16 (Target, AmlLength);
572228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
573228110Sjkim            break;
574228110Sjkim
575228110Sjkim        case ACPI_RSC_COUNT_GPIO_VEN:
576228110Sjkim
577228110Sjkim            ItemCount = ACPI_GET16 (Source);
578243347Sjkim            ACPI_SET16 (Destination, ItemCount);
579228110Sjkim
580228110Sjkim            AmlLength = (UINT16) (AmlLength + (Info->Value * ItemCount));
581228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
582228110Sjkim            break;
583228110Sjkim
584228110Sjkim        case ACPI_RSC_COUNT_GPIO_RES:
585228110Sjkim
586228110Sjkim            /* Set resource source string length */
587228110Sjkim
588228110Sjkim            ItemCount = ACPI_GET16 (Source);
589243347Sjkim            ACPI_SET16 (Destination, AmlLength);
590228110Sjkim
591228110Sjkim            /* Compute offset for the Vendor Data */
592228110Sjkim
593228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
594228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, Info->Value);
595228110Sjkim
596228110Sjkim            /* Set vendor offset only if there is vendor data */
597228110Sjkim
598228110Sjkim            if (Resource->Data.Gpio.VendorLength)
599228110Sjkim            {
600243347Sjkim                ACPI_SET16 (Target, AmlLength);
601228110Sjkim            }
602228110Sjkim
603228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
604228110Sjkim            break;
605228110Sjkim
606228110Sjkim        case ACPI_RSC_COUNT_SERIAL_VEN:
607228110Sjkim
608228110Sjkim            ItemCount = ACPI_GET16 (Source);
609243347Sjkim            ACPI_SET16 (Destination, ItemCount + Info->Value);
610228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
611228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
612228110Sjkim            break;
613228110Sjkim
614228110Sjkim        case ACPI_RSC_COUNT_SERIAL_RES:
615228110Sjkim
616228110Sjkim            ItemCount = ACPI_GET16 (Source);
617228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
618228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
619228110Sjkim            break;
620228110Sjkim
621151937Sjkim        case ACPI_RSC_LENGTH:
62267754Smsmith
623151937Sjkim            AcpiRsSetResourceLength (Info->Value, Aml);
624151937Sjkim            break;
62567754Smsmith
626151937Sjkim        case ACPI_RSC_MOVE8:
627151937Sjkim        case ACPI_RSC_MOVE16:
628151937Sjkim        case ACPI_RSC_MOVE32:
629151937Sjkim        case ACPI_RSC_MOVE64:
63077424Smsmith
631151937Sjkim            if (Info->Value)
632151937Sjkim            {
633151937Sjkim                ItemCount = Info->Value;
634151937Sjkim            }
635151937Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
636151937Sjkim            break;
63767754Smsmith
638228110Sjkim        case ACPI_RSC_MOVE_GPIO_PIN:
639228110Sjkim
640228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
641228110Sjkim                  ACPI_GET16 (Destination));
642228110Sjkim            Source = * (UINT16 **) Source;
643228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
644228110Sjkim            break;
645228110Sjkim
646228110Sjkim        case ACPI_RSC_MOVE_GPIO_RES:
647228110Sjkim
648228110Sjkim            /* Used for both ResourceSource string and VendorData */
649228110Sjkim
650228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
651228110Sjkim                  ACPI_GET16 (Destination));
652228110Sjkim            Source = * (UINT8 **) Source;
653228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
654228110Sjkim            break;
655228110Sjkim
656228110Sjkim        case ACPI_RSC_MOVE_SERIAL_VEN:
657228110Sjkim
658228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
659228110Sjkim                  (AmlLength - ItemCount));
660228110Sjkim            Source = * (UINT8 **) Source;
661228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
662228110Sjkim            break;
663228110Sjkim
664228110Sjkim        case ACPI_RSC_MOVE_SERIAL_RES:
665228110Sjkim
666228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
667228110Sjkim                  (AmlLength - ItemCount));
668228110Sjkim            Source = * (UINT8 **) Source;
669228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
670228110Sjkim            break;
671228110Sjkim
672151937Sjkim        case ACPI_RSC_ADDRESS:
67367754Smsmith
674151937Sjkim            /* Set the Resource Type, General Flags, and Type-Specific Flags */
67567754Smsmith
676151937Sjkim            AcpiRsSetAddressCommon (Aml, Resource);
677151937Sjkim            break;
67867754Smsmith
679151937Sjkim        case ACPI_RSC_SOURCEX:
680151937Sjkim            /*
681151937Sjkim             * Optional ResourceSource (Index and String)
682151937Sjkim             */
683151937Sjkim            AmlLength = AcpiRsSetResourceSource (
684151937Sjkim                            Aml, (ACPI_RS_LENGTH) AmlLength, Source);
685151937Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
686151937Sjkim            break;
68767754Smsmith
688151937Sjkim        case ACPI_RSC_SOURCE:
689151937Sjkim            /*
690151937Sjkim             * Optional ResourceSource (Index and String). This is the more
691151937Sjkim             * complicated case used by the Interrupt() macro
692151937Sjkim             */
693151937Sjkim            AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source);
694151937Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
695151937Sjkim            break;
69667754Smsmith
697151937Sjkim        case ACPI_RSC_BITMASK:
698151937Sjkim            /*
699151937Sjkim             * 8-bit encoded bitmask (DMA macro)
700151937Sjkim             */
701243347Sjkim            ACPI_SET8 (Destination,
702167802Sjkim                AcpiRsEncodeBitmask (Source,
703243347Sjkim                    *ACPI_ADD_PTR (UINT8, Resource, Info->Value)));
704151937Sjkim            break;
70567754Smsmith
706151937Sjkim        case ACPI_RSC_BITMASK16:
707151937Sjkim            /*
708151937Sjkim             * 16-bit encoded bitmask (IRQ macro)
709151937Sjkim             */
710167802Sjkim            Temp16 = AcpiRsEncodeBitmask (Source,
711167802Sjkim                        *ACPI_ADD_PTR (UINT8, Resource, Info->Value));
712151937Sjkim            ACPI_MOVE_16_TO_16 (Destination, &Temp16);
713151937Sjkim            break;
714151937Sjkim
715151937Sjkim        case ACPI_RSC_EXIT_LE:
716151937Sjkim            /*
717151937Sjkim             * Control - Exit conversion if less than or equal
718151937Sjkim             */
719151937Sjkim            if (ItemCount <= Info->Value)
720151937Sjkim            {
721151937Sjkim                goto Exit;
722151937Sjkim            }
723151937Sjkim            break;
724151937Sjkim
725151937Sjkim        case ACPI_RSC_EXIT_NE:
726151937Sjkim            /*
727151937Sjkim             * Control - Exit conversion if not equal
728151937Sjkim             */
729151937Sjkim            switch (COMPARE_OPCODE (Info))
730151937Sjkim            {
731151937Sjkim            case ACPI_RSC_COMPARE_VALUE:
732167802Sjkim
733167802Sjkim                if (*ACPI_ADD_PTR (UINT8, Resource,
734167802Sjkim                        COMPARE_TARGET (Info)) != COMPARE_VALUE (Info))
735151937Sjkim                {
736151937Sjkim                    goto Exit;
737151937Sjkim                }
738151937Sjkim                break;
739151937Sjkim
740151937Sjkim            default:
741167802Sjkim
742167802Sjkim                ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
743151937Sjkim                return_ACPI_STATUS (AE_BAD_PARAMETER);
744151937Sjkim            }
745151937Sjkim            break;
746151937Sjkim
747193267Sjkim        case ACPI_RSC_EXIT_EQ:
748193267Sjkim            /*
749193267Sjkim             * Control - Exit conversion if equal
750193267Sjkim             */
751193267Sjkim            if (*ACPI_ADD_PTR (UINT8, Resource,
752193267Sjkim                    COMPARE_TARGET (Info)) == COMPARE_VALUE (Info))
753193267Sjkim            {
754193267Sjkim                goto Exit;
755193267Sjkim            }
756193267Sjkim            break;
757193267Sjkim
758151937Sjkim        default:
759151937Sjkim
760167802Sjkim            ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
761151937Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
762151937Sjkim        }
763151937Sjkim
764151937Sjkim        Count--;
765151937Sjkim        Info++;
766151937Sjkim    }
767151937Sjkim
768151937SjkimExit:
76967754Smsmith    return_ACPI_STATUS (AE_OK);
77067754Smsmith}
77167754Smsmith
772151937Sjkim
773151937Sjkim#if 0
774151937Sjkim/* Previous resource validations */
775151937Sjkim
776151937Sjkim    if (Aml->ExtAddress64.RevisionID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION)
777151937Sjkim    {
778151937Sjkim        return_ACPI_STATUS (AE_SUPPORT);
779151937Sjkim    }
780151937Sjkim
781151937Sjkim    if (Resource->Data.StartDpf.PerformanceRobustness >= 3)
782151937Sjkim    {
783151937Sjkim        return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
784151937Sjkim    }
785151937Sjkim
786151937Sjkim    if (((Aml->Irq.Flags & 0x09) == 0x00) ||
787151937Sjkim        ((Aml->Irq.Flags & 0x09) == 0x09))
788151937Sjkim    {
789151937Sjkim        /*
790151937Sjkim         * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive]
791151937Sjkim         * polarity/trigger interrupts are allowed (ACPI spec, section
792151937Sjkim         * "IRQ Format"), so 0x00 and 0x09 are illegal.
793151937Sjkim         */
794167802Sjkim        ACPI_ERROR ((AE_INFO,
795204773Sjkim            "Invalid interrupt polarity/trigger in resource list, 0x%X",
796151937Sjkim            Aml->Irq.Flags));
797151937Sjkim        return_ACPI_STATUS (AE_BAD_DATA);
798151937Sjkim    }
799151937Sjkim
800151937Sjkim    Resource->Data.ExtendedIrq.InterruptCount = Temp8;
801151937Sjkim    if (Temp8 < 1)
802151937Sjkim    {
803151937Sjkim        /* Must have at least one IRQ */
804151937Sjkim
805151937Sjkim        return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
806151937Sjkim    }
807151937Sjkim
808151937Sjkim    if (Resource->Data.Dma.Transfer == 0x03)
809151937Sjkim    {
810167802Sjkim        ACPI_ERROR ((AE_INFO,
811167802Sjkim            "Invalid DMA.Transfer preference (3)"));
812151937Sjkim        return_ACPI_STATUS (AE_BAD_DATA);
813151937Sjkim    }
814151937Sjkim#endif
815