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 "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
76 ASL_RESOURCE_NODE *
77 RsDoDmaDescriptor (
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
197 ASL_RESOURCE_NODE *
198 RsDoFixedDmaDescriptor (
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
249 break;
250 }
251
252 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
253 }
254
255 return (Rnode);
256 }
257
258
259 /*******************************************************************************
260 *
261 * FUNCTION: RsDoFixedIoDescriptor
262 *
263 * PARAMETERS: Op - Parent resource descriptor parse node
264 * CurrentByteOffset - Offset into the resource template AML
265 * buffer (to track references to the desc)
266 *
267 * RETURN: Completed resource node
268 *
269 * DESCRIPTION: Construct a short "FixedIO" descriptor
270 *
271 ******************************************************************************/
272
273 ASL_RESOURCE_NODE *
274 RsDoFixedIoDescriptor (
275 ACPI_PARSE_OBJECT *Op,
276 UINT32 CurrentByteOffset)
277 {
278 AML_RESOURCE *Descriptor;
279 ACPI_PARSE_OBJECT *InitializerOp;
280 ACPI_PARSE_OBJECT *AddressOp = NULL;
281 ASL_RESOURCE_NODE *Rnode;
282 UINT32 i;
283
284
285 InitializerOp = Op->Asl.Child;
286 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO));
287
288 Descriptor = Rnode->Buffer;
289 Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_FIXED_IO |
290 ASL_RDESC_FIXED_IO_SIZE;
291
292 /* Process all child initialization nodes */
293
294 for (i = 0; InitializerOp; i++)
295 {
296 switch (i)
297 {
298 case 0: /* Base Address */
299
300 Descriptor->FixedIo.Address =
301 (UINT16) InitializerOp->Asl.Value.Integer;
302 RsCreateWordField (InitializerOp, ACPI_RESTAG_BASEADDRESS,
303 CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address));
304 AddressOp = InitializerOp;
305 break;
306
307 case 1: /* Length */
308
309 Descriptor->FixedIo.AddressLength =
310 (UINT8) InitializerOp->Asl.Value.Integer;
311 RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
312 CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength));
313 break;
314
315 case 2: /* Name */
316
317 UtAttachNamepathToOwner (Op, InitializerOp);
318 break;
319
320 default:
321
322 AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
323 break;
324 }
325
326 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
327 }
328
329 /* Error checks */
330
331 if (Descriptor->FixedIo.Address > 0x03FF)
332 {
333 AslError (ASL_WARNING, ASL_MSG_ISA_ADDRESS, AddressOp, NULL);
334 }
335
336 return (Rnode);
337 }
338
339
340 /*******************************************************************************
341 *
342 * FUNCTION: RsDoIoDescriptor
343 *
344 * PARAMETERS: Op - Parent resource descriptor parse node
345 * CurrentByteOffset - Offset into the resource template AML
346 * buffer (to track references to the desc)
347 *
348 * RETURN: Completed resource node
349 *
350 * DESCRIPTION: Construct a short "IO" descriptor
351 *
352 ******************************************************************************/
353
354 ASL_RESOURCE_NODE *
355 RsDoIoDescriptor (
356 ACPI_PARSE_OBJECT *Op,
357 UINT32 CurrentByteOffset)
358 {
359 AML_RESOURCE *Descriptor;
360 ACPI_PARSE_OBJECT *InitializerOp;
361 ACPI_PARSE_OBJECT *MinOp = NULL;
362 ACPI_PARSE_OBJECT *MaxOp = NULL;
363 ACPI_PARSE_OBJECT *LengthOp = NULL;
364 ACPI_PARSE_OBJECT *AlignOp = NULL;
365 ASL_RESOURCE_NODE *Rnode;
366 UINT32 i;
367
368
369 InitializerOp = Op->Asl.Child;
370 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO));
371
372 Descriptor = Rnode->Buffer;
373 Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_IO |
374 ASL_RDESC_IO_SIZE;
375
376 /* Process all child initialization nodes */
377
378 for (i = 0; InitializerOp; i++)
379 {
380 switch (i)
381 {
382 case 0: /* Decode size */
383
384 RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1);
385 RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
386 CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0);
387 break;
388
389 case 1: /* Min Address */
390
391 Descriptor->Io.Minimum =
392 (UINT16) InitializerOp->Asl.Value.Integer;
393 RsCreateWordField (InitializerOp, ACPI_RESTAG_MINADDR,
394 CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum));
395 MinOp = InitializerOp;
396 break;
397
398 case 2: /* Max Address */
399
400 Descriptor->Io.Maximum =
401 (UINT16) InitializerOp->Asl.Value.Integer;
402 RsCreateWordField (InitializerOp, ACPI_RESTAG_MAXADDR,
403 CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum));
404 MaxOp = InitializerOp;
405 break;
406
407 case 3: /* Alignment */
408
409 Descriptor->Io.Alignment =
410 (UINT8) InitializerOp->Asl.Value.Integer;
411 RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
412 CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment));
413 AlignOp = InitializerOp;
414 break;
415
416 case 4: /* Length */
417
418 Descriptor->Io.AddressLength =
419 (UINT8) InitializerOp->Asl.Value.Integer;
420 RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
421 CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength));
422 LengthOp = InitializerOp;
423 break;
424
425 case 5: /* Name */
426
427 UtAttachNamepathToOwner (Op, InitializerOp);
428 break;
429
430 default:
431
432 AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
433 break;
434 }
435
436 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
437 }
438
439 /* Validate the Min/Max/Len/Align values */
440
441 RsSmallAddressCheck (ACPI_RESOURCE_NAME_IO,
442 Descriptor->Io.Minimum,
443 Descriptor->Io.Maximum,
444 Descriptor->Io.AddressLength,
445 Descriptor->Io.Alignment,
446 MinOp, MaxOp, LengthOp, AlignOp, Op);
447
448 return (Rnode);
449 }
450
451
452 /*******************************************************************************
453 *
454 * FUNCTION: RsDoIrqDescriptor
455 *
456 * PARAMETERS: Op - Parent resource descriptor parse node
457 * CurrentByteOffset - Offset into the resource template AML
458 * buffer (to track references to the desc)
459 *
460 * RETURN: Completed resource node
461 *
462 * DESCRIPTION: Construct a short "IRQ" descriptor
463 *
464 ******************************************************************************/
465
466 ASL_RESOURCE_NODE *
467 RsDoIrqDescriptor (
468 ACPI_PARSE_OBJECT *Op,
469 UINT32 CurrentByteOffset)
470 {
471 AML_RESOURCE *Descriptor;
472 ACPI_PARSE_OBJECT *InitializerOp;
473 ASL_RESOURCE_NODE *Rnode;
474 UINT32 Interrupts = 0;
475 UINT16 IrqMask = 0;
476 UINT32 i;
477
478
479 InitializerOp = Op->Asl.Child;
480 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ));
481
482 /* Length = 3 (with flag byte) */
483
484 Descriptor = Rnode->Buffer;
485 Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ |
486 (ASL_RDESC_IRQ_SIZE + 0x01);
487
488 /* Process all child initialization nodes */
489
490 for (i = 0; InitializerOp; i++)
491 {
492 switch (i)
493 {
494 case 0: /* Interrupt Type (or Mode - edge/level) */
495
496 RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1);
497 RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
498 CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0);
499 break;
500
501 case 1: /* Interrupt Level (or Polarity - Active high/low) */
502
503 RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0);
504 RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
505 CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3);
506 break;
507
508 case 2: /* Share Type - Default: exclusive (0) */
509
510 RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0);
511 RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
512 CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4);
513 break;
514
515 case 3: /* Name */
516
517 UtAttachNamepathToOwner (Op, InitializerOp);
518 break;
519
520 default:
521
522 /* All IRQ bytes are handled here, after the flags and name */
523
524 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
525 {
526 /* Up to 16 interrupts can be specified in the list */
527
528 Interrupts++;
529 if (Interrupts > 16)
530 {
531 AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
532 InitializerOp, NULL);
533 return (Rnode);
534 }
535
536 /* Only interrupts 0-15 are allowed (mask is 16 bits) */
537
538 if (InitializerOp->Asl.Value.Integer > 15)
539 {
540 AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
541 InitializerOp, NULL);
542 }
543 else
544 {
545 IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer);
546 }
547 }
548
549 /* Case 4: First IRQ value in list */
550
551 if (i == 4)
552 {
553 /* Check now for duplicates in list */
554
555 RsCheckListForDuplicates (InitializerOp);
556
557 /* Create a named field at the start of the list */
558
559 RsCreateWordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
560 CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
561 }
562 break;
563 }
564
565 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
566 }
567
568 /* Now we can set the channel mask */
569
570 Descriptor->Irq.IrqMask = IrqMask;
571 return (Rnode);
572 }
573
574
575 /*******************************************************************************
576 *
577 * FUNCTION: RsDoIrqNoFlagsDescriptor
578 *
579 * PARAMETERS: Op - Parent resource descriptor parse node
580 * CurrentByteOffset - Offset into the resource template AML
581 * buffer (to track references to the desc)
582 *
583 * RETURN: Completed resource node
584 *
585 * DESCRIPTION: Construct a short "IRQNoFlags" descriptor
586 *
587 ******************************************************************************/
588
589 ASL_RESOURCE_NODE *
590 RsDoIrqNoFlagsDescriptor (
591 ACPI_PARSE_OBJECT *Op,
592 UINT32 CurrentByteOffset)
593 {
594 AML_RESOURCE *Descriptor;
595 ACPI_PARSE_OBJECT *InitializerOp;
596 ASL_RESOURCE_NODE *Rnode;
597 UINT16 IrqMask = 0;
598 UINT32 Interrupts = 0;
599 UINT32 i;
600
601
602 InitializerOp = Op->Asl.Child;
603 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS));
604
605 Descriptor = Rnode->Buffer;
606 Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ |
607 ASL_RDESC_IRQ_SIZE;
608
609 /* Process all child initialization nodes */
610
611 for (i = 0; InitializerOp; i++)
612 {
613 switch (i)
614 {
615 case 0: /* Name */
616
617 UtAttachNamepathToOwner (Op, InitializerOp);
618 break;
619
620 default:
621
622 /* IRQ bytes are handled here, after the flags and name */
623
624 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
625 {
626 /* Up to 16 interrupts can be specified in the list */
627
628 Interrupts++;
629 if (Interrupts > 16)
630 {
631 AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
632 InitializerOp, NULL);
633 return (Rnode);
634 }
635
636 /* Only interrupts 0-15 are allowed (mask is 16 bits) */
637
638 if (InitializerOp->Asl.Value.Integer > 15)
639 {
640 AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
641 InitializerOp, NULL);
642 }
643 else
644 {
645 IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
646 }
647 }
648
649 /* Case 1: First IRQ value in list */
650
651 if (i == 1)
652 {
653 /* Check now for duplicates in list */
654
655 RsCheckListForDuplicates (InitializerOp);
656
657 /* Create a named field at the start of the list */
658
659 RsCreateWordField (InitializerOp, ACPI_RESTAG_INTERRUPT,
660 CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
661 }
662 break;
663 }
664
665 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
666 }
667
668 /* Now we can set the interrupt mask */
669
670 Descriptor->Irq.IrqMask = IrqMask;
671 return (Rnode);
672 }