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