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