1 2 /******************************************************************************* 3 * 4 * Module Name: hwregs - Read/write access functions for the various ACPI 5 * control and status registers. 6 * 7 ******************************************************************************/ 8 9 /****************************************************************************** 10 * 11 * 1. Copyright Notice 12 * 13 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 14 * All rights reserved. 15 * 16 * 2. License 17 * 18 * 2.1. This is your license from Intel Corp. under its intellectual property 19 * rights. You may have additional license terms from the party that provided 20 * you this software, covering your right to use that party's intellectual 21 * property rights. 22 * 23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24 * copy of the source code appearing in this file ("Covered Code") an 25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26 * base code distributed originally by Intel ("Original Intel Code") to copy, 27 * make derivatives, distribute, use and display any portion of the Covered 28 * Code in any form, with the right to sublicense such rights; and 29 * 30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31 * license (with the right to sublicense), under only those claims of Intel 32 * patents that are infringed by the Original Intel Code, to make, use, sell, 33 * offer to sell, and import the Covered Code and derivative works thereof 34 * solely to the minimum extent necessary to exercise the above copyright 35 * license, and in no event shall the patent license extend to any additions 36 * to or modifications of the Original Intel Code. No other license or right 37 * is granted directly or by implication, estoppel or otherwise; 38 * 39 * The above copyright and patent license is granted only if the following 40 * conditions are met: 41 * 42 * 3. Conditions 43 * 44 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45 * Redistribution of source code of any substantial portion of the Covered 46 * Code or modification with rights to further distribute source must include 47 * the above Copyright Notice, the above License, this list of Conditions, 48 * and the following Disclaimer and Export Compliance provision. In addition, 49 * Licensee must cause all Covered Code to which Licensee contributes to 50 * contain a file documenting the changes Licensee made to create that Covered 51 * Code and the date of any change. Licensee must include in that file the 52 * documentation of any changes made by any predecessor Licensee. Licensee 53 * must include a prominent statement that the modification is derived, 54 * directly or indirectly, from Original Intel Code. 55 * 56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57 * Redistribution of source code of any substantial portion of the Covered 58 * Code or modification without rights to further distribute source must 59 * include the following Disclaimer and Export Compliance provision in the 60 * documentation and/or other materials provided with distribution. In 61 * addition, Licensee may not authorize further sublicense of source of any 62 * portion of the Covered Code, and must include terms to the effect that the 63 * license from Licensee to its licensee is limited to the intellectual 64 * property embodied in the software Licensee provides to its licensee, and 65 * not to intellectual property embodied in modifications its licensee may 66 * make. 67 * 68 * 3.3. Redistribution of Executable. Redistribution in executable form of any 69 * substantial portion of the Covered Code or modification must reproduce the 70 * above Copyright Notice, and the following Disclaimer and Export Compliance 71 * provision in the documentation and/or other materials provided with the 72 * distribution. 73 * 74 * 3.4. Intel retains all right, title, and interest in and to the Original 75 * Intel Code. 76 * 77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78 * Intel shall be used in advertising or otherwise to promote the sale, use or 79 * other dealings in products derived from or relating to the Covered Code 80 * without prior written authorization from Intel. 81 * 82 * 4. Disclaimer and Export Compliance 83 * 84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90 * PARTICULAR PURPOSE. 91 * 92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99 * LIMITED REMEDY. 100 * 101 * 4.3. Licensee shall not export, either directly or indirectly, any of this 102 * software or system incorporating such software without first obtaining any 103 * required license or other approval from the U. S. Department of Commerce or 104 * any other agency or department of the United States Government. In the 105 * event Licensee exports any such software from the United States or 106 * re-exports any such software from a foreign destination, Licensee shall 107 * ensure that the distribution and export/re-export of the software is in 108 * compliance with all laws, regulations, orders, or other restrictions of the 109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110 * any of its subsidiaries will export/re-export any technical data, process, 111 * software, or service, directly or indirectly, to any country for which the 112 * United States government or any agency thereof requires an export license, 113 * other governmental approval, or letter of assurance, without first obtaining 114 * such license, approval or letter. 115 * 116 *****************************************************************************/ 117 118 #define __HWREGS_C__ 119 120 #include "acpi.h" 121 #include "accommon.h" 122 #include "acevents.h" 123 124 #define _COMPONENT ACPI_HARDWARE 125 ACPI_MODULE_NAME ("hwregs") 126 127 128 /* Local Prototypes */ 129 130 static ACPI_STATUS 131 AcpiHwReadMultiple ( 132 UINT32 *Value, 133 ACPI_GENERIC_ADDRESS *RegisterA, 134 ACPI_GENERIC_ADDRESS *RegisterB); 135 136 static ACPI_STATUS 137 AcpiHwWriteMultiple ( 138 UINT32 Value, 139 ACPI_GENERIC_ADDRESS *RegisterA, 140 ACPI_GENERIC_ADDRESS *RegisterB); 141 142 143 /****************************************************************************** 144 * 145 * FUNCTION: AcpiHwValidateRegister 146 * 147 * PARAMETERS: Reg - GAS register structure 148 * MaxBitWidth - Max BitWidth supported (32 or 64) 149 * Address - Pointer to where the gas->address 150 * is returned 151 * 152 * RETURN: Status 153 * 154 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS 155 * pointer, Address, SpaceId, BitWidth, and BitOffset. 156 * 157 ******************************************************************************/ 158 159 ACPI_STATUS 160 AcpiHwValidateRegister ( 161 ACPI_GENERIC_ADDRESS *Reg, 162 UINT8 MaxBitWidth, 163 UINT64 *Address) 164 { 165 166 /* Must have a valid pointer to a GAS structure */ 167 168 if (!Reg) 169 { 170 return (AE_BAD_PARAMETER); 171 } 172 173 /* 174 * Copy the target address. This handles possible alignment issues. 175 * Address must not be null. A null address also indicates an optional 176 * ACPI register that is not supported, so no error message. 177 */ 178 ACPI_MOVE_64_TO_64 (Address, &Reg->Address); 179 if (!(*Address)) 180 { 181 return (AE_BAD_ADDRESS); 182 } 183 184 /* Validate the SpaceID */ 185 186 if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 187 (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 188 { 189 ACPI_ERROR ((AE_INFO, 190 "Unsupported address space: 0x%X", Reg->SpaceId)); 191 return (AE_SUPPORT); 192 } 193 194 /* Validate the BitWidth */ 195 196 if ((Reg->BitWidth != 8) && 197 (Reg->BitWidth != 16) && 198 (Reg->BitWidth != 32) && 199 (Reg->BitWidth != MaxBitWidth)) 200 { 201 ACPI_ERROR ((AE_INFO, 202 "Unsupported register bit width: 0x%X", Reg->BitWidth)); 203 return (AE_SUPPORT); 204 } 205 206 /* Validate the BitOffset. Just a warning for now. */ 207 208 if (Reg->BitOffset != 0) 209 { 210 ACPI_WARNING ((AE_INFO, 211 "Unsupported register bit offset: 0x%X", Reg->BitOffset)); 212 } 213 214 return (AE_OK); 215 } 216 217 218 /****************************************************************************** 219 * 220 * FUNCTION: AcpiHwRead 221 * 222 * PARAMETERS: Value - Where the value is returned 223 * Reg - GAS register structure 224 * 225 * RETURN: Status 226 * 227 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max 228 * version of AcpiRead, used internally since the overhead of 229 * 64-bit values is not needed. 230 * 231 * LIMITATIONS: <These limitations also apply to AcpiHwWrite> 232 * BitWidth must be exactly 8, 16, or 32. 233 * SpaceID must be SystemMemory or SystemIO. 234 * BitOffset and AccessWidth are currently ignored, as there has 235 * not been a need to implement these. 236 * 237 ******************************************************************************/ 238 239 ACPI_STATUS 240 AcpiHwRead ( 241 UINT32 *Value, 242 ACPI_GENERIC_ADDRESS *Reg) 243 { 244 UINT64 Address; 245 ACPI_STATUS Status; 246 247 248 ACPI_FUNCTION_NAME (HwRead); 249 250 251 /* Validate contents of the GAS register */ 252 253 Status = AcpiHwValidateRegister (Reg, 32, &Address); 254 if (ACPI_FAILURE (Status)) 255 { 256 return (Status); 257 } 258 259 /* Initialize entire 32-bit return value to zero */ 260 261 *Value = 0; 262 263 /* 264 * Two address spaces supported: Memory or IO. PCI_Config is 265 * not supported here because the GAS structure is insufficient 266 */ 267 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 268 { 269 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 270 Address, Value, Reg->BitWidth); 271 } 272 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 273 { 274 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 275 Address, Value, Reg->BitWidth); 276 } 277 278 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 279 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", 280 *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), 281 AcpiUtGetRegionName (Reg->SpaceId))); 282 283 return (Status); 284 } 285 286 287 /****************************************************************************** 288 * 289 * FUNCTION: AcpiHwWrite 290 * 291 * PARAMETERS: Value - Value to be written 292 * Reg - GAS register structure 293 * 294 * RETURN: Status 295 * 296 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max 297 * version of AcpiWrite, used internally since the overhead of 298 * 64-bit values is not needed. 299 * 300 ******************************************************************************/ 301 302 ACPI_STATUS 303 AcpiHwWrite ( 304 UINT32 Value, 305 ACPI_GENERIC_ADDRESS *Reg) 306 { 307 UINT64 Address; 308 ACPI_STATUS Status; 309 310 311 ACPI_FUNCTION_NAME (HwWrite); 312 313 314 /* Validate contents of the GAS register */ 315 316 Status = AcpiHwValidateRegister (Reg, 32, &Address); 317 if (ACPI_FAILURE (Status)) 318 { 319 return (Status); 320 } 321 322 /* 323 * Two address spaces supported: Memory or IO. PCI_Config is 324 * not supported here because the GAS structure is insufficient 325 */ 326 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 327 { 328 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 329 Address, Value, Reg->BitWidth); 330 } 331 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 332 { 333 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 334 Address, Value, Reg->BitWidth); 335 } 336 337 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 338 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 339 Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), 340 AcpiUtGetRegionName (Reg->SpaceId))); 341 342 return (Status); 343 } 344 345 346 /******************************************************************************* 347 * 348 * FUNCTION: AcpiHwClearAcpiStatus 349 * 350 * PARAMETERS: None 351 * 352 * RETURN: Status 353 * 354 * DESCRIPTION: Clears all fixed and general purpose status bits 355 * 356 ******************************************************************************/ 357 358 ACPI_STATUS 359 AcpiHwClearAcpiStatus ( 360 void) 361 { 362 ACPI_STATUS Status; 363 ACPI_CPU_FLAGS LockFlags = 0; 364 365 366 ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 367 368 369 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", 370 ACPI_BITMASK_ALL_FIXED_STATUS, 371 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); 372 373 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 374 375 /* Clear the fixed events in PM1 A/B */ 376 377 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 378 ACPI_BITMASK_ALL_FIXED_STATUS); 379 if (ACPI_FAILURE (Status)) 380 { 381 goto UnlockAndExit; 382 } 383 384 /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 385 386 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 387 388 UnlockAndExit: 389 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 390 return_ACPI_STATUS (Status); 391 } 392 393 394 /******************************************************************************* 395 * 396 * FUNCTION: AcpiHwGetRegisterBitMask 397 * 398 * PARAMETERS: RegisterId - Index of ACPI Register to access 399 * 400 * RETURN: The bitmask to be used when accessing the register 401 * 402 * DESCRIPTION: Map RegisterId into a register bitmask. 403 * 404 ******************************************************************************/ 405 406 ACPI_BIT_REGISTER_INFO * 407 AcpiHwGetBitRegisterInfo ( 408 UINT32 RegisterId) 409 { 410 ACPI_FUNCTION_ENTRY (); 411 412 413 if (RegisterId > ACPI_BITREG_MAX) 414 { 415 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId)); 416 return (NULL); 417 } 418 419 return (&AcpiGbl_BitRegisterInfo[RegisterId]); 420 } 421 422 423 /****************************************************************************** 424 * 425 * FUNCTION: AcpiHwWritePm1Control 426 * 427 * PARAMETERS: Pm1aControl - Value to be written to PM1A control 428 * Pm1bControl - Value to be written to PM1B control 429 * 430 * RETURN: Status 431 * 432 * DESCRIPTION: Write the PM1 A/B control registers. These registers are 433 * different than than the PM1 A/B status and enable registers 434 * in that different values can be written to the A/B registers. 435 * Most notably, the SLP_TYP bits can be different, as per the 436 * values returned from the _Sx predefined methods. 437 * 438 ******************************************************************************/ 439 440 ACPI_STATUS 441 AcpiHwWritePm1Control ( 442 UINT32 Pm1aControl, 443 UINT32 Pm1bControl) 444 { 445 ACPI_STATUS Status; 446 447 448 ACPI_FUNCTION_TRACE (HwWritePm1Control); 449 450 451 Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); 452 if (ACPI_FAILURE (Status)) 453 { 454 return_ACPI_STATUS (Status); 455 } 456 457 if (AcpiGbl_FADT.XPm1bControlBlock.Address) 458 { 459 Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); 460 } 461 return_ACPI_STATUS (Status); 462 } 463 464 465 /****************************************************************************** 466 * 467 * FUNCTION: AcpiHwRegisterRead 468 * 469 * PARAMETERS: RegisterId - ACPI Register ID 470 * ReturnValue - Where the register value is returned 471 * 472 * RETURN: Status and the value read. 473 * 474 * DESCRIPTION: Read from the specified ACPI register 475 * 476 ******************************************************************************/ 477 478 ACPI_STATUS 479 AcpiHwRegisterRead ( 480 UINT32 RegisterId, 481 UINT32 *ReturnValue) 482 { 483 UINT32 Value = 0; 484 ACPI_STATUS Status; 485 486 487 ACPI_FUNCTION_TRACE (HwRegisterRead); 488 489 490 switch (RegisterId) 491 { 492 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 493 494 Status = AcpiHwReadMultiple (&Value, 495 &AcpiGbl_XPm1aStatus, 496 &AcpiGbl_XPm1bStatus); 497 break; 498 499 500 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 501 502 Status = AcpiHwReadMultiple (&Value, 503 &AcpiGbl_XPm1aEnable, 504 &AcpiGbl_XPm1bEnable); 505 break; 506 507 508 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 509 510 Status = AcpiHwReadMultiple (&Value, 511 &AcpiGbl_FADT.XPm1aControlBlock, 512 &AcpiGbl_FADT.XPm1bControlBlock); 513 514 /* 515 * Zero the write-only bits. From the ACPI specification, "Hardware 516 * Write-Only Bits": "Upon reads to registers with write-only bits, 517 * software masks out all write-only bits." 518 */ 519 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; 520 break; 521 522 523 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 524 525 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock); 526 break; 527 528 529 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 530 531 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock); 532 break; 533 534 535 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 536 537 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8); 538 break; 539 540 541 default: 542 ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 543 RegisterId)); 544 Status = AE_BAD_PARAMETER; 545 break; 546 } 547 548 if (ACPI_SUCCESS (Status)) 549 { 550 *ReturnValue = Value; 551 } 552 553 return_ACPI_STATUS (Status); 554 } 555 556 557 /****************************************************************************** 558 * 559 * FUNCTION: AcpiHwRegisterWrite 560 * 561 * PARAMETERS: RegisterId - ACPI Register ID 562 * Value - The value to write 563 * 564 * RETURN: Status 565 * 566 * DESCRIPTION: Write to the specified ACPI register 567 * 568 * NOTE: In accordance with the ACPI specification, this function automatically 569 * preserves the value of the following bits, meaning that these bits cannot be 570 * changed via this interface: 571 * 572 * PM1_CONTROL[0] = SCI_EN 573 * PM1_CONTROL[9] 574 * PM1_STATUS[11] 575 * 576 * ACPI References: 577 * 1) Hardware Ignored Bits: When software writes to a register with ignored 578 * bit fields, it preserves the ignored bit fields 579 * 2) SCI_EN: OSPM always preserves this bit position 580 * 581 ******************************************************************************/ 582 583 ACPI_STATUS 584 AcpiHwRegisterWrite ( 585 UINT32 RegisterId, 586 UINT32 Value) 587 { 588 ACPI_STATUS Status; 589 UINT32 ReadValue; 590 591 592 ACPI_FUNCTION_TRACE (HwRegisterWrite); 593 594 595 switch (RegisterId) 596 { 597 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 598 /* 599 * Handle the "ignored" bit in PM1 Status. According to the ACPI 600 * specification, ignored bits are to be preserved when writing. 601 * Normally, this would mean a read/modify/write sequence. However, 602 * preserving a bit in the status register is different. Writing a 603 * one clears the status, and writing a zero preserves the status. 604 * Therefore, we must always write zero to the ignored bit. 605 * 606 * This behavior is clarified in the ACPI 4.0 specification. 607 */ 608 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; 609 610 Status = AcpiHwWriteMultiple (Value, 611 &AcpiGbl_XPm1aStatus, 612 &AcpiGbl_XPm1bStatus); 613 break; 614 615 616 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 617 618 Status = AcpiHwWriteMultiple (Value, 619 &AcpiGbl_XPm1aEnable, 620 &AcpiGbl_XPm1bEnable); 621 break; 622 623 624 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 625 626 /* 627 * Perform a read first to preserve certain bits (per ACPI spec) 628 * Note: This includes SCI_EN, we never want to change this bit 629 */ 630 Status = AcpiHwReadMultiple (&ReadValue, 631 &AcpiGbl_FADT.XPm1aControlBlock, 632 &AcpiGbl_FADT.XPm1bControlBlock); 633 if (ACPI_FAILURE (Status)) 634 { 635 goto Exit; 636 } 637 638 /* Insert the bits to be preserved */ 639 640 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 641 642 /* Now we can write the data */ 643 644 Status = AcpiHwWriteMultiple (Value, 645 &AcpiGbl_FADT.XPm1aControlBlock, 646 &AcpiGbl_FADT.XPm1bControlBlock); 647 break; 648 649 650 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 651 652 /* 653 * For control registers, all reserved bits must be preserved, 654 * as per the ACPI spec. 655 */ 656 Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock); 657 if (ACPI_FAILURE (Status)) 658 { 659 goto Exit; 660 } 661 662 /* Insert the bits to be preserved */ 663 664 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); 665 666 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); 667 break; 668 669 670 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 671 672 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); 673 break; 674 675 676 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 677 678 /* SMI_CMD is currently always in IO space */ 679 680 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 681 break; 682 683 684 default: 685 ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 686 RegisterId)); 687 Status = AE_BAD_PARAMETER; 688 break; 689 } 690 691 Exit: 692 return_ACPI_STATUS (Status); 693 } 694 695 696 /****************************************************************************** 697 * 698 * FUNCTION: AcpiHwReadMultiple 699 * 700 * PARAMETERS: Value - Where the register value is returned 701 * RegisterA - First ACPI register (required) 702 * RegisterB - Second ACPI register (optional) 703 * 704 * RETURN: Status 705 * 706 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) 707 * 708 ******************************************************************************/ 709 710 static ACPI_STATUS 711 AcpiHwReadMultiple ( 712 UINT32 *Value, 713 ACPI_GENERIC_ADDRESS *RegisterA, 714 ACPI_GENERIC_ADDRESS *RegisterB) 715 { 716 UINT32 ValueA = 0; 717 UINT32 ValueB = 0; 718 ACPI_STATUS Status; 719 720 721 /* The first register is always required */ 722 723 Status = AcpiHwRead (&ValueA, RegisterA); 724 if (ACPI_FAILURE (Status)) 725 { 726 return (Status); 727 } 728 729 /* Second register is optional */ 730 731 if (RegisterB->Address) 732 { 733 Status = AcpiHwRead (&ValueB, RegisterB); 734 if (ACPI_FAILURE (Status)) 735 { 736 return (Status); 737 } 738 } 739 740 /* 741 * OR the two return values together. No shifting or masking is necessary, 742 * because of how the PM1 registers are defined in the ACPI specification: 743 * 744 * "Although the bits can be split between the two register blocks (each 745 * register block has a unique pointer within the FADT), the bit positions 746 * are maintained. The register block with unimplemented bits (that is, 747 * those implemented in the other register block) always returns zeros, 748 * and writes have no side effects" 749 */ 750 *Value = (ValueA | ValueB); 751 return (AE_OK); 752 } 753 754 755 /****************************************************************************** 756 * 757 * FUNCTION: AcpiHwWriteMultiple 758 * 759 * PARAMETERS: Value - The value to write 760 * RegisterA - First ACPI register (required) 761 * RegisterB - Second ACPI register (optional) 762 * 763 * RETURN: Status 764 * 765 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) 766 * 767 ******************************************************************************/ 768 769 static ACPI_STATUS 770 AcpiHwWriteMultiple ( 771 UINT32 Value, 772 ACPI_GENERIC_ADDRESS *RegisterA, 773 ACPI_GENERIC_ADDRESS *RegisterB) 774 { 775 ACPI_STATUS Status; 776 777 778 /* The first register is always required */ 779 780 Status = AcpiHwWrite (Value, RegisterA); 781 if (ACPI_FAILURE (Status)) 782 { 783 return (Status); 784 } 785 786 /* 787 * Second register is optional 788 * 789 * No bit shifting or clearing is necessary, because of how the PM1 790 * registers are defined in the ACPI specification: 791 * 792 * "Although the bits can be split between the two register blocks (each 793 * register block has a unique pointer within the FADT), the bit positions 794 * are maintained. The register block with unimplemented bits (that is, 795 * those implemented in the other register block) always returns zeros, 796 * and writes have no side effects" 797 */ 798 if (RegisterB->Address) 799 { 800 Status = AcpiHwWrite (Value, RegisterB); 801 } 802 803 return (Status); 804 } 805 806