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 }