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 "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 73 ASL_RESOURCE_NODE * 74 RsDoDmaDescriptor ( 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 193 ASL_RESOURCE_NODE * 194 RsDoFixedDmaDescriptor ( 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 268 ASL_RESOURCE_NODE * 269 RsDoFixedIoDescriptor ( 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 348 ASL_RESOURCE_NODE * 349 RsDoIoDescriptor ( 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 459 ASL_RESOURCE_NODE * 460 RsDoIrqDescriptor ( 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 581 ASL_RESOURCE_NODE * 582 RsDoIrqNoFlagsDescriptor ( 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