rsmisc.c revision 243347
167754Smsmith/*******************************************************************************
267754Smsmith *
377424Smsmith * Module Name: rsmisc - Miscellaneous resource descriptors
467754Smsmith *
567754Smsmith ******************************************************************************/
667754Smsmith
7217365Sjkim/*
8229989Sjkim * Copyright (C) 2000 - 2012, 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
14067754Smsmith
141151937Sjkim        case ACPI_RSC_INITSET:
142151937Sjkim            break;
14367754Smsmith
14467754Smsmith
145151937Sjkim        case ACPI_RSC_FLAGINIT:
14677424Smsmith
147151937Sjkim            FlagsMode = TRUE;
148151937Sjkim            break;
14967754Smsmith
15067754Smsmith
151151937Sjkim        case ACPI_RSC_1BITFLAG:
152151937Sjkim            /*
153151937Sjkim             * Mask and shift the flag bit
154151937Sjkim             */
155243347Sjkim            ACPI_SET8 (Destination,
156243347Sjkim                ((ACPI_GET8 (Source) >> Info->Value) & 0x01));
157151937Sjkim            break;
15867754Smsmith
15967754Smsmith
160151937Sjkim        case ACPI_RSC_2BITFLAG:
161151937Sjkim            /*
162151937Sjkim             * Mask and shift the flag bits
163151937Sjkim             */
164243347Sjkim            ACPI_SET8 (Destination,
165243347Sjkim                ((ACPI_GET8 (Source) >> Info->Value) & 0x03));
166151937Sjkim            break;
16767754Smsmith
16867754Smsmith
169228110Sjkim        case ACPI_RSC_3BITFLAG:
170228110Sjkim            /*
171228110Sjkim             * Mask and shift the flag bits
172228110Sjkim             */
173243347Sjkim            ACPI_SET8 (Destination,
174243347Sjkim                ((ACPI_GET8 (Source) >> Info->Value) & 0x07));
175228110Sjkim            break;
176228110Sjkim
177228110Sjkim
178151937Sjkim        case ACPI_RSC_COUNT:
17967754Smsmith
180167802Sjkim            ItemCount = ACPI_GET8 (Source);
181243347Sjkim            ACPI_SET8 (Destination, ItemCount);
18267754Smsmith
183151937Sjkim            Resource->Length = Resource->Length +
184151937Sjkim                (Info->Value * (ItemCount - 1));
185151937Sjkim            break;
18667754Smsmith
18777424Smsmith
188151937Sjkim        case ACPI_RSC_COUNT16:
18967754Smsmith
190151937Sjkim            ItemCount = AmlResourceLength;
191243347Sjkim            ACPI_SET16 (Destination, ItemCount);
19267754Smsmith
193151937Sjkim            Resource->Length = Resource->Length +
194151937Sjkim                (Info->Value * (ItemCount - 1));
195151937Sjkim            break;
19667754Smsmith
19767754Smsmith
198228110Sjkim        case ACPI_RSC_COUNT_GPIO_PIN:
199228110Sjkim
200228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, Info->Value);
201228110Sjkim            ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
202228110Sjkim
203228110Sjkim            Resource->Length = Resource->Length + ItemCount;
204228110Sjkim            ItemCount = ItemCount / 2;
205243347Sjkim            ACPI_SET16 (Destination, ItemCount);
206228110Sjkim            break;
207228110Sjkim
208228110Sjkim
209228110Sjkim        case ACPI_RSC_COUNT_GPIO_VEN:
210228110Sjkim
211228110Sjkim            ItemCount = ACPI_GET8 (Source);
212243347Sjkim            ACPI_SET8 (Destination, ItemCount);
213228110Sjkim
214228110Sjkim            Resource->Length = Resource->Length +
215228110Sjkim                (Info->Value * ItemCount);
216228110Sjkim            break;
217228110Sjkim
218228110Sjkim
219228110Sjkim        case ACPI_RSC_COUNT_GPIO_RES:
220228110Sjkim
221228110Sjkim            /*
222228110Sjkim             * Vendor data is optional (length/offset may both be zero)
223228110Sjkim             * Examine vendor data length field first
224228110Sjkim             */
225228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, (Info->Value + 2));
226228110Sjkim            if (ACPI_GET16 (Target))
227228110Sjkim            {
228228110Sjkim                /* Use vendor offset to get resource source length */
229228110Sjkim
230228110Sjkim                Target = ACPI_ADD_PTR (void, Aml, Info->Value);
231228110Sjkim                ItemCount = ACPI_GET16 (Target) - ACPI_GET16 (Source);
232228110Sjkim            }
233228110Sjkim            else
234228110Sjkim            {
235228110Sjkim                /* No vendor data to worry about */
236228110Sjkim
237228110Sjkim                ItemCount = Aml->LargeHeader.ResourceLength +
238228110Sjkim                    sizeof (AML_RESOURCE_LARGE_HEADER) -
239228110Sjkim                    ACPI_GET16 (Source);
240228110Sjkim            }
241228110Sjkim
242228110Sjkim            Resource->Length = Resource->Length + ItemCount;
243243347Sjkim            ACPI_SET16 (Destination, ItemCount);
244228110Sjkim            break;
245228110Sjkim
246228110Sjkim
247228110Sjkim        case ACPI_RSC_COUNT_SERIAL_VEN:
248228110Sjkim
249228110Sjkim            ItemCount = ACPI_GET16 (Source) - Info->Value;
250228110Sjkim
251228110Sjkim            Resource->Length = Resource->Length + ItemCount;
252243347Sjkim            ACPI_SET16 (Destination, ItemCount);
253228110Sjkim            break;
254228110Sjkim
255228110Sjkim
256228110Sjkim        case ACPI_RSC_COUNT_SERIAL_RES:
257228110Sjkim
258228110Sjkim            ItemCount = (AmlResourceLength +
259228110Sjkim                sizeof (AML_RESOURCE_LARGE_HEADER)) -
260228110Sjkim                ACPI_GET16 (Source) - Info->Value;
261228110Sjkim
262228110Sjkim            Resource->Length = Resource->Length + ItemCount;
263243347Sjkim            ACPI_SET16 (Destination, ItemCount);
264228110Sjkim            break;
265228110Sjkim
266228110Sjkim
267151937Sjkim        case ACPI_RSC_LENGTH:
26867754Smsmith
269151937Sjkim            Resource->Length = Resource->Length + Info->Value;
270151937Sjkim            break;
27167754Smsmith
27267754Smsmith
273151937Sjkim        case ACPI_RSC_MOVE8:
274151937Sjkim        case ACPI_RSC_MOVE16:
275151937Sjkim        case ACPI_RSC_MOVE32:
276151937Sjkim        case ACPI_RSC_MOVE64:
277151937Sjkim            /*
278151937Sjkim             * Raw data move. Use the Info value field unless ItemCount has
279151937Sjkim             * been previously initialized via a COUNT opcode
280151937Sjkim             */
281151937Sjkim            if (Info->Value)
282151937Sjkim            {
283151937Sjkim                ItemCount = Info->Value;
284151937Sjkim            }
285167802Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
286151937Sjkim            break;
28767754Smsmith
28867754Smsmith
289228110Sjkim        case ACPI_RSC_MOVE_GPIO_PIN:
290228110Sjkim
291228110Sjkim            /* Generate and set the PIN data pointer */
292228110Sjkim
293228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
294228110Sjkim                  (Resource->Length - ItemCount * 2));
295228110Sjkim            *(UINT16 **) Destination = ACPI_CAST_PTR (UINT16, Target);
296228110Sjkim
297228110Sjkim            /* Copy the PIN data */
298228110Sjkim
299228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
300228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
301228110Sjkim            break;
302228110Sjkim
303228110Sjkim
304228110Sjkim        case ACPI_RSC_MOVE_GPIO_RES:
305228110Sjkim
306228110Sjkim            /* Generate and set the ResourceSource string pointer */
307228110Sjkim
308228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
309228110Sjkim                  (Resource->Length - ItemCount));
310228110Sjkim            *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
311228110Sjkim
312228110Sjkim            /* Copy the ResourceSource string */
313228110Sjkim
314228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, ACPI_GET16 (Source));
315228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
316228110Sjkim            break;
317228110Sjkim
318228110Sjkim
319228110Sjkim        case ACPI_RSC_MOVE_SERIAL_VEN:
320228110Sjkim
321228110Sjkim            /* Generate and set the Vendor Data pointer */
322228110Sjkim
323228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
324228110Sjkim                  (Resource->Length - ItemCount));
325228110Sjkim            *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
326228110Sjkim
327228110Sjkim            /* Copy the Vendor Data */
328228110Sjkim
329228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, Info->Value);
330228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
331228110Sjkim            break;
332228110Sjkim
333228110Sjkim
334228110Sjkim        case ACPI_RSC_MOVE_SERIAL_RES:
335228110Sjkim
336228110Sjkim            /* Generate and set the ResourceSource string pointer */
337228110Sjkim
338228110Sjkim            Target = (char *) ACPI_ADD_PTR (void, Resource,
339228110Sjkim                  (Resource->Length - ItemCount));
340228110Sjkim            *(UINT8 **) Destination = ACPI_CAST_PTR (UINT8, Target);
341228110Sjkim
342228110Sjkim            /* Copy the ResourceSource string */
343228110Sjkim
344228110Sjkim            Source = ACPI_ADD_PTR (void, Aml, (ACPI_GET16 (Source) + Info->Value));
345228110Sjkim            AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode);
346228110Sjkim            break;
347228110Sjkim
348228110Sjkim
349151937Sjkim        case ACPI_RSC_SET8:
35067754Smsmith
351151937Sjkim            ACPI_MEMSET (Destination, Info->AmlOffset, Info->Value);
352151937Sjkim            break;
35367754Smsmith
35467754Smsmith
355151937Sjkim        case ACPI_RSC_DATA8:
35667754Smsmith
357167802Sjkim            Target = ACPI_ADD_PTR (char, Resource, Info->Value);
358167802Sjkim            ACPI_MEMCPY (Destination, Source,  ACPI_GET16 (Target));
359151937Sjkim            break;
36067754Smsmith
36167754Smsmith
362151937Sjkim        case ACPI_RSC_ADDRESS:
363151937Sjkim            /*
364151937Sjkim             * Common handler for address descriptor flags
365151937Sjkim             */
366151937Sjkim            if (!AcpiRsGetAddressCommon (Resource, Aml))
367151937Sjkim            {
368151937Sjkim                return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
369151937Sjkim            }
370151937Sjkim            break;
37167754Smsmith
37267754Smsmith
373151937Sjkim        case ACPI_RSC_SOURCE:
374151937Sjkim            /*
375151937Sjkim             * Optional ResourceSource (Index and String)
376151937Sjkim             */
377151937Sjkim            Resource->Length +=
378151937Sjkim                AcpiRsGetResourceSource (AmlResourceLength, Info->Value,
379151937Sjkim                    Destination, Aml, NULL);
380151937Sjkim            break;
38167754Smsmith
38267754Smsmith
383151937Sjkim        case ACPI_RSC_SOURCEX:
384151937Sjkim            /*
385151937Sjkim             * Optional ResourceSource (Index and String). This is the more
386151937Sjkim             * complicated case used by the Interrupt() macro
387151937Sjkim             */
388228110Sjkim            Target = ACPI_ADD_PTR (char, Resource,
389228110Sjkim                Info->AmlOffset + (ItemCount * 4));
39067754Smsmith
391151937Sjkim            Resource->Length +=
392228110Sjkim                AcpiRsGetResourceSource (AmlResourceLength, (ACPI_RS_LENGTH)
393228110Sjkim                    (((ItemCount - 1) * sizeof (UINT32)) + Info->Value),
394151937Sjkim                    Destination, Aml, Target);
395151937Sjkim            break;
39667754Smsmith
39767754Smsmith
398151937Sjkim        case ACPI_RSC_BITMASK:
399151937Sjkim            /*
400151937Sjkim             * 8-bit encoded bitmask (DMA macro)
401151937Sjkim             */
402167802Sjkim            ItemCount = AcpiRsDecodeBitmask (ACPI_GET8 (Source), Destination);
403151937Sjkim            if (ItemCount)
404151937Sjkim            {
405152069Sjkim                Resource->Length += (ItemCount - 1);
406151937Sjkim            }
40777424Smsmith
408167802Sjkim            Target = ACPI_ADD_PTR (char, Resource, Info->Value);
409243347Sjkim            ACPI_SET8 (Target, ItemCount);
410151937Sjkim            break;
41167754Smsmith
41267754Smsmith
413151937Sjkim        case ACPI_RSC_BITMASK16:
414151937Sjkim            /*
415151937Sjkim             * 16-bit encoded bitmask (IRQ macro)
416151937Sjkim             */
417151937Sjkim            ACPI_MOVE_16_TO_16 (&Temp16, Source);
41867754Smsmith
419151937Sjkim            ItemCount = AcpiRsDecodeBitmask (Temp16, Destination);
420151937Sjkim            if (ItemCount)
421151937Sjkim            {
422152069Sjkim                Resource->Length += (ItemCount - 1);
423151937Sjkim            }
424151937Sjkim
425167802Sjkim            Target = ACPI_ADD_PTR (char, Resource, Info->Value);
426243347Sjkim            ACPI_SET8 (Target, ItemCount);
427151937Sjkim            break;
428151937Sjkim
429151937Sjkim
430151937Sjkim        case ACPI_RSC_EXIT_NE:
431151937Sjkim            /*
432151937Sjkim             * Control - Exit conversion if not equal
433151937Sjkim             */
434151937Sjkim            switch (Info->ResourceOffset)
435151937Sjkim            {
436151937Sjkim            case ACPI_RSC_COMPARE_AML_LENGTH:
437151937Sjkim                if (AmlResourceLength != Info->Value)
438151937Sjkim                {
439151937Sjkim                    goto Exit;
440151937Sjkim                }
441151937Sjkim                break;
442151937Sjkim
443151937Sjkim            case ACPI_RSC_COMPARE_VALUE:
444167802Sjkim                if (ACPI_GET8 (Source) != Info->Value)
445151937Sjkim                {
446151937Sjkim                    goto Exit;
447151937Sjkim                }
448151937Sjkim                break;
449151937Sjkim
450151937Sjkim            default:
451167802Sjkim
452167802Sjkim                ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
453151937Sjkim                return_ACPI_STATUS (AE_BAD_PARAMETER);
454151937Sjkim            }
455151937Sjkim            break;
456151937Sjkim
457151937Sjkim
458151937Sjkim        default:
459151937Sjkim
460167802Sjkim            ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
461151937Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
462151937Sjkim        }
463151937Sjkim
464151937Sjkim        Count--;
465151937Sjkim        Info++;
46667754Smsmith    }
46767754Smsmith
468151937SjkimExit:
469151937Sjkim    if (!FlagsMode)
47067754Smsmith    {
471167802Sjkim        /* Round the resource struct length up to the next boundary (32 or 64) */
47267754Smsmith
473167802Sjkim        Resource->Length = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (Resource->Length);
47467754Smsmith    }
47567754Smsmith    return_ACPI_STATUS (AE_OK);
47667754Smsmith}
47767754Smsmith
47867754Smsmith
47967754Smsmith/*******************************************************************************
48067754Smsmith *
481151937Sjkim * FUNCTION:    AcpiRsConvertResourceToAml
48267754Smsmith *
483151937Sjkim * PARAMETERS:  Resource            - Pointer to the resource descriptor
484151937Sjkim *              Aml                 - Where the AML descriptor is returned
485151937Sjkim *              Info                - Pointer to appropriate conversion table
48667754Smsmith *
48777424Smsmith * RETURN:      Status
48867754Smsmith *
489151937Sjkim * DESCRIPTION: Convert an internal resource descriptor to the corresponding
490151937Sjkim *              external AML resource descriptor.
49167754Smsmith *
49267754Smsmith ******************************************************************************/
49367754Smsmith
49467754SmsmithACPI_STATUS
495151937SjkimAcpiRsConvertResourceToAml (
496151937Sjkim    ACPI_RESOURCE           *Resource,
497151937Sjkim    AML_RESOURCE            *Aml,
498151937Sjkim    ACPI_RSCONVERT_INFO     *Info)
49967754Smsmith{
500151937Sjkim    void                    *Source = NULL;
501151937Sjkim    void                    *Destination;
502228110Sjkim    char                    *Target;
503151937Sjkim    ACPI_RSDESC_SIZE        AmlLength = 0;
504151937Sjkim    UINT8                   Count;
505151937Sjkim    UINT16                  Temp16 = 0;
506151937Sjkim    UINT16                  ItemCount = 0;
50767754Smsmith
50867754Smsmith
509167802Sjkim    ACPI_FUNCTION_TRACE (RsConvertResourceToAml);
51067754Smsmith
51177424Smsmith
512228110Sjkim    if (!Info)
513228110Sjkim    {
514228110Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
515228110Sjkim    }
516228110Sjkim
51767754Smsmith    /*
518151937Sjkim     * First table entry must be ACPI_RSC_INITxxx and must contain the
519151937Sjkim     * table length (# of table entries)
52067754Smsmith     */
521151937Sjkim    Count = INIT_TABLE_LENGTH (Info);
522151937Sjkim
523151937Sjkim    while (Count)
52467754Smsmith    {
52567754Smsmith        /*
526151937Sjkim         * Source is the internal resource descriptor,
527151937Sjkim         * destination is the external AML byte stream buffer
52867754Smsmith         */
529167802Sjkim        Source      = ACPI_ADD_PTR (void, Resource, Info->ResourceOffset);
530167802Sjkim        Destination = ACPI_ADD_PTR (void, Aml, Info->AmlOffset);
53167754Smsmith
532151937Sjkim        switch (Info->Opcode)
53367754Smsmith        {
534151937Sjkim        case ACPI_RSC_INITSET:
53567754Smsmith
536151937Sjkim            ACPI_MEMSET (Aml, 0, INIT_RESOURCE_LENGTH (Info));
537151937Sjkim            AmlLength = INIT_RESOURCE_LENGTH (Info);
538151937Sjkim            AcpiRsSetResourceHeader (INIT_RESOURCE_TYPE (Info), AmlLength, Aml);
539151937Sjkim            break;
54067754Smsmith
54167754Smsmith
542151937Sjkim        case ACPI_RSC_INITGET:
543151937Sjkim            break;
54467754Smsmith
54567754Smsmith
546151937Sjkim        case ACPI_RSC_FLAGINIT:
547151937Sjkim            /*
548151937Sjkim             * Clear the flag byte
549151937Sjkim             */
550243347Sjkim            ACPI_SET8 (Destination, 0);
551151937Sjkim            break;
55267754Smsmith
55367754Smsmith
554151937Sjkim        case ACPI_RSC_1BITFLAG:
555151937Sjkim            /*
556151937Sjkim             * Mask and shift the flag bit
557151937Sjkim             */
558243347Sjkim            ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
559243347Sjkim                ((ACPI_GET8 (Source) & 0x01) << Info->Value));
560151937Sjkim            break;
56167754Smsmith
56267754Smsmith
563151937Sjkim        case ACPI_RSC_2BITFLAG:
564151937Sjkim            /*
565151937Sjkim             * Mask and shift the flag bits
566151937Sjkim             */
567243347Sjkim            ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
568243347Sjkim                ((ACPI_GET8 (Source) & 0x03) << Info->Value));
569151937Sjkim            break;
57067754Smsmith
57167754Smsmith
572228110Sjkim        case ACPI_RSC_3BITFLAG:
573228110Sjkim            /*
574228110Sjkim             * Mask and shift the flag bits
575228110Sjkim             */
576243347Sjkim            ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8)
577243347Sjkim                ((ACPI_GET8 (Source) & 0x07) << Info->Value));
578228110Sjkim            break;
579228110Sjkim
580228110Sjkim
581151937Sjkim        case ACPI_RSC_COUNT:
58277424Smsmith
583167802Sjkim            ItemCount = ACPI_GET8 (Source);
584243347Sjkim            ACPI_SET8 (Destination, ItemCount);
58567754Smsmith
586167802Sjkim            AmlLength = (UINT16) (AmlLength + (Info->Value * (ItemCount - 1)));
587151937Sjkim            break;
58867754Smsmith
58967754Smsmith
590151937Sjkim        case ACPI_RSC_COUNT16:
59167754Smsmith
592167802Sjkim            ItemCount = ACPI_GET16 (Source);
593151937Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
594151937Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
595151937Sjkim            break;
59667754Smsmith
59767754Smsmith
598228110Sjkim        case ACPI_RSC_COUNT_GPIO_PIN:
599228110Sjkim
600228110Sjkim            ItemCount = ACPI_GET16 (Source);
601243347Sjkim            ACPI_SET16 (Destination, AmlLength);
602228110Sjkim
603228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount * 2);
604228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, Info->Value);
605243347Sjkim            ACPI_SET16 (Target, AmlLength);
606228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
607228110Sjkim            break;
608228110Sjkim
609228110Sjkim
610228110Sjkim        case ACPI_RSC_COUNT_GPIO_VEN:
611228110Sjkim
612228110Sjkim            ItemCount = ACPI_GET16 (Source);
613243347Sjkim            ACPI_SET16 (Destination, ItemCount);
614228110Sjkim
615228110Sjkim            AmlLength = (UINT16) (AmlLength + (Info->Value * ItemCount));
616228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
617228110Sjkim            break;
618228110Sjkim
619228110Sjkim
620228110Sjkim        case ACPI_RSC_COUNT_GPIO_RES:
621228110Sjkim
622228110Sjkim            /* Set resource source string length */
623228110Sjkim
624228110Sjkim            ItemCount = ACPI_GET16 (Source);
625243347Sjkim            ACPI_SET16 (Destination, AmlLength);
626228110Sjkim
627228110Sjkim            /* Compute offset for the Vendor Data */
628228110Sjkim
629228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
630228110Sjkim            Target = ACPI_ADD_PTR (void, Aml, Info->Value);
631228110Sjkim
632228110Sjkim            /* Set vendor offset only if there is vendor data */
633228110Sjkim
634228110Sjkim            if (Resource->Data.Gpio.VendorLength)
635228110Sjkim            {
636243347Sjkim                ACPI_SET16 (Target, AmlLength);
637228110Sjkim            }
638228110Sjkim
639228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
640228110Sjkim            break;
641228110Sjkim
642228110Sjkim
643228110Sjkim        case ACPI_RSC_COUNT_SERIAL_VEN:
644228110Sjkim
645228110Sjkim            ItemCount = ACPI_GET16 (Source);
646243347Sjkim            ACPI_SET16 (Destination, ItemCount + Info->Value);
647228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
648228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
649228110Sjkim            break;
650228110Sjkim
651228110Sjkim
652228110Sjkim        case ACPI_RSC_COUNT_SERIAL_RES:
653228110Sjkim
654228110Sjkim            ItemCount = ACPI_GET16 (Source);
655228110Sjkim            AmlLength = (UINT16) (AmlLength + ItemCount);
656228110Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
657228110Sjkim            break;
658228110Sjkim
659228110Sjkim
660151937Sjkim        case ACPI_RSC_LENGTH:
66167754Smsmith
662151937Sjkim            AcpiRsSetResourceLength (Info->Value, Aml);
663151937Sjkim            break;
66467754Smsmith
66567754Smsmith
666151937Sjkim        case ACPI_RSC_MOVE8:
667151937Sjkim        case ACPI_RSC_MOVE16:
668151937Sjkim        case ACPI_RSC_MOVE32:
669151937Sjkim        case ACPI_RSC_MOVE64:
67077424Smsmith
671151937Sjkim            if (Info->Value)
672151937Sjkim            {
673151937Sjkim                ItemCount = Info->Value;
674151937Sjkim            }
675151937Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
676151937Sjkim            break;
67767754Smsmith
67867754Smsmith
679228110Sjkim        case ACPI_RSC_MOVE_GPIO_PIN:
680228110Sjkim
681228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
682228110Sjkim                  ACPI_GET16 (Destination));
683228110Sjkim            Source = * (UINT16 **) Source;
684228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
685228110Sjkim            break;
686228110Sjkim
687228110Sjkim
688228110Sjkim        case ACPI_RSC_MOVE_GPIO_RES:
689228110Sjkim
690228110Sjkim            /* Used for both ResourceSource string and VendorData */
691228110Sjkim
692228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
693228110Sjkim                  ACPI_GET16 (Destination));
694228110Sjkim            Source = * (UINT8 **) Source;
695228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
696228110Sjkim            break;
697228110Sjkim
698228110Sjkim
699228110Sjkim        case ACPI_RSC_MOVE_SERIAL_VEN:
700228110Sjkim
701228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
702228110Sjkim                  (AmlLength - ItemCount));
703228110Sjkim            Source = * (UINT8 **) Source;
704228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
705228110Sjkim            break;
706228110Sjkim
707228110Sjkim
708228110Sjkim        case ACPI_RSC_MOVE_SERIAL_RES:
709228110Sjkim
710228110Sjkim            Destination = (char *) ACPI_ADD_PTR (void, Aml,
711228110Sjkim                  (AmlLength - ItemCount));
712228110Sjkim            Source = * (UINT8 **) Source;
713228110Sjkim            AcpiRsMoveData (Destination, Source, ItemCount, Info->Opcode);
714228110Sjkim            break;
715228110Sjkim
716228110Sjkim
717151937Sjkim        case ACPI_RSC_ADDRESS:
71867754Smsmith
719151937Sjkim            /* Set the Resource Type, General Flags, and Type-Specific Flags */
72067754Smsmith
721151937Sjkim            AcpiRsSetAddressCommon (Aml, Resource);
722151937Sjkim            break;
72367754Smsmith
72467754Smsmith
725151937Sjkim        case ACPI_RSC_SOURCEX:
726151937Sjkim            /*
727151937Sjkim             * Optional ResourceSource (Index and String)
728151937Sjkim             */
729151937Sjkim            AmlLength = AcpiRsSetResourceSource (
730151937Sjkim                            Aml, (ACPI_RS_LENGTH) AmlLength, Source);
731151937Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
732151937Sjkim            break;
73367754Smsmith
73467754Smsmith
735151937Sjkim        case ACPI_RSC_SOURCE:
736151937Sjkim            /*
737151937Sjkim             * Optional ResourceSource (Index and String). This is the more
738151937Sjkim             * complicated case used by the Interrupt() macro
739151937Sjkim             */
740151937Sjkim            AmlLength = AcpiRsSetResourceSource (Aml, Info->Value, Source);
741151937Sjkim            AcpiRsSetResourceLength (AmlLength, Aml);
742151937Sjkim            break;
74367754Smsmith
74477424Smsmith
745151937Sjkim        case ACPI_RSC_BITMASK:
746151937Sjkim            /*
747151937Sjkim             * 8-bit encoded bitmask (DMA macro)
748151937Sjkim             */
749243347Sjkim            ACPI_SET8 (Destination,
750167802Sjkim                AcpiRsEncodeBitmask (Source,
751243347Sjkim                    *ACPI_ADD_PTR (UINT8, Resource, Info->Value)));
752151937Sjkim            break;
75367754Smsmith
754151937Sjkim
755151937Sjkim        case ACPI_RSC_BITMASK16:
756151937Sjkim            /*
757151937Sjkim             * 16-bit encoded bitmask (IRQ macro)
758151937Sjkim             */
759167802Sjkim            Temp16 = AcpiRsEncodeBitmask (Source,
760167802Sjkim                        *ACPI_ADD_PTR (UINT8, Resource, Info->Value));
761151937Sjkim            ACPI_MOVE_16_TO_16 (Destination, &Temp16);
762151937Sjkim            break;
763151937Sjkim
764151937Sjkim
765151937Sjkim        case ACPI_RSC_EXIT_LE:
766151937Sjkim            /*
767151937Sjkim             * Control - Exit conversion if less than or equal
768151937Sjkim             */
769151937Sjkim            if (ItemCount <= Info->Value)
770151937Sjkim            {
771151937Sjkim                goto Exit;
772151937Sjkim            }
773151937Sjkim            break;
774151937Sjkim
775151937Sjkim
776151937Sjkim        case ACPI_RSC_EXIT_NE:
777151937Sjkim            /*
778151937Sjkim             * Control - Exit conversion if not equal
779151937Sjkim             */
780151937Sjkim            switch (COMPARE_OPCODE (Info))
781151937Sjkim            {
782151937Sjkim            case ACPI_RSC_COMPARE_VALUE:
783167802Sjkim
784167802Sjkim                if (*ACPI_ADD_PTR (UINT8, Resource,
785167802Sjkim                        COMPARE_TARGET (Info)) != COMPARE_VALUE (Info))
786151937Sjkim                {
787151937Sjkim                    goto Exit;
788151937Sjkim                }
789151937Sjkim                break;
790151937Sjkim
791151937Sjkim            default:
792167802Sjkim
793167802Sjkim                ACPI_ERROR ((AE_INFO, "Invalid conversion sub-opcode"));
794151937Sjkim                return_ACPI_STATUS (AE_BAD_PARAMETER);
795151937Sjkim            }
796151937Sjkim            break;
797151937Sjkim
798151937Sjkim
799193267Sjkim        case ACPI_RSC_EXIT_EQ:
800193267Sjkim            /*
801193267Sjkim             * Control - Exit conversion if equal
802193267Sjkim             */
803193267Sjkim            if (*ACPI_ADD_PTR (UINT8, Resource,
804193267Sjkim                    COMPARE_TARGET (Info)) == COMPARE_VALUE (Info))
805193267Sjkim            {
806193267Sjkim                goto Exit;
807193267Sjkim            }
808193267Sjkim            break;
809193267Sjkim
810193267Sjkim
811151937Sjkim        default:
812151937Sjkim
813167802Sjkim            ACPI_ERROR ((AE_INFO, "Invalid conversion opcode"));
814151937Sjkim            return_ACPI_STATUS (AE_BAD_PARAMETER);
815151937Sjkim        }
816151937Sjkim
817151937Sjkim        Count--;
818151937Sjkim        Info++;
819151937Sjkim    }
820151937Sjkim
821151937SjkimExit:
82267754Smsmith    return_ACPI_STATUS (AE_OK);
82367754Smsmith}
82467754Smsmith
825151937Sjkim
826151937Sjkim#if 0
827151937Sjkim/* Previous resource validations */
828151937Sjkim
829151937Sjkim    if (Aml->ExtAddress64.RevisionID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION)
830151937Sjkim    {
831151937Sjkim        return_ACPI_STATUS (AE_SUPPORT);
832151937Sjkim    }
833151937Sjkim
834151937Sjkim    if (Resource->Data.StartDpf.PerformanceRobustness >= 3)
835151937Sjkim    {
836151937Sjkim        return_ACPI_STATUS (AE_AML_BAD_RESOURCE_VALUE);
837151937Sjkim    }
838151937Sjkim
839151937Sjkim    if (((Aml->Irq.Flags & 0x09) == 0x00) ||
840151937Sjkim        ((Aml->Irq.Flags & 0x09) == 0x09))
841151937Sjkim    {
842151937Sjkim        /*
843151937Sjkim         * Only [ActiveHigh, EdgeSensitive] or [ActiveLow, LevelSensitive]
844151937Sjkim         * polarity/trigger interrupts are allowed (ACPI spec, section
845151937Sjkim         * "IRQ Format"), so 0x00 and 0x09 are illegal.
846151937Sjkim         */
847167802Sjkim        ACPI_ERROR ((AE_INFO,
848204773Sjkim            "Invalid interrupt polarity/trigger in resource list, 0x%X",
849151937Sjkim            Aml->Irq.Flags));
850151937Sjkim        return_ACPI_STATUS (AE_BAD_DATA);
851151937Sjkim    }
852151937Sjkim
853151937Sjkim    Resource->Data.ExtendedIrq.InterruptCount = Temp8;
854151937Sjkim    if (Temp8 < 1)
855151937Sjkim    {
856151937Sjkim        /* Must have at least one IRQ */
857151937Sjkim
858151937Sjkim        return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH);
859151937Sjkim    }
860151937Sjkim
861151937Sjkim    if (Resource->Data.Dma.Transfer == 0x03)
862151937Sjkim    {
863167802Sjkim        ACPI_ERROR ((AE_INFO,
864167802Sjkim            "Invalid DMA.Transfer preference (3)"));
865151937Sjkim        return_ACPI_STATUS (AE_BAD_DATA);
866151937Sjkim    }
867151937Sjkim#endif
868