aslrestype1i.c revision 228110
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 * FixedDMA 57 * FixedIO 58 * IO 59 * IRQ 60 * IRQNoFlags 61 */ 62 63/******************************************************************************* 64 * 65 * FUNCTION: RsDoDmaDescriptor 66 * 67 * PARAMETERS: Op - Parent resource descriptor parse node 68 * CurrentByteOffset - Offset into the resource template AML 69 * buffer (to track references to the desc) 70 * 71 * RETURN: Completed resource node 72 * 73 * DESCRIPTION: Construct a short "DMA" descriptor 74 * 75 ******************************************************************************/ 76 77ASL_RESOURCE_NODE * 78RsDoDmaDescriptor ( 79 ACPI_PARSE_OBJECT *Op, 80 UINT32 CurrentByteOffset) 81{ 82 AML_RESOURCE *Descriptor; 83 ACPI_PARSE_OBJECT *InitializerOp; 84 ASL_RESOURCE_NODE *Rnode; 85 UINT32 i; 86 UINT8 DmaChannelMask = 0; 87 UINT8 DmaChannels = 0; 88 89 90 InitializerOp = Op->Asl.Child; 91 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA)); 92 93 Descriptor = Rnode->Buffer; 94 Descriptor->Dma.DescriptorType = ACPI_RESOURCE_NAME_DMA | 95 ASL_RDESC_DMA_SIZE; 96 97 /* Process all child initialization nodes */ 98 99 for (i = 0; InitializerOp; i++) 100 { 101 switch (i) 102 { 103 case 0: /* DMA type */ 104 105 RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0); 106 RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_DMATYPE, 107 CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5, 2); 108 break; 109 110 case 1: /* Bus Master */ 111 112 RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0); 113 RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER, 114 CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2); 115 break; 116 117 case 2: /* Xfer Type (transfer width) */ 118 119 RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0); 120 RsCreateMultiBitField (InitializerOp, ACPI_RESTAG_XFERTYPE, 121 CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0, 2); 122 break; 123 124 case 3: /* Name */ 125 126 UtAttachNamepathToOwner (Op, InitializerOp); 127 break; 128 129 default: 130 131 /* All DMA channel bytes are handled here, after flags and name */ 132 133 if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) 134 { 135 /* Up to 8 channels can be specified in the list */ 136 137 DmaChannels++; 138 if (DmaChannels > 8) 139 { 140 AslError (ASL_ERROR, ASL_MSG_DMA_LIST, 141 InitializerOp, NULL); 142 return (Rnode); 143 } 144 145 /* Only DMA channels 0-7 are allowed (mask is 8 bits) */ 146 147 if (InitializerOp->Asl.Value.Integer > 7) 148 { 149 AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL, 150 InitializerOp, NULL); 151 } 152 153 /* Build the mask */ 154 155 DmaChannelMask |= 156 (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); 157 } 158 159 if (i == 4) /* case 4: First DMA byte */ 160 { 161 /* Check now for duplicates in list */ 162 163 RsCheckListForDuplicates (InitializerOp); 164 165 /* Create a named field at the start of the list */ 166 167 RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA, 168 CurrentByteOffset + 169 ASL_RESDESC_OFFSET (Dma.DmaChannelMask)); 170 } 171 break; 172 } 173 174 InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); 175 } 176 177 /* Now we can set the channel mask */ 178 179 Descriptor->Dma.DmaChannelMask = DmaChannelMask; 180 return (Rnode); 181} 182 183 184/******************************************************************************* 185 * 186 * FUNCTION: RsDoFixedDmaDescriptor 187 * 188 * PARAMETERS: Op - Parent resource descriptor parse node 189 * CurrentByteOffset - Offset into the resource template AML 190 * buffer (to track references to the desc) 191 * 192 * RETURN: Completed resource node 193 * 194 * DESCRIPTION: Construct a short "FixedDMA" descriptor 195 * 196 ******************************************************************************/ 197 198ASL_RESOURCE_NODE * 199RsDoFixedDmaDescriptor ( 200 ACPI_PARSE_OBJECT *Op, 201 UINT32 CurrentByteOffset) 202{ 203 AML_RESOURCE *Descriptor; 204 ACPI_PARSE_OBJECT *InitializerOp; 205 ASL_RESOURCE_NODE *Rnode; 206 UINT32 i; 207 208 209 InitializerOp = Op->Asl.Child; 210 Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_DMA)); 211 212 Descriptor = Rnode->Buffer; 213 Descriptor->FixedDma.DescriptorType = 214 ACPI_RESOURCE_NAME_FIXED_DMA | ASL_RDESC_FIXED_DMA_SIZE; 215 216 /* Process all child initialization nodes */ 217 218 for (i = 0; InitializerOp; i++) 219 { 220 switch (i) 221 { 222 case 0: /* DMA Request Lines [WORD] (_DMA) */ 223 224 Descriptor->FixedDma.RequestLines = (UINT16) InitializerOp->Asl.Value.Integer; 225 RsCreateWordField (InitializerOp, ACPI_RESTAG_DMA, 226 CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.RequestLines)); 227 break; 228 229 case 1: /* DMA Channel [WORD] (_TYP) */ 230 231 Descriptor->FixedDma.Channels = (UINT16) InitializerOp->Asl.Value.Integer; 232 RsCreateWordField (InitializerOp, ACPI_RESTAG_DMATYPE, 233 CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.Channels)); 234 break; 235 236 case 2: /* Transfer Width [BYTE] (_SIZ) */ 237 238 Descriptor->FixedDma.Width = (UINT8) InitializerOp->Asl.Value.Integer; 239 RsCreateByteField (InitializerOp, ACPI_RESTAG_XFERTYPE, 240 CurrentByteOffset + ASL_RESDESC_OFFSET (FixedDma.Width)); 241 break; 242 243 case 3: /* Descriptor Name (optional) */ 244 245 UtAttachNamepathToOwner (Op, InitializerOp); 246 break; 247 248 default: /* Ignore any extra nodes */ 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 273ASL_RESOURCE_NODE * 274RsDoFixedIoDescriptor ( 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 354ASL_RESOURCE_NODE * 355RsDoIoDescriptor ( 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 466ASL_RESOURCE_NODE * 467RsDoIrqDescriptor ( 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 589ASL_RESOURCE_NODE * 590RsDoIrqNoFlagsDescriptor ( 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} 673