1 /******************************************************************************* 2 * 3 * Module Name: hwregs - Read/write access functions for the various ACPI 4 * control and status registers. 5 * 6 ******************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2017, 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 #include "acpi.h" 46 #include "accommon.h" 47 #include "acevents.h" 48 49 #define _COMPONENT ACPI_HARDWARE 50 ACPI_MODULE_NAME ("hwregs") 51 52 53 #if (!ACPI_REDUCED_HARDWARE) 54 55 /* Local Prototypes */ 56 57 static UINT8 58 AcpiHwGetAccessBitWidth ( 59 UINT64 Address, 60 ACPI_GENERIC_ADDRESS *Reg, 61 UINT8 MaxBitWidth); 62 63 static ACPI_STATUS 64 AcpiHwReadMultiple ( 65 UINT32 *Value, 66 ACPI_GENERIC_ADDRESS *RegisterA, 67 ACPI_GENERIC_ADDRESS *RegisterB); 68 69 static ACPI_STATUS 70 AcpiHwWriteMultiple ( 71 UINT32 Value, 72 ACPI_GENERIC_ADDRESS *RegisterA, 73 ACPI_GENERIC_ADDRESS *RegisterB); 74 75 #endif /* !ACPI_REDUCED_HARDWARE */ 76 77 78 /****************************************************************************** 79 * 80 * FUNCTION: AcpiHwGetAccessBitWidth 81 * 82 * PARAMETERS: Address - GAS register address 83 * Reg - GAS register structure 84 * MaxBitWidth - Max BitWidth supported (32 or 64) 85 * 86 * RETURN: Status 87 * 88 * DESCRIPTION: Obtain optimal access bit width 89 * 90 ******************************************************************************/ 91 92 static UINT8 93 AcpiHwGetAccessBitWidth ( 94 UINT64 Address, 95 ACPI_GENERIC_ADDRESS *Reg, 96 UINT8 MaxBitWidth) 97 { 98 UINT8 AccessBitWidth; 99 100 101 /* 102 * GAS format "register", used by FADT: 103 * 1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64; 104 * 2. AccessSize field is ignored and BitWidth field is used for 105 * determining the boundary of the IO accesses. 106 * GAS format "region", used by APEI registers: 107 * 1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64; 108 * 2. AccessSize field is used for determining the boundary of the 109 * IO accesses; 110 * 3. BitOffset/BitWidth fields are used to describe the "region". 111 * 112 * Note: This algorithm assumes that the "Address" fields should always 113 * contain aligned values. 114 */ 115 if (!Reg->BitOffset && Reg->BitWidth && 116 ACPI_IS_POWER_OF_TWO (Reg->BitWidth) && 117 ACPI_IS_ALIGNED (Reg->BitWidth, 8)) 118 { 119 AccessBitWidth = Reg->BitWidth; 120 } 121 else if (Reg->AccessWidth) 122 { 123 AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth); 124 } 125 else 126 { 127 AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 ( 128 Reg->BitOffset + Reg->BitWidth); 129 if (AccessBitWidth <= 8) 130 { 131 AccessBitWidth = 8; 132 } 133 else 134 { 135 while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3)) 136 { 137 AccessBitWidth >>= 1; 138 } 139 } 140 } 141 142 /* Maximum IO port access bit width is 32 */ 143 144 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) 145 { 146 MaxBitWidth = 32; 147 } 148 149 /* 150 * Return access width according to the requested maximum access bit width, 151 * as the caller should know the format of the register and may enforce 152 * a 32-bit accesses. 153 */ 154 if (AccessBitWidth < MaxBitWidth) 155 { 156 return (AccessBitWidth); 157 } 158 return (MaxBitWidth); 159 } 160 161 162 /****************************************************************************** 163 * 164 * FUNCTION: AcpiHwValidateRegister 165 * 166 * PARAMETERS: Reg - GAS register structure 167 * MaxBitWidth - Max BitWidth supported (32 or 64) 168 * Address - Pointer to where the gas->address 169 * is returned 170 * 171 * RETURN: Status 172 * 173 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS 174 * pointer, Address, SpaceId, BitWidth, and BitOffset. 175 * 176 ******************************************************************************/ 177 178 ACPI_STATUS 179 AcpiHwValidateRegister ( 180 ACPI_GENERIC_ADDRESS *Reg, 181 UINT8 MaxBitWidth, 182 UINT64 *Address) 183 { 184 UINT8 BitWidth; 185 UINT8 AccessWidth; 186 187 188 /* Must have a valid pointer to a GAS structure */ 189 190 if (!Reg) 191 { 192 return (AE_BAD_PARAMETER); 193 } 194 195 /* 196 * Copy the target address. This handles possible alignment issues. 197 * Address must not be null. A null address also indicates an optional 198 * ACPI register that is not supported, so no error message. 199 */ 200 ACPI_MOVE_64_TO_64 (Address, &Reg->Address); 201 if (!(*Address)) 202 { 203 return (AE_BAD_ADDRESS); 204 } 205 206 /* Validate the SpaceID */ 207 208 if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 209 (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 210 { 211 ACPI_ERROR ((AE_INFO, 212 "Unsupported address space: 0x%X", Reg->SpaceId)); 213 return (AE_SUPPORT); 214 } 215 216 /* Validate the AccessWidth */ 217 218 if (Reg->AccessWidth > 4) 219 { 220 ACPI_ERROR ((AE_INFO, 221 "Unsupported register access width: 0x%X", Reg->AccessWidth)); 222 return (AE_SUPPORT); 223 } 224 225 /* Validate the BitWidth, convert AccessWidth into number of bits */ 226 227 AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth); 228 BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth); 229 if (MaxBitWidth < BitWidth) 230 { 231 ACPI_WARNING ((AE_INFO, 232 "Requested bit width 0x%X is smaller than register bit width 0x%X", 233 MaxBitWidth, BitWidth)); 234 return (AE_SUPPORT); 235 } 236 237 return (AE_OK); 238 } 239 240 241 /****************************************************************************** 242 * 243 * FUNCTION: AcpiHwRead 244 * 245 * PARAMETERS: Value - Where the value is returned 246 * Reg - GAS register structure 247 * 248 * RETURN: Status 249 * 250 * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max 251 * version of AcpiRead. 252 * 253 * LIMITATIONS: <These limitations also apply to AcpiHwWrite> 254 * SpaceID must be SystemMemory or SystemIO. 255 * 256 ******************************************************************************/ 257 258 ACPI_STATUS 259 AcpiHwRead ( 260 UINT64 *Value, 261 ACPI_GENERIC_ADDRESS *Reg) 262 { 263 UINT64 Address; 264 UINT8 AccessWidth; 265 UINT32 BitWidth; 266 UINT8 BitOffset; 267 UINT64 Value64; 268 UINT32 Value32; 269 UINT8 Index; 270 ACPI_STATUS Status; 271 272 273 ACPI_FUNCTION_NAME (HwRead); 274 275 276 /* Validate contents of the GAS register */ 277 278 Status = AcpiHwValidateRegister (Reg, 64, &Address); 279 if (ACPI_FAILURE (Status)) 280 { 281 return (Status); 282 } 283 284 /* 285 * Initialize entire 64-bit return value to zero, convert AccessWidth 286 * into number of bits based 287 */ 288 *Value = 0; 289 AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64); 290 BitWidth = Reg->BitOffset + Reg->BitWidth; 291 BitOffset = Reg->BitOffset; 292 293 /* 294 * Two address spaces supported: Memory or IO. PCI_Config is 295 * not supported here because the GAS structure is insufficient 296 */ 297 Index = 0; 298 while (BitWidth) 299 { 300 if (BitOffset >= AccessWidth) 301 { 302 Value64 = 0; 303 BitOffset -= AccessWidth; 304 } 305 else 306 { 307 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 308 { 309 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 310 Address + Index * ACPI_DIV_8 (AccessWidth), 311 &Value64, AccessWidth); 312 } 313 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 314 { 315 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 316 Address + Index * ACPI_DIV_8 (AccessWidth), 317 &Value32, AccessWidth); 318 Value64 = (UINT64) Value32; 319 } 320 } 321 322 /* 323 * Use offset style bit writes because "Index * AccessWidth" is 324 * ensured to be less than 64-bits by AcpiHwValidateRegister(). 325 */ 326 ACPI_SET_BITS (Value, Index * AccessWidth, 327 ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64); 328 329 BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth; 330 Index++; 331 } 332 333 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 334 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", 335 ACPI_FORMAT_UINT64 (*Value), AccessWidth, 336 ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId))); 337 338 return (Status); 339 } 340 341 342 /****************************************************************************** 343 * 344 * FUNCTION: AcpiHwWrite 345 * 346 * PARAMETERS: Value - Value to be written 347 * Reg - GAS register structure 348 * 349 * RETURN: Status 350 * 351 * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max 352 * version of AcpiWrite. 353 * 354 ******************************************************************************/ 355 356 ACPI_STATUS 357 AcpiHwWrite ( 358 UINT64 Value, 359 ACPI_GENERIC_ADDRESS *Reg) 360 { 361 UINT64 Address; 362 UINT8 AccessWidth; 363 UINT32 BitWidth; 364 UINT8 BitOffset; 365 UINT64 Value64; 366 UINT8 Index; 367 ACPI_STATUS Status; 368 369 370 ACPI_FUNCTION_NAME (HwWrite); 371 372 373 /* Validate contents of the GAS register */ 374 375 Status = AcpiHwValidateRegister (Reg, 64, &Address); 376 if (ACPI_FAILURE (Status)) 377 { 378 return (Status); 379 } 380 381 /* Convert AccessWidth into number of bits based */ 382 383 AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64); 384 BitWidth = Reg->BitOffset + Reg->BitWidth; 385 BitOffset = Reg->BitOffset; 386 387 /* 388 * Two address spaces supported: Memory or IO. PCI_Config is 389 * not supported here because the GAS structure is insufficient 390 */ 391 Index = 0; 392 while (BitWidth) 393 { 394 /* 395 * Use offset style bit reads because "Index * AccessWidth" is 396 * ensured to be less than 64-bits by AcpiHwValidateRegister(). 397 */ 398 Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth, 399 ACPI_MASK_BITS_ABOVE_64 (AccessWidth)); 400 401 if (BitOffset >= AccessWidth) 402 { 403 BitOffset -= AccessWidth; 404 } 405 else 406 { 407 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 408 { 409 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 410 Address + Index * ACPI_DIV_8 (AccessWidth), 411 Value64, AccessWidth); 412 } 413 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 414 { 415 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 416 Address + Index * ACPI_DIV_8 (AccessWidth), 417 (UINT32) Value64, AccessWidth); 418 } 419 } 420 421 /* 422 * Index * AccessWidth is ensured to be less than 32-bits by 423 * AcpiHwValidateRegister(). 424 */ 425 BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth; 426 Index++; 427 } 428 429 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 430 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", 431 ACPI_FORMAT_UINT64 (Value), AccessWidth, 432 ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId))); 433 434 return (Status); 435 } 436 437 438 #if (!ACPI_REDUCED_HARDWARE) 439 /******************************************************************************* 440 * 441 * FUNCTION: AcpiHwClearAcpiStatus 442 * 443 * PARAMETERS: None 444 * 445 * RETURN: Status 446 * 447 * DESCRIPTION: Clears all fixed and general purpose status bits 448 * 449 ******************************************************************************/ 450 451 ACPI_STATUS 452 AcpiHwClearAcpiStatus ( 453 void) 454 { 455 ACPI_STATUS Status; 456 ACPI_CPU_FLAGS LockFlags = 0; 457 458 459 ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 460 461 462 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", 463 ACPI_BITMASK_ALL_FIXED_STATUS, 464 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); 465 466 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 467 468 /* Clear the fixed events in PM1 A/B */ 469 470 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 471 ACPI_BITMASK_ALL_FIXED_STATUS); 472 473 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 474 475 if (ACPI_FAILURE (Status)) 476 { 477 goto Exit; 478 } 479 480 /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 481 482 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 483 484 Exit: 485 return_ACPI_STATUS (Status); 486 } 487 488 489 /******************************************************************************* 490 * 491 * FUNCTION: AcpiHwGetBitRegisterInfo 492 * 493 * PARAMETERS: RegisterId - Index of ACPI Register to access 494 * 495 * RETURN: The bitmask to be used when accessing the register 496 * 497 * DESCRIPTION: Map RegisterId into a register bitmask. 498 * 499 ******************************************************************************/ 500 501 ACPI_BIT_REGISTER_INFO * 502 AcpiHwGetBitRegisterInfo ( 503 UINT32 RegisterId) 504 { 505 ACPI_FUNCTION_ENTRY (); 506 507 508 if (RegisterId > ACPI_BITREG_MAX) 509 { 510 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId)); 511 return (NULL); 512 } 513 514 return (&AcpiGbl_BitRegisterInfo[RegisterId]); 515 } 516 517 518 /****************************************************************************** 519 * 520 * FUNCTION: AcpiHwWritePm1Control 521 * 522 * PARAMETERS: Pm1aControl - Value to be written to PM1A control 523 * Pm1bControl - Value to be written to PM1B control 524 * 525 * RETURN: Status 526 * 527 * DESCRIPTION: Write the PM1 A/B control registers. These registers are 528 * different than than the PM1 A/B status and enable registers 529 * in that different values can be written to the A/B registers. 530 * Most notably, the SLP_TYP bits can be different, as per the 531 * values returned from the _Sx predefined methods. 532 * 533 ******************************************************************************/ 534 535 ACPI_STATUS 536 AcpiHwWritePm1Control ( 537 UINT32 Pm1aControl, 538 UINT32 Pm1bControl) 539 { 540 ACPI_STATUS Status; 541 542 543 ACPI_FUNCTION_TRACE (HwWritePm1Control); 544 545 546 Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); 547 if (ACPI_FAILURE (Status)) 548 { 549 return_ACPI_STATUS (Status); 550 } 551 552 if (AcpiGbl_FADT.XPm1bControlBlock.Address) 553 { 554 Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); 555 } 556 return_ACPI_STATUS (Status); 557 } 558 559 560 /****************************************************************************** 561 * 562 * FUNCTION: AcpiHwRegisterRead 563 * 564 * PARAMETERS: RegisterId - ACPI Register ID 565 * ReturnValue - Where the register value is returned 566 * 567 * RETURN: Status and the value read. 568 * 569 * DESCRIPTION: Read from the specified ACPI register 570 * 571 ******************************************************************************/ 572 573 ACPI_STATUS 574 AcpiHwRegisterRead ( 575 UINT32 RegisterId, 576 UINT32 *ReturnValue) 577 { 578 UINT32 Value = 0; 579 UINT64 Value64; 580 ACPI_STATUS Status; 581 582 583 ACPI_FUNCTION_TRACE (HwRegisterRead); 584 585 586 switch (RegisterId) 587 { 588 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 589 590 Status = AcpiHwReadMultiple (&Value, 591 &AcpiGbl_XPm1aStatus, 592 &AcpiGbl_XPm1bStatus); 593 break; 594 595 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 596 597 Status = AcpiHwReadMultiple (&Value, 598 &AcpiGbl_XPm1aEnable, 599 &AcpiGbl_XPm1bEnable); 600 break; 601 602 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 603 604 Status = AcpiHwReadMultiple (&Value, 605 &AcpiGbl_FADT.XPm1aControlBlock, 606 &AcpiGbl_FADT.XPm1bControlBlock); 607 608 /* 609 * Zero the write-only bits. From the ACPI specification, "Hardware 610 * Write-Only Bits": "Upon reads to registers with write-only bits, 611 * software masks out all write-only bits." 612 */ 613 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; 614 break; 615 616 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 617 618 Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock); 619 Value = (UINT32) Value64; 620 break; 621 622 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 623 624 Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock); 625 Value = (UINT32) Value64; 626 break; 627 628 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 629 630 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8); 631 break; 632 633 default: 634 635 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", 636 RegisterId)); 637 Status = AE_BAD_PARAMETER; 638 break; 639 } 640 641 if (ACPI_SUCCESS (Status)) 642 { 643 *ReturnValue = (UINT32) Value; 644 } 645 646 return_ACPI_STATUS (Status); 647 } 648 649 650 /****************************************************************************** 651 * 652 * FUNCTION: AcpiHwRegisterWrite 653 * 654 * PARAMETERS: RegisterId - ACPI Register ID 655 * Value - The value to write 656 * 657 * RETURN: Status 658 * 659 * DESCRIPTION: Write to the specified ACPI register 660 * 661 * NOTE: In accordance with the ACPI specification, this function automatically 662 * preserves the value of the following bits, meaning that these bits cannot be 663 * changed via this interface: 664 * 665 * PM1_CONTROL[0] = SCI_EN 666 * PM1_CONTROL[9] 667 * PM1_STATUS[11] 668 * 669 * ACPI References: 670 * 1) Hardware Ignored Bits: When software writes to a register with ignored 671 * bit fields, it preserves the ignored bit fields 672 * 2) SCI_EN: OSPM always preserves this bit position 673 * 674 ******************************************************************************/ 675 676 ACPI_STATUS 677 AcpiHwRegisterWrite ( 678 UINT32 RegisterId, 679 UINT32 Value) 680 { 681 ACPI_STATUS Status; 682 UINT32 ReadValue; 683 UINT64 ReadValue64; 684 685 686 ACPI_FUNCTION_TRACE (HwRegisterWrite); 687 688 689 switch (RegisterId) 690 { 691 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 692 /* 693 * Handle the "ignored" bit in PM1 Status. According to the ACPI 694 * specification, ignored bits are to be preserved when writing. 695 * Normally, this would mean a read/modify/write sequence. However, 696 * preserving a bit in the status register is different. Writing a 697 * one clears the status, and writing a zero preserves the status. 698 * Therefore, we must always write zero to the ignored bit. 699 * 700 * This behavior is clarified in the ACPI 4.0 specification. 701 */ 702 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; 703 704 Status = AcpiHwWriteMultiple (Value, 705 &AcpiGbl_XPm1aStatus, 706 &AcpiGbl_XPm1bStatus); 707 break; 708 709 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 710 711 Status = AcpiHwWriteMultiple (Value, 712 &AcpiGbl_XPm1aEnable, 713 &AcpiGbl_XPm1bEnable); 714 break; 715 716 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 717 /* 718 * Perform a read first to preserve certain bits (per ACPI spec) 719 * Note: This includes SCI_EN, we never want to change this bit 720 */ 721 Status = AcpiHwReadMultiple (&ReadValue, 722 &AcpiGbl_FADT.XPm1aControlBlock, 723 &AcpiGbl_FADT.XPm1bControlBlock); 724 if (ACPI_FAILURE (Status)) 725 { 726 goto Exit; 727 } 728 729 /* Insert the bits to be preserved */ 730 731 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 732 733 /* Now we can write the data */ 734 735 Status = AcpiHwWriteMultiple (Value, 736 &AcpiGbl_FADT.XPm1aControlBlock, 737 &AcpiGbl_FADT.XPm1bControlBlock); 738 break; 739 740 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 741 /* 742 * For control registers, all reserved bits must be preserved, 743 * as per the ACPI spec. 744 */ 745 Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock); 746 if (ACPI_FAILURE (Status)) 747 { 748 goto Exit; 749 } 750 ReadValue = (UINT32) ReadValue64; 751 752 /* Insert the bits to be preserved */ 753 754 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); 755 756 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); 757 break; 758 759 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 760 761 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); 762 break; 763 764 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 765 766 /* SMI_CMD is currently always in IO space */ 767 768 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 769 break; 770 771 default: 772 773 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", 774 RegisterId)); 775 Status = AE_BAD_PARAMETER; 776 break; 777 } 778 779 Exit: 780 return_ACPI_STATUS (Status); 781 } 782 783 784 /****************************************************************************** 785 * 786 * FUNCTION: AcpiHwReadMultiple 787 * 788 * PARAMETERS: Value - Where the register value is returned 789 * RegisterA - First ACPI register (required) 790 * RegisterB - Second ACPI register (optional) 791 * 792 * RETURN: Status 793 * 794 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) 795 * 796 ******************************************************************************/ 797 798 static ACPI_STATUS 799 AcpiHwReadMultiple ( 800 UINT32 *Value, 801 ACPI_GENERIC_ADDRESS *RegisterA, 802 ACPI_GENERIC_ADDRESS *RegisterB) 803 { 804 UINT32 ValueA = 0; 805 UINT32 ValueB = 0; 806 UINT64 Value64; 807 ACPI_STATUS Status; 808 809 810 /* The first register is always required */ 811 812 Status = AcpiHwRead (&Value64, RegisterA); 813 if (ACPI_FAILURE (Status)) 814 { 815 return (Status); 816 } 817 ValueA = (UINT32) Value64; 818 819 /* Second register is optional */ 820 821 if (RegisterB->Address) 822 { 823 Status = AcpiHwRead (&Value64, RegisterB); 824 if (ACPI_FAILURE (Status)) 825 { 826 return (Status); 827 } 828 ValueB = (UINT32) Value64; 829 } 830 831 /* 832 * OR the two return values together. No shifting or masking is necessary, 833 * because of how the PM1 registers are defined in the ACPI specification: 834 * 835 * "Although the bits can be split between the two register blocks (each 836 * register block has a unique pointer within the FADT), the bit positions 837 * are maintained. The register block with unimplemented bits (that is, 838 * those implemented in the other register block) always returns zeros, 839 * and writes have no side effects" 840 */ 841 *Value = (ValueA | ValueB); 842 return (AE_OK); 843 } 844 845 846 /****************************************************************************** 847 * 848 * FUNCTION: AcpiHwWriteMultiple 849 * 850 * PARAMETERS: Value - The value to write 851 * RegisterA - First ACPI register (required) 852 * RegisterB - Second ACPI register (optional) 853 * 854 * RETURN: Status 855 * 856 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) 857 * 858 ******************************************************************************/ 859 860 static ACPI_STATUS 861 AcpiHwWriteMultiple ( 862 UINT32 Value, 863 ACPI_GENERIC_ADDRESS *RegisterA, 864 ACPI_GENERIC_ADDRESS *RegisterB) 865 { 866 ACPI_STATUS Status; 867 868 869 /* The first register is always required */ 870 871 Status = AcpiHwWrite (Value, RegisterA); 872 if (ACPI_FAILURE (Status)) 873 { 874 return (Status); 875 } 876 877 /* 878 * Second register is optional 879 * 880 * No bit shifting or clearing is necessary, because of how the PM1 881 * registers are defined in the ACPI specification: 882 * 883 * "Although the bits can be split between the two register blocks (each 884 * register block has a unique pointer within the FADT), the bit positions 885 * are maintained. The register block with unimplemented bits (that is, 886 * those implemented in the other register block) always returns zeros, 887 * and writes have no side effects" 888 */ 889 if (RegisterB->Address) 890 { 891 Status = AcpiHwWrite (Value, RegisterB); 892 } 893 894 return (Status); 895 } 896 897 #endif /* !ACPI_REDUCED_HARDWARE */ 898