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 * Copyright (C) 2000 - 2011, Intel Corp. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions, and the following disclaimer, 18 * without modification. 19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 20 * substantially similar to the "NO WARRANTY" disclaimer below 21 * ("Disclaimer") and any redistribution must be conditioned upon 22 * including a substantially similar Disclaimer requirement for further 23 * binary redistribution. 24 * 3. Neither the names of the above-listed copyright holders nor the names 25 * of any contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * Alternatively, this software may be distributed under the terms of the 29 * GNU General Public License ("GPL") version 2 as published by the Free 30 * Software Foundation. 31 * 32 * NO WARRANTY 33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 * POSSIBILITY OF SUCH DAMAGES. 44 */ 45 46 #define __HWREGS_C__ 47 48 #include "acpi.h" 49 #include "accommon.h" 50 #include "acevents.h" 51 52 #define _COMPONENT ACPI_HARDWARE 53 ACPI_MODULE_NAME ("hwregs") 54 55 56 /* Local Prototypes */ 57 58 static ACPI_STATUS 59 AcpiHwReadMultiple ( 60 UINT32 *Value, 61 ACPI_GENERIC_ADDRESS *RegisterA, 62 ACPI_GENERIC_ADDRESS *RegisterB); 63 64 static ACPI_STATUS 65 AcpiHwWriteMultiple ( 66 UINT32 Value, 67 ACPI_GENERIC_ADDRESS *RegisterA, 68 ACPI_GENERIC_ADDRESS *RegisterB); 69 70 71 /****************************************************************************** 72 * 73 * FUNCTION: AcpiHwValidateRegister 74 * 75 * PARAMETERS: Reg - GAS register structure 76 * MaxBitWidth - Max BitWidth supported (32 or 64) 77 * Address - Pointer to where the gas->address 78 * is returned 79 * 80 * RETURN: Status 81 * 82 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS 83 * pointer, Address, SpaceId, BitWidth, and BitOffset. 84 * 85 ******************************************************************************/ 86 87 ACPI_STATUS 88 AcpiHwValidateRegister ( 89 ACPI_GENERIC_ADDRESS *Reg, 90 UINT8 MaxBitWidth, 91 UINT64 *Address) 92 { 93 94 /* Must have a valid pointer to a GAS structure */ 95 96 if (!Reg) 97 { 98 return (AE_BAD_PARAMETER); 99 } 100 101 /* 102 * Copy the target address. This handles possible alignment issues. 103 * Address must not be null. A null address also indicates an optional 104 * ACPI register that is not supported, so no error message. 105 */ 106 ACPI_MOVE_64_TO_64 (Address, &Reg->Address); 107 if (!(*Address)) 108 { 109 return (AE_BAD_ADDRESS); 110 } 111 112 /* Validate the SpaceID */ 113 114 if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 115 (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 116 { 117 ACPI_ERROR ((AE_INFO, 118 "Unsupported address space: 0x%X", Reg->SpaceId)); 119 return (AE_SUPPORT); 120 } 121 122 /* Validate the BitWidth */ 123 124 if ((Reg->BitWidth != 8) && 125 (Reg->BitWidth != 16) && 126 (Reg->BitWidth != 32) && 127 (Reg->BitWidth != MaxBitWidth)) 128 { 129 ACPI_ERROR ((AE_INFO, 130 "Unsupported register bit width: 0x%X", Reg->BitWidth)); 131 return (AE_SUPPORT); 132 } 133 134 /* Validate the BitOffset. Just a warning for now. */ 135 136 if (Reg->BitOffset != 0) 137 { 138 ACPI_WARNING ((AE_INFO, 139 "Unsupported register bit offset: 0x%X", Reg->BitOffset)); 140 } 141 142 return (AE_OK); 143 } 144 145 146 /****************************************************************************** 147 * 148 * FUNCTION: AcpiHwRead 149 * 150 * PARAMETERS: Value - Where the value is returned 151 * Reg - GAS register structure 152 * 153 * RETURN: Status 154 * 155 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max 156 * version of AcpiRead, used internally since the overhead of 157 * 64-bit values is not needed. 158 * 159 * LIMITATIONS: <These limitations also apply to AcpiHwWrite> 160 * BitWidth must be exactly 8, 16, or 32. 161 * SpaceID must be SystemMemory or SystemIO. 162 * BitOffset and AccessWidth are currently ignored, as there has 163 * not been a need to implement these. 164 * 165 ******************************************************************************/ 166 167 ACPI_STATUS 168 AcpiHwRead ( 169 UINT32 *Value, 170 ACPI_GENERIC_ADDRESS *Reg) 171 { 172 UINT64 Address; 173 ACPI_STATUS Status; 174 175 176 ACPI_FUNCTION_NAME (HwRead); 177 178 179 /* Validate contents of the GAS register */ 180 181 Status = AcpiHwValidateRegister (Reg, 32, &Address); 182 if (ACPI_FAILURE (Status)) 183 { 184 return (Status); 185 } 186 187 /* Initialize entire 32-bit return value to zero */ 188 189 *Value = 0; 190 191 /* 192 * Two address spaces supported: Memory or IO. PCI_Config is 193 * not supported here because the GAS structure is insufficient 194 */ 195 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 196 { 197 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 198 Address, Value, Reg->BitWidth); 199 } 200 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 201 { 202 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 203 Address, Value, Reg->BitWidth); 204 } 205 206 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 207 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", 208 *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), 209 AcpiUtGetRegionName (Reg->SpaceId))); 210 211 return (Status); 212 } 213 214 215 /****************************************************************************** 216 * 217 * FUNCTION: AcpiHwWrite 218 * 219 * PARAMETERS: Value - Value to be written 220 * Reg - GAS register structure 221 * 222 * RETURN: Status 223 * 224 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max 225 * version of AcpiWrite, used internally since the overhead of 226 * 64-bit values is not needed. 227 * 228 ******************************************************************************/ 229 230 ACPI_STATUS 231 AcpiHwWrite ( 232 UINT32 Value, 233 ACPI_GENERIC_ADDRESS *Reg) 234 { 235 UINT64 Address; 236 ACPI_STATUS Status; 237 238 239 ACPI_FUNCTION_NAME (HwWrite); 240 241 242 /* Validate contents of the GAS register */ 243 244 Status = AcpiHwValidateRegister (Reg, 32, &Address); 245 if (ACPI_FAILURE (Status)) 246 { 247 return (Status); 248 } 249 250 /* 251 * Two address spaces supported: Memory or IO. PCI_Config is 252 * not supported here because the GAS structure is insufficient 253 */ 254 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 255 { 256 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 257 Address, Value, Reg->BitWidth); 258 } 259 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 260 { 261 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 262 Address, Value, Reg->BitWidth); 263 } 264 265 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 266 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 267 Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), 268 AcpiUtGetRegionName (Reg->SpaceId))); 269 270 return (Status); 271 } 272 273 274 /******************************************************************************* 275 * 276 * FUNCTION: AcpiHwClearAcpiStatus 277 * 278 * PARAMETERS: None 279 * 280 * RETURN: Status 281 * 282 * DESCRIPTION: Clears all fixed and general purpose status bits 283 * 284 ******************************************************************************/ 285 286 ACPI_STATUS 287 AcpiHwClearAcpiStatus ( 288 void) 289 { 290 ACPI_STATUS Status; 291 ACPI_CPU_FLAGS LockFlags = 0; 292 293 294 ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 295 296 297 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", 298 ACPI_BITMASK_ALL_FIXED_STATUS, 299 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); 300 301 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 302 303 /* Clear the fixed events in PM1 A/B */ 304 305 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 306 ACPI_BITMASK_ALL_FIXED_STATUS); 307 if (ACPI_FAILURE (Status)) 308 { 309 goto UnlockAndExit; 310 } 311 312 /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 313 314 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 315 316 UnlockAndExit: 317 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 318 return_ACPI_STATUS (Status); 319 } 320 321 322 /******************************************************************************* 323 * 324 * FUNCTION: AcpiHwGetRegisterBitMask 325 * 326 * PARAMETERS: RegisterId - Index of ACPI Register to access 327 * 328 * RETURN: The bitmask to be used when accessing the register 329 * 330 * DESCRIPTION: Map RegisterId into a register bitmask. 331 * 332 ******************************************************************************/ 333 334 ACPI_BIT_REGISTER_INFO * 335 AcpiHwGetBitRegisterInfo ( 336 UINT32 RegisterId) 337 { 338 ACPI_FUNCTION_ENTRY (); 339 340 341 if (RegisterId > ACPI_BITREG_MAX) 342 { 343 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId)); 344 return (NULL); 345 } 346 347 return (&AcpiGbl_BitRegisterInfo[RegisterId]); 348 } 349 350 351 /****************************************************************************** 352 * 353 * FUNCTION: AcpiHwWritePm1Control 354 * 355 * PARAMETERS: Pm1aControl - Value to be written to PM1A control 356 * Pm1bControl - Value to be written to PM1B control 357 * 358 * RETURN: Status 359 * 360 * DESCRIPTION: Write the PM1 A/B control registers. These registers are 361 * different than than the PM1 A/B status and enable registers 362 * in that different values can be written to the A/B registers. 363 * Most notably, the SLP_TYP bits can be different, as per the 364 * values returned from the _Sx predefined methods. 365 * 366 ******************************************************************************/ 367 368 ACPI_STATUS 369 AcpiHwWritePm1Control ( 370 UINT32 Pm1aControl, 371 UINT32 Pm1bControl) 372 { 373 ACPI_STATUS Status; 374 375 376 ACPI_FUNCTION_TRACE (HwWritePm1Control); 377 378 379 Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); 380 if (ACPI_FAILURE (Status)) 381 { 382 return_ACPI_STATUS (Status); 383 } 384 385 if (AcpiGbl_FADT.XPm1bControlBlock.Address) 386 { 387 Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); 388 } 389 return_ACPI_STATUS (Status); 390 } 391 392 393 /****************************************************************************** 394 * 395 * FUNCTION: AcpiHwRegisterRead 396 * 397 * PARAMETERS: RegisterId - ACPI Register ID 398 * ReturnValue - Where the register value is returned 399 * 400 * RETURN: Status and the value read. 401 * 402 * DESCRIPTION: Read from the specified ACPI register 403 * 404 ******************************************************************************/ 405 406 ACPI_STATUS 407 AcpiHwRegisterRead ( 408 UINT32 RegisterId, 409 UINT32 *ReturnValue) 410 { 411 UINT32 Value = 0; 412 ACPI_STATUS Status; 413 414 415 ACPI_FUNCTION_TRACE (HwRegisterRead); 416 417 418 switch (RegisterId) 419 { 420 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 421 422 Status = AcpiHwReadMultiple (&Value, 423 &AcpiGbl_XPm1aStatus, 424 &AcpiGbl_XPm1bStatus); 425 break; 426 427 428 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 429 430 Status = AcpiHwReadMultiple (&Value, 431 &AcpiGbl_XPm1aEnable, 432 &AcpiGbl_XPm1bEnable); 433 break; 434 435 436 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 437 438 Status = AcpiHwReadMultiple (&Value, 439 &AcpiGbl_FADT.XPm1aControlBlock, 440 &AcpiGbl_FADT.XPm1bControlBlock); 441 442 /* 443 * Zero the write-only bits. From the ACPI specification, "Hardware 444 * Write-Only Bits": "Upon reads to registers with write-only bits, 445 * software masks out all write-only bits." 446 */ 447 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; 448 break; 449 450 451 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 452 453 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock); 454 break; 455 456 457 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 458 459 Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock); 460 break; 461 462 463 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 464 465 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8); 466 break; 467 468 469 default: 470 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", 471 RegisterId)); 472 Status = AE_BAD_PARAMETER; 473 break; 474 } 475 476 if (ACPI_SUCCESS (Status)) 477 { 478 *ReturnValue = Value; 479 } 480 481 return_ACPI_STATUS (Status); 482 } 483 484 485 /****************************************************************************** 486 * 487 * FUNCTION: AcpiHwRegisterWrite 488 * 489 * PARAMETERS: RegisterId - ACPI Register ID 490 * Value - The value to write 491 * 492 * RETURN: Status 493 * 494 * DESCRIPTION: Write to the specified ACPI register 495 * 496 * NOTE: In accordance with the ACPI specification, this function automatically 497 * preserves the value of the following bits, meaning that these bits cannot be 498 * changed via this interface: 499 * 500 * PM1_CONTROL[0] = SCI_EN 501 * PM1_CONTROL[9] 502 * PM1_STATUS[11] 503 * 504 * ACPI References: 505 * 1) Hardware Ignored Bits: When software writes to a register with ignored 506 * bit fields, it preserves the ignored bit fields 507 * 2) SCI_EN: OSPM always preserves this bit position 508 * 509 ******************************************************************************/ 510 511 ACPI_STATUS 512 AcpiHwRegisterWrite ( 513 UINT32 RegisterId, 514 UINT32 Value) 515 { 516 ACPI_STATUS Status; 517 UINT32 ReadValue; 518 519 520 ACPI_FUNCTION_TRACE (HwRegisterWrite); 521 522 523 switch (RegisterId) 524 { 525 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 526 /* 527 * Handle the "ignored" bit in PM1 Status. According to the ACPI 528 * specification, ignored bits are to be preserved when writing. 529 * Normally, this would mean a read/modify/write sequence. However, 530 * preserving a bit in the status register is different. Writing a 531 * one clears the status, and writing a zero preserves the status. 532 * Therefore, we must always write zero to the ignored bit. 533 * 534 * This behavior is clarified in the ACPI 4.0 specification. 535 */ 536 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; 537 538 Status = AcpiHwWriteMultiple (Value, 539 &AcpiGbl_XPm1aStatus, 540 &AcpiGbl_XPm1bStatus); 541 break; 542 543 544 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 545 546 Status = AcpiHwWriteMultiple (Value, 547 &AcpiGbl_XPm1aEnable, 548 &AcpiGbl_XPm1bEnable); 549 break; 550 551 552 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 553 554 /* 555 * Perform a read first to preserve certain bits (per ACPI spec) 556 * Note: This includes SCI_EN, we never want to change this bit 557 */ 558 Status = AcpiHwReadMultiple (&ReadValue, 559 &AcpiGbl_FADT.XPm1aControlBlock, 560 &AcpiGbl_FADT.XPm1bControlBlock); 561 if (ACPI_FAILURE (Status)) 562 { 563 goto Exit; 564 } 565 566 /* Insert the bits to be preserved */ 567 568 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 569 570 /* Now we can write the data */ 571 572 Status = AcpiHwWriteMultiple (Value, 573 &AcpiGbl_FADT.XPm1aControlBlock, 574 &AcpiGbl_FADT.XPm1bControlBlock); 575 break; 576 577 578 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 579 580 /* 581 * For control registers, all reserved bits must be preserved, 582 * as per the ACPI spec. 583 */ 584 Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock); 585 if (ACPI_FAILURE (Status)) 586 { 587 goto Exit; 588 } 589 590 /* Insert the bits to be preserved */ 591 592 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); 593 594 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); 595 break; 596 597 598 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 599 600 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); 601 break; 602 603 604 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 605 606 /* SMI_CMD is currently always in IO space */ 607 608 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 609 break; 610 611 612 default: 613 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", 614 RegisterId)); 615 Status = AE_BAD_PARAMETER; 616 break; 617 } 618 619 Exit: 620 return_ACPI_STATUS (Status); 621 } 622 623 624 /****************************************************************************** 625 * 626 * FUNCTION: AcpiHwReadMultiple 627 * 628 * PARAMETERS: Value - Where the register value is returned 629 * RegisterA - First ACPI register (required) 630 * RegisterB - Second ACPI register (optional) 631 * 632 * RETURN: Status 633 * 634 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) 635 * 636 ******************************************************************************/ 637 638 static ACPI_STATUS 639 AcpiHwReadMultiple ( 640 UINT32 *Value, 641 ACPI_GENERIC_ADDRESS *RegisterA, 642 ACPI_GENERIC_ADDRESS *RegisterB) 643 { 644 UINT32 ValueA = 0; 645 UINT32 ValueB = 0; 646 ACPI_STATUS Status; 647 648 649 /* The first register is always required */ 650 651 Status = AcpiHwRead (&ValueA, RegisterA); 652 if (ACPI_FAILURE (Status)) 653 { 654 return (Status); 655 } 656 657 /* Second register is optional */ 658 659 if (RegisterB->Address) 660 { 661 Status = AcpiHwRead (&ValueB, RegisterB); 662 if (ACPI_FAILURE (Status)) 663 { 664 return (Status); 665 } 666 } 667 668 /* 669 * OR the two return values together. No shifting or masking is necessary, 670 * because of how the PM1 registers are defined in the ACPI specification: 671 * 672 * "Although the bits can be split between the two register blocks (each 673 * register block has a unique pointer within the FADT), the bit positions 674 * are maintained. The register block with unimplemented bits (that is, 675 * those implemented in the other register block) always returns zeros, 676 * and writes have no side effects" 677 */ 678 *Value = (ValueA | ValueB); 679 return (AE_OK); 680 } 681 682 683 /****************************************************************************** 684 * 685 * FUNCTION: AcpiHwWriteMultiple 686 * 687 * PARAMETERS: Value - The value to write 688 * RegisterA - First ACPI register (required) 689 * RegisterB - Second ACPI register (optional) 690 * 691 * RETURN: Status 692 * 693 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) 694 * 695 ******************************************************************************/ 696 697 static ACPI_STATUS 698 AcpiHwWriteMultiple ( 699 UINT32 Value, 700 ACPI_GENERIC_ADDRESS *RegisterA, 701 ACPI_GENERIC_ADDRESS *RegisterB) 702 { 703 ACPI_STATUS Status; 704 705 706 /* The first register is always required */ 707 708 Status = AcpiHwWrite (Value, RegisterA); 709 if (ACPI_FAILURE (Status)) 710 { 711 return (Status); 712 } 713 714 /* 715 * Second register is optional 716 * 717 * No bit shifting or clearing is necessary, because of how the PM1 718 * registers are defined in the ACPI specification: 719 * 720 * "Although the bits can be split between the two register blocks (each 721 * register block has a unique pointer within the FADT), the bit positions 722 * are maintained. The register block with unimplemented bits (that is, 723 * those implemented in the other register block) always returns zeros, 724 * and writes have no side effects" 725 */ 726 if (RegisterB->Address) 727 { 728 Status = AcpiHwWrite (Value, RegisterB); 729 } 730 731 return (Status); 732 } 733 734