aslrestype1i.c revision 245582
1/******************************************************************************
2 *
3 * Module Name: aslrestype1i - Small I/O-related resource descriptors
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <contrib/dev/acpica/compiler/aslcompiler.h>
46#include "aslcompiler.y.h"
47
48#define _COMPONENT          ACPI_COMPILER
49        ACPI_MODULE_NAME    ("aslrestype1i")
50
51/*
52 * This module contains the I/O-related small resource descriptors:
53 *
54 * DMA
55 * FixedDMA
56 * FixedIO
57 * IO
58 * IRQ
59 * IRQNoFlags
60 */
61
62/*******************************************************************************
63 *
64 * FUNCTION:    RsDoDmaDescriptor
65 *
66 * PARAMETERS:  Op                  - Parent resource descriptor parse node
67 *              CurrentByteOffset   - Offset into the resource template AML
68 *                                    buffer (to track references to the desc)
69 *
70 * RETURN:      Completed resource node
71 *
72 * DESCRIPTION: Construct a short "DMA" descriptor
73 *
74 ******************************************************************************/
75
76ASL_RESOURCE_NODE *
77RsDoDmaDescriptor (
78    ACPI_PARSE_OBJECT       *Op,
79    UINT32                  CurrentByteOffset)
80{
81    AML_RESOURCE            *Descriptor;
82    ACPI_PARSE_OBJECT       *InitializerOp;
83    ASL_RESOURCE_NODE       *Rnode;
84    UINT32                  i;
85    UINT8                   DmaChannelMask = 0;
86    UINT8                   DmaChannels = 0;
87
88
89    InitializerOp = Op->Asl.Child;
90    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA));
91
92    Descriptor = Rnode->Buffer;
93    Descriptor->Dma.DescriptorType  = ACPI_RESOURCE_NAME_DMA |
94                                        ASL_RDESC_DMA_SIZE;
95
96    /* Process all child initialization nodes */
97
98    for (i = 0; InitializerOp; i++)
99    {
100        switch (i)
101        {
102        case 0: /* DMA type */
103
104            RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0);
105            RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_DMATYPE,
106                CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5, 2);
107            break;
108
109        case 1: /* Bus Master */
110
111            RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0);
112            RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER,
113                CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2);
114            break;
115
116        case 2: /* Xfer Type (transfer width) */
117
118            RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0);
119            RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_XFERTYPE,
120                CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0, 2);
121            break;
122
123        case 3: /* Name */
124
125            UtAttachNamepathToOwner (Op, InitializerOp);
126            break;
127
128        default:
129
130            /* All DMA channel bytes are handled here, after flags and name */
131
132            if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
133            {
134                /* Up to 8 channels can be specified in the list */
135
136                DmaChannels++;
137                if (DmaChannels > 8)
138                {
139                    AslError (ASL_ERROR, ASL_MSG_DMA_LIST,
140                        InitializerOp, NULL);
141                    return (Rnode);
142                }
143
144                /* Only DMA channels 0-7 are allowed (mask is 8 bits) */
145
146                if (InitializerOp->Asl.Value.Integer > 7)
147                {
148                    AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL,
149                        InitializerOp, NULL);
150                }
151
152                /* Build the mask */
153
154                DmaChannelMask |=
155                    (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
156            }
157
158            if (i == 4) /* case 4: First DMA byte */
159            {
160                /* Check now for duplicates in list */
161
162                RsCheckListForDuplicates (InitializerOp);
163
164                /* Create a named field at the start of the list */
165
166                RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA,
167                    CurrentByteOffset +
168                    ASL_RESDESC_OFFSET (Dma.DmaChannelMask));
169            }
170            break;
171        }
172
173        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
174    }
175
176    /* Now we can set the channel mask */
177
178    Descriptor->Dma.DmaChannelMask = DmaChannelMask;
179    return (Rnode);
180}
181
182
183/*******************************************************************************
184 *
185 * FUNCTION:    RsDoFixedDmaDescriptor
186 *
187 * PARAMETERS:  Op                  - Parent resource descriptor parse node
188 *              CurrentByteOffset   - Offset into the resource template AML
189 *                                    buffer (to track references to the desc)
190 *
191 * RETURN:      Completed resource node
192 *
193 * DESCRIPTION: Construct a short "FixedDMA" descriptor
194 *
195 ******************************************************************************/
196
197ASL_RESOURCE_NODE *
198RsDoFixedDmaDescriptor (
199    ACPI_PARSE_OBJECT       *Op,
200    UINT32                  CurrentByteOffset)
201{
202    AML_RESOURCE            *Descriptor;
203    ACPI_PARSE_OBJECT       *InitializerOp;
204    ASL_RESOURCE_NODE       *Rnode;
205    UINT32                  i;
206
207
208    InitializerOp = Op->Asl.Child;
209    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_DMA));
210
211    Descriptor = Rnode->Buffer;
212    Descriptor->FixedDma.DescriptorType =
213        ACPI_RESOURCE_NAME_FIXED_DMA | ASL_RDESC_FIXED_DMA_SIZE;
214
215    /* Process all child initialization nodes */
216
217    for (i = 0; InitializerOp; i++)
218    {
219        switch (i)
220        {
221        case 0: /* DMA Request Lines [WORD] (_DMA) */
222
223            Descriptor->FixedDma.RequestLines = (UINT16) InitializerOp->Asl.Value.Integer;
224            RsCreateWordField (InitializerOp, ACPI_RESTAG_DMA,
225                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.RequestLines));
226            break;
227
228        case 1: /* DMA Channel [WORD] (_TYP) */
229
230            Descriptor->FixedDma.Channels = (UINT16) InitializerOp->Asl.Value.Integer;
231            RsCreateWordField (InitializerOp, ACPI_RESTAG_DMATYPE,
232                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.Channels));
233            break;
234
235        case 2: /* Transfer Width [BYTE] (_SIZ) */
236
237            Descriptor->FixedDma.Width = (UINT8) InitializerOp->Asl.Value.Integer;
238            RsCreateByteField (InitializerOp, ACPI_RESTAG_XFERTYPE,
239                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.Width));
240            break;
241
242        case 3: /* Descriptor Name (optional) */
243
244            UtAttachNamepathToOwner (Op, InitializerOp);
245            break;
246
247        default:    /* Ignore any extra nodes */
248            break;
249        }
250
251        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
252    }
253
254    return (Rnode);
255}
256
257
258/*******************************************************************************
259 *
260 * FUNCTION:    RsDoFixedIoDescriptor
261 *
262 * PARAMETERS:  Op                  - Parent resource descriptor parse node
263 *              CurrentByteOffset   - Offset into the resource template AML
264 *                                    buffer (to track references to the desc)
265 *
266 * RETURN:      Completed resource node
267 *
268 * DESCRIPTION: Construct a short "FixedIO" descriptor
269 *
270 ******************************************************************************/
271
272ASL_RESOURCE_NODE *
273RsDoFixedIoDescriptor (
274    ACPI_PARSE_OBJECT       *Op,
275    UINT32                  CurrentByteOffset)
276{
277    AML_RESOURCE            *Descriptor;
278    ACPI_PARSE_OBJECT       *InitializerOp;
279    ACPI_PARSE_OBJECT       *AddressOp = NULL;
280    ASL_RESOURCE_NODE       *Rnode;
281    UINT32                  i;
282
283
284    InitializerOp = Op->Asl.Child;
285    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO));
286
287    Descriptor = Rnode->Buffer;
288    Descriptor->Io.DescriptorType  = ACPI_RESOURCE_NAME_FIXED_IO |
289                                      ASL_RDESC_FIXED_IO_SIZE;
290
291    /* Process all child initialization nodes */
292
293    for (i = 0; InitializerOp; i++)
294    {
295        switch (i)
296        {
297        case 0: /* Base Address */
298
299            Descriptor->FixedIo.Address =
300                (UINT16) InitializerOp->Asl.Value.Integer;
301            RsCreateWordField (InitializerOp, ACPI_RESTAG_BASEADDRESS,
302                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address));
303            AddressOp = InitializerOp;
304            break;
305
306        case 1: /* Length */
307
308            Descriptor->FixedIo.AddressLength =
309                (UINT8) InitializerOp->Asl.Value.Integer;
310            RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
311                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength));
312            break;
313
314        case 2: /* Name */
315
316            UtAttachNamepathToOwner (Op, InitializerOp);
317            break;
318
319        default:
320
321            AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
322            break;
323        }
324
325        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
326    }
327
328    /* Error checks */
329
330    if (Descriptor->FixedIo.Address > 0x03FF)
331    {
332        AslError (ASL_WARNING, ASL_MSG_ISA_ADDRESS, AddressOp, NULL);
333    }
334
335    return (Rnode);
336}
337
338
339/*******************************************************************************
340 *
341 * FUNCTION:    RsDoIoDescriptor
342 *
343 * PARAMETERS:  Op                  - Parent resource descriptor parse node
344 *              CurrentByteOffset   - Offset into the resource template AML
345 *                                    buffer (to track references to the desc)
346 *
347 * RETURN:      Completed resource node
348 *
349 * DESCRIPTION: Construct a short "IO" descriptor
350 *
351 ******************************************************************************/
352
353ASL_RESOURCE_NODE *
354RsDoIoDescriptor (
355    ACPI_PARSE_OBJECT       *Op,
356    UINT32                  CurrentByteOffset)
357{
358    AML_RESOURCE            *Descriptor;
359    ACPI_PARSE_OBJECT       *InitializerOp;
360    ACPI_PARSE_OBJECT       *MinOp = NULL;
361    ACPI_PARSE_OBJECT       *MaxOp = NULL;
362    ACPI_PARSE_OBJECT       *LengthOp = NULL;
363    ACPI_PARSE_OBJECT       *AlignOp = NULL;
364    ASL_RESOURCE_NODE       *Rnode;
365    UINT32                  i;
366
367
368    InitializerOp = Op->Asl.Child;
369    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO));
370
371    Descriptor = Rnode->Buffer;
372    Descriptor->Io.DescriptorType  = ACPI_RESOURCE_NAME_IO |
373                                      ASL_RDESC_IO_SIZE;
374
375    /* Process all child initialization nodes */
376
377    for (i = 0; InitializerOp; i++)
378    {
379        switch (i)
380        {
381        case 0: /* Decode size */
382
383            RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1);
384            RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
385                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0);
386            break;
387
388        case 1:  /* Min Address */
389
390            Descriptor->Io.Minimum =
391                (UINT16) InitializerOp->Asl.Value.Integer;
392            RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR,
393                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum));
394            MinOp = InitializerOp;
395            break;
396
397        case 2: /* Max Address */
398
399            Descriptor->Io.Maximum =
400                (UINT16) InitializerOp->Asl.Value.Integer;
401            RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR,
402                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum));
403            MaxOp = InitializerOp;
404            break;
405
406        case 3: /* Alignment */
407
408            Descriptor->Io.Alignment =
409                (UINT8) InitializerOp->Asl.Value.Integer;
410            RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
411                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment));
412            AlignOp = InitializerOp;
413            break;
414
415        case 4: /* Length */
416
417            Descriptor->Io.AddressLength =
418                (UINT8) InitializerOp->Asl.Value.Integer;
419            RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
420                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength));
421            LengthOp = InitializerOp;
422            break;
423
424        case 5: /* Name */
425
426            UtAttachNamepathToOwner (Op, InitializerOp);
427            break;
428
429        default:
430
431            AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
432            break;
433        }
434
435        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
436    }
437
438    /* Validate the Min/Max/Len/Align values */
439
440    RsSmallAddressCheck (ACPI_RESOURCE_NAME_IO,
441        Descriptor->Io.Minimum,
442        Descriptor->Io.Maximum,
443        Descriptor->Io.AddressLength,
444        Descriptor->Io.Alignment,
445        MinOp, MaxOp, LengthOp, AlignOp, Op);
446
447    return (Rnode);
448}
449
450
451/*******************************************************************************
452 *
453 * FUNCTION:    RsDoIrqDescriptor
454 *
455 * PARAMETERS:  Op                  - Parent resource descriptor parse node
456 *              CurrentByteOffset   - Offset into the resource template AML
457 *                                    buffer (to track references to the desc)
458 *
459 * RETURN:      Completed resource node
460 *
461 * DESCRIPTION: Construct a short "IRQ" descriptor
462 *
463 ******************************************************************************/
464
465ASL_RESOURCE_NODE *
466RsDoIrqDescriptor (
467    ACPI_PARSE_OBJECT       *Op,
468    UINT32                  CurrentByteOffset)
469{
470    AML_RESOURCE            *Descriptor;
471    ACPI_PARSE_OBJECT       *InitializerOp;
472    ASL_RESOURCE_NODE       *Rnode;
473    UINT32                  Interrupts = 0;
474    UINT16                  IrqMask = 0;
475    UINT32                  i;
476
477
478    InitializerOp = Op->Asl.Child;
479    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ));
480
481    /* Length = 3 (with flag byte) */
482
483    Descriptor = Rnode->Buffer;
484    Descriptor->Irq.DescriptorType  = ACPI_RESOURCE_NAME_IRQ |
485                                      (ASL_RDESC_IRQ_SIZE + 0x01);
486
487    /* Process all child initialization nodes */
488
489    for (i = 0; InitializerOp; i++)
490    {
491        switch (i)
492        {
493        case 0: /* Interrupt Type (or Mode - edge/level) */
494
495            RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1);
496            RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
497                CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0);
498            break;
499
500        case 1: /* Interrupt Level (or Polarity - Active high/low) */
501
502            RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0);
503            RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
504                CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3);
505            break;
506
507        case 2: /* Share Type - Default: exclusive (0) */
508
509            RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0);
510            RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
511                CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4);
512            break;
513
514        case 3: /* Name */
515
516            UtAttachNamepathToOwner (Op, InitializerOp);
517            break;
518
519        default:
520
521            /* All IRQ bytes are handled here, after the flags and name */
522
523            if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
524            {
525                /* Up to 16 interrupts can be specified in the list */
526
527                Interrupts++;
528                if (Interrupts > 16)
529                {
530                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
531                        InitializerOp, NULL);
532                    return (Rnode);
533                }
534
535                /* Only interrupts 0-15 are allowed (mask is 16 bits) */
536
537                if (InitializerOp->Asl.Value.Integer > 15)
538                {
539                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
540                        InitializerOp, NULL);
541                }
542                else
543                {
544                    IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer);
545                }
546            }
547
548            /* Case 4: First IRQ value in list */
549
550            if (i == 4)
551            {
552                /* Check now for duplicates in list */
553
554                RsCheckListForDuplicates (InitializerOp);
555
556                /* Create a named field at the start of the list */
557
558                RsCreateWordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
559                    CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
560            }
561            break;
562        }
563
564        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
565    }
566
567    /* Now we can set the channel mask */
568
569    Descriptor->Irq.IrqMask = IrqMask;
570    return (Rnode);
571}
572
573
574/*******************************************************************************
575 *
576 * FUNCTION:    RsDoIrqNoFlagsDescriptor
577 *
578 * PARAMETERS:  Op                  - Parent resource descriptor parse node
579 *              CurrentByteOffset   - Offset into the resource template AML
580 *                                    buffer (to track references to the desc)
581 *
582 * RETURN:      Completed resource node
583 *
584 * DESCRIPTION: Construct a short "IRQNoFlags" descriptor
585 *
586 ******************************************************************************/
587
588ASL_RESOURCE_NODE *
589RsDoIrqNoFlagsDescriptor (
590    ACPI_PARSE_OBJECT       *Op,
591    UINT32                  CurrentByteOffset)
592{
593    AML_RESOURCE            *Descriptor;
594    ACPI_PARSE_OBJECT       *InitializerOp;
595    ASL_RESOURCE_NODE       *Rnode;
596    UINT16                  IrqMask = 0;
597    UINT32                  Interrupts = 0;
598    UINT32                  i;
599
600
601    InitializerOp = Op->Asl.Child;
602    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS));
603
604    Descriptor = Rnode->Buffer;
605    Descriptor->Irq.DescriptorType  = ACPI_RESOURCE_NAME_IRQ |
606                                      ASL_RDESC_IRQ_SIZE;
607
608    /* Process all child initialization nodes */
609
610    for (i = 0; InitializerOp; i++)
611    {
612        switch (i)
613        {
614        case 0: /* Name */
615
616            UtAttachNamepathToOwner (Op, InitializerOp);
617            break;
618
619        default:
620
621            /* IRQ bytes are handled here, after the flags and name */
622
623            if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
624            {
625                /* Up to 16 interrupts can be specified in the list */
626
627                Interrupts++;
628                if (Interrupts > 16)
629                {
630                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
631                        InitializerOp, NULL);
632                    return (Rnode);
633                }
634
635                /* Only interrupts 0-15 are allowed (mask is 16 bits) */
636
637                if (InitializerOp->Asl.Value.Integer > 15)
638                {
639                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
640                        InitializerOp, NULL);
641                }
642                else
643                {
644                    IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
645                }
646            }
647
648            /* Case 1: First IRQ value in list */
649
650            if (i == 1)
651            {
652                /* Check now for duplicates in list */
653
654                RsCheckListForDuplicates (InitializerOp);
655
656                /* Create a named field at the start of the list */
657
658                RsCreateWordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
659                    CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
660            }
661            break;
662        }
663
664        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
665    }
666
667    /* Now we can set the interrupt mask */
668
669    Descriptor->Irq.IrqMask = IrqMask;
670    return (Rnode);
671}
672