aslrestype1i.c revision 217365
1
2/******************************************************************************
3 *
4 * Module Name: aslrestype1i - Small I/O-related resource descriptors
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2011, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions, and the following disclaimer,
17 *    without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 *    substantially similar to the "NO WARRANTY" disclaimer below
20 *    ("Disclaimer") and any redistribution must be conditioned upon
21 *    including a substantially similar Disclaimer requirement for further
22 *    binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 *    of any contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <contrib/dev/acpica/compiler/aslcompiler.h>
47#include "aslcompiler.y.h"
48
49#define _COMPONENT          ACPI_COMPILER
50        ACPI_MODULE_NAME    ("aslrestype1i")
51
52/*
53 * This module contains the I/O-related small resource descriptors:
54 *
55 * DMA
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            RsCreateBitField (InitializerOp, ACPI_RESTAG_DMATYPE,
106                CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5);
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            RsCreateBitField (InitializerOp, ACPI_RESTAG_XFERTYPE,
120                CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0);
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:    RsDoFixedIoDescriptor
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 "FixedIO" descriptor
194 *
195 ******************************************************************************/
196
197ASL_RESOURCE_NODE *
198RsDoFixedIoDescriptor (
199    ACPI_PARSE_OBJECT       *Op,
200    UINT32                  CurrentByteOffset)
201{
202    AML_RESOURCE            *Descriptor;
203    ACPI_PARSE_OBJECT       *InitializerOp;
204    ACPI_PARSE_OBJECT       *AddressOp = NULL;
205    ASL_RESOURCE_NODE       *Rnode;
206    UINT32                  i;
207
208
209    InitializerOp = Op->Asl.Child;
210    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO));
211
212    Descriptor = Rnode->Buffer;
213    Descriptor->Io.DescriptorType  = ACPI_RESOURCE_NAME_FIXED_IO |
214                                      ASL_RDESC_FIXED_IO_SIZE;
215
216    /* Process all child initialization nodes */
217
218    for (i = 0; InitializerOp; i++)
219    {
220        switch (i)
221        {
222        case 0: /* Base Address */
223
224            Descriptor->FixedIo.Address =
225                (UINT16) InitializerOp->Asl.Value.Integer;
226            RsCreateByteField (InitializerOp, ACPI_RESTAG_BASEADDRESS,
227                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address));
228            AddressOp = InitializerOp;
229            break;
230
231        case 1: /* Length */
232
233            Descriptor->FixedIo.AddressLength =
234                (UINT8) InitializerOp->Asl.Value.Integer;
235            RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
236                CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength));
237            break;
238
239        case 2: /* Name */
240
241            UtAttachNamepathToOwner (Op, InitializerOp);
242            break;
243
244        default:
245
246            AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
247            break;
248        }
249
250        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
251    }
252
253    /* Error checks */
254
255    if (Descriptor->FixedIo.Address > 0x03FF)
256    {
257        AslError (ASL_WARNING, ASL_MSG_ISA_ADDRESS, AddressOp, NULL);
258    }
259
260    return (Rnode);
261}
262
263
264/*******************************************************************************
265 *
266 * FUNCTION:    RsDoIoDescriptor
267 *
268 * PARAMETERS:  Op                  - Parent resource descriptor parse node
269 *              CurrentByteOffset   - Offset into the resource template AML
270 *                                    buffer (to track references to the desc)
271 *
272 * RETURN:      Completed resource node
273 *
274 * DESCRIPTION: Construct a short "IO" descriptor
275 *
276 ******************************************************************************/
277
278ASL_RESOURCE_NODE *
279RsDoIoDescriptor (
280    ACPI_PARSE_OBJECT       *Op,
281    UINT32                  CurrentByteOffset)
282{
283    AML_RESOURCE            *Descriptor;
284    ACPI_PARSE_OBJECT       *InitializerOp;
285    ACPI_PARSE_OBJECT       *MinOp = NULL;
286    ACPI_PARSE_OBJECT       *MaxOp = NULL;
287    ACPI_PARSE_OBJECT       *LengthOp = NULL;
288    ACPI_PARSE_OBJECT       *AlignOp = NULL;
289    ASL_RESOURCE_NODE       *Rnode;
290    UINT32                  i;
291
292
293    InitializerOp = Op->Asl.Child;
294    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO));
295
296    Descriptor = Rnode->Buffer;
297    Descriptor->Io.DescriptorType  = ACPI_RESOURCE_NAME_IO |
298                                      ASL_RDESC_IO_SIZE;
299
300    /* Process all child initialization nodes */
301
302    for (i = 0; InitializerOp; i++)
303    {
304        switch (i)
305        {
306        case 0: /* Decode size */
307
308            RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1);
309            RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
310                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0);
311            break;
312
313        case 1:  /* Min Address */
314
315            Descriptor->Io.Minimum =
316                (UINT16) InitializerOp->Asl.Value.Integer;
317            RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
318                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum));
319            MinOp = InitializerOp;
320            break;
321
322        case 2: /* Max Address */
323
324            Descriptor->Io.Maximum =
325                (UINT16) InitializerOp->Asl.Value.Integer;
326            RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
327                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum));
328            MaxOp = InitializerOp;
329            break;
330
331        case 3: /* Alignment */
332
333            Descriptor->Io.Alignment =
334                (UINT8) InitializerOp->Asl.Value.Integer;
335            RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
336                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment));
337            AlignOp = InitializerOp;
338            break;
339
340        case 4: /* Length */
341
342            Descriptor->Io.AddressLength =
343                (UINT8) InitializerOp->Asl.Value.Integer;
344            RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
345                CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength));
346            LengthOp = InitializerOp;
347            break;
348
349        case 5: /* Name */
350
351            UtAttachNamepathToOwner (Op, InitializerOp);
352            break;
353
354        default:
355
356            AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
357            break;
358        }
359
360        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
361    }
362
363    /* Validate the Min/Max/Len/Align values */
364
365    RsSmallAddressCheck (ACPI_RESOURCE_NAME_IO,
366        Descriptor->Io.Minimum,
367        Descriptor->Io.Maximum,
368        Descriptor->Io.AddressLength,
369        Descriptor->Io.Alignment,
370        MinOp, MaxOp, LengthOp, AlignOp, Op);
371
372    return (Rnode);
373}
374
375
376/*******************************************************************************
377 *
378 * FUNCTION:    RsDoIrqDescriptor
379 *
380 * PARAMETERS:  Op                  - Parent resource descriptor parse node
381 *              CurrentByteOffset   - Offset into the resource template AML
382 *                                    buffer (to track references to the desc)
383 *
384 * RETURN:      Completed resource node
385 *
386 * DESCRIPTION: Construct a short "IRQ" descriptor
387 *
388 ******************************************************************************/
389
390ASL_RESOURCE_NODE *
391RsDoIrqDescriptor (
392    ACPI_PARSE_OBJECT       *Op,
393    UINT32                  CurrentByteOffset)
394{
395    AML_RESOURCE            *Descriptor;
396    ACPI_PARSE_OBJECT       *InitializerOp;
397    ASL_RESOURCE_NODE       *Rnode;
398    UINT32                  Interrupts = 0;
399    UINT16                  IrqMask = 0;
400    UINT32                  i;
401
402
403    InitializerOp = Op->Asl.Child;
404    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ));
405
406    /* Length = 3 (with flag byte) */
407
408    Descriptor = Rnode->Buffer;
409    Descriptor->Irq.DescriptorType  = ACPI_RESOURCE_NAME_IRQ |
410                                      (ASL_RDESC_IRQ_SIZE + 0x01);
411
412    /* Process all child initialization nodes */
413
414    for (i = 0; InitializerOp; i++)
415    {
416        switch (i)
417        {
418        case 0: /* Interrupt Type (or Mode - edge/level) */
419
420            RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1);
421            RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
422                CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0);
423            break;
424
425        case 1: /* Interrupt Level (or Polarity - Active high/low) */
426
427            RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0);
428            RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
429                CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3);
430            break;
431
432        case 2: /* Share Type - Default: exclusive (0) */
433
434            RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0);
435            RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
436                CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4);
437            break;
438
439        case 3: /* Name */
440
441            UtAttachNamepathToOwner (Op, InitializerOp);
442            break;
443
444        default:
445
446            /* All IRQ bytes are handled here, after the flags and name */
447
448            if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
449            {
450                /* Up to 16 interrupts can be specified in the list */
451
452                Interrupts++;
453                if (Interrupts > 16)
454                {
455                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
456                        InitializerOp, NULL);
457                    return (Rnode);
458                }
459
460                /* Only interrupts 0-15 are allowed (mask is 16 bits) */
461
462                if (InitializerOp->Asl.Value.Integer > 15)
463                {
464                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
465                        InitializerOp, NULL);
466                }
467                else
468                {
469                    IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer);
470                }
471            }
472
473            /* Case 4: First IRQ value in list */
474
475            if (i == 4)
476            {
477                /* Check now for duplicates in list */
478
479                RsCheckListForDuplicates (InitializerOp);
480
481                /* Create a named field at the start of the list */
482
483                RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT,
484                    CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
485            }
486            break;
487        }
488
489        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
490    }
491
492    /* Now we can set the channel mask */
493
494    Descriptor->Irq.IrqMask = IrqMask;
495    return (Rnode);
496}
497
498
499/*******************************************************************************
500 *
501 * FUNCTION:    RsDoIrqNoFlagsDescriptor
502 *
503 * PARAMETERS:  Op                  - Parent resource descriptor parse node
504 *              CurrentByteOffset   - Offset into the resource template AML
505 *                                    buffer (to track references to the desc)
506 *
507 * RETURN:      Completed resource node
508 *
509 * DESCRIPTION: Construct a short "IRQNoFlags" descriptor
510 *
511 ******************************************************************************/
512
513ASL_RESOURCE_NODE *
514RsDoIrqNoFlagsDescriptor (
515    ACPI_PARSE_OBJECT       *Op,
516    UINT32                  CurrentByteOffset)
517{
518    AML_RESOURCE            *Descriptor;
519    ACPI_PARSE_OBJECT       *InitializerOp;
520    ASL_RESOURCE_NODE       *Rnode;
521    UINT16                  IrqMask = 0;
522    UINT32                  Interrupts = 0;
523    UINT32                  i;
524
525
526    InitializerOp = Op->Asl.Child;
527    Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS));
528
529    Descriptor = Rnode->Buffer;
530    Descriptor->Irq.DescriptorType  = ACPI_RESOURCE_NAME_IRQ |
531                                      ASL_RDESC_IRQ_SIZE;
532
533    /* Process all child initialization nodes */
534
535    for (i = 0; InitializerOp; i++)
536    {
537        switch (i)
538        {
539        case 0: /* Name */
540
541            UtAttachNamepathToOwner (Op, InitializerOp);
542            break;
543
544        default:
545
546            /* IRQ bytes are handled here, after the flags and name */
547
548            if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
549            {
550                /* Up to 16 interrupts can be specified in the list */
551
552                Interrupts++;
553                if (Interrupts > 16)
554                {
555                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
556                        InitializerOp, NULL);
557                    return (Rnode);
558                }
559
560                /* Only interrupts 0-15 are allowed (mask is 16 bits) */
561
562                if (InitializerOp->Asl.Value.Integer > 15)
563                {
564                    AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
565                        InitializerOp, NULL);
566                }
567                else
568                {
569                    IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
570                }
571            }
572
573            /* Case 1: First IRQ value in list */
574
575            if (i == 1)
576            {
577                /* Check now for duplicates in list */
578
579                RsCheckListForDuplicates (InitializerOp);
580
581                /* Create a named field at the start of the list */
582
583                RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT,
584                    CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
585            }
586            break;
587        }
588
589        InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
590    }
591
592    /* Now we can set the interrupt mask */
593
594    Descriptor->Irq.IrqMask = IrqMask;
595    return (Rnode);
596}
597