1 2 /******************************************************************************* 3 * 4 * Module Name: hwregs - Read/write access functions for the various ACPI 5 * control and status registers. 6 * $Revision: 1.188 $ 7 * 8 ******************************************************************************/ 9 10 /****************************************************************************** 11 * 12 * 1. Copyright Notice 13 * 14 * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp. 15 * All rights reserved. 16 * 17 * 2. License 18 * 19 * 2.1. This is your license from Intel Corp. under its intellectual property 20 * rights. You may have additional license terms from the party that provided 21 * you this software, covering your right to use that party's intellectual 22 * property rights. 23 * 24 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 25 * copy of the source code appearing in this file ("Covered Code") an 26 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 27 * base code distributed originally by Intel ("Original Intel Code") to copy, 28 * make derivatives, distribute, use and display any portion of the Covered 29 * Code in any form, with the right to sublicense such rights; and 30 * 31 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 32 * license (with the right to sublicense), under only those claims of Intel 33 * patents that are infringed by the Original Intel Code, to make, use, sell, 34 * offer to sell, and import the Covered Code and derivative works thereof 35 * solely to the minimum extent necessary to exercise the above copyright 36 * license, and in no event shall the patent license extend to any additions 37 * to or modifications of the Original Intel Code. No other license or right 38 * is granted directly or by implication, estoppel or otherwise; 39 * 40 * The above copyright and patent license is granted only if the following 41 * conditions are met: 42 * 43 * 3. Conditions 44 * 45 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 46 * Redistribution of source code of any substantial portion of the Covered 47 * Code or modification with rights to further distribute source must include 48 * the above Copyright Notice, the above License, this list of Conditions, 49 * and the following Disclaimer and Export Compliance provision. In addition, 50 * Licensee must cause all Covered Code to which Licensee contributes to 51 * contain a file documenting the changes Licensee made to create that Covered 52 * Code and the date of any change. Licensee must include in that file the 53 * documentation of any changes made by any predecessor Licensee. Licensee 54 * must include a prominent statement that the modification is derived, 55 * directly or indirectly, from Original Intel Code. 56 * 57 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 58 * Redistribution of source code of any substantial portion of the Covered 59 * Code or modification without rights to further distribute source must 60 * include the following Disclaimer and Export Compliance provision in the 61 * documentation and/or other materials provided with distribution. In 62 * addition, Licensee may not authorize further sublicense of source of any 63 * portion of the Covered Code, and must include terms to the effect that the 64 * license from Licensee to its licensee is limited to the intellectual 65 * property embodied in the software Licensee provides to its licensee, and 66 * not to intellectual property embodied in modifications its licensee may 67 * make. 68 * 69 * 3.3. Redistribution of Executable. Redistribution in executable form of any 70 * substantial portion of the Covered Code or modification must reproduce the 71 * above Copyright Notice, and the following Disclaimer and Export Compliance 72 * provision in the documentation and/or other materials provided with the 73 * distribution. 74 * 75 * 3.4. Intel retains all right, title, and interest in and to the Original 76 * Intel Code. 77 * 78 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 79 * Intel shall be used in advertising or otherwise to promote the sale, use or 80 * other dealings in products derived from or relating to the Covered Code 81 * without prior written authorization from Intel. 82 * 83 * 4. Disclaimer and Export Compliance 84 * 85 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 86 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 87 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 88 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 89 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 90 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 91 * PARTICULAR PURPOSE. 92 * 93 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 94 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 95 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 96 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 97 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 98 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 99 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 100 * LIMITED REMEDY. 101 * 102 * 4.3. Licensee shall not export, either directly or indirectly, any of this 103 * software or system incorporating such software without first obtaining any 104 * required license or other approval from the U. S. Department of Commerce or 105 * any other agency or department of the United States Government. In the 106 * event Licensee exports any such software from the United States or 107 * re-exports any such software from a foreign destination, Licensee shall 108 * ensure that the distribution and export/re-export of the software is in 109 * compliance with all laws, regulations, orders, or other restrictions of the 110 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 111 * any of its subsidiaries will export/re-export any technical data, process, 112 * software, or service, directly or indirectly, to any country for which the 113 * United States government or any agency thereof requires an export license, 114 * other governmental approval, or letter of assurance, without first obtaining 115 * such license, approval or letter. 116 * 117 *****************************************************************************/ 118 119 #define __HWREGS_C__ 120 121 #include "acpi.h" 122 #include "acnamesp.h" 123 #include "acevents.h" 124 125 #define _COMPONENT ACPI_HARDWARE 126 ACPI_MODULE_NAME ("hwregs") 127 128 129 /******************************************************************************* 130 * 131 * FUNCTION: AcpiHwClearAcpiStatus 132 * 133 * PARAMETERS: None 134 * 135 * RETURN: None 136 * 137 * DESCRIPTION: Clears all fixed and general purpose status bits 138 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 139 * 140 ******************************************************************************/ 141 142 ACPI_STATUS 143 AcpiHwClearAcpiStatus ( 144 void) 145 { 146 ACPI_STATUS Status; 147 ACPI_CPU_FLAGS LockFlags = 0; 148 149 150 ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 151 152 153 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n", 154 ACPI_BITMASK_ALL_FIXED_STATUS, 155 (UINT16) AcpiGbl_FADT.XPm1aEventBlock.Address)); 156 157 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 158 159 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 160 ACPI_BITMASK_ALL_FIXED_STATUS); 161 if (ACPI_FAILURE (Status)) 162 { 163 goto UnlockAndExit; 164 } 165 166 /* Clear the fixed events */ 167 168 if (AcpiGbl_FADT.XPm1bEventBlock.Address) 169 { 170 Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS, 171 &AcpiGbl_FADT.XPm1bEventBlock); 172 if (ACPI_FAILURE (Status)) 173 { 174 goto UnlockAndExit; 175 } 176 } 177 178 /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 179 180 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock); 181 182 UnlockAndExit: 183 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 184 return_ACPI_STATUS (Status); 185 } 186 187 188 /******************************************************************************* 189 * 190 * FUNCTION: AcpiGetSleepTypeData 191 * 192 * PARAMETERS: SleepState - Numeric sleep state 193 * *SleepTypeA - Where SLP_TYPa is returned 194 * *SleepTypeB - Where SLP_TYPb is returned 195 * 196 * RETURN: Status - ACPI status 197 * 198 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep 199 * state. 200 * 201 ******************************************************************************/ 202 203 ACPI_STATUS 204 AcpiGetSleepTypeData ( 205 UINT8 SleepState, 206 UINT8 *SleepTypeA, 207 UINT8 *SleepTypeB) 208 { 209 ACPI_STATUS Status = AE_OK; 210 ACPI_EVALUATE_INFO *Info; 211 212 213 ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 214 215 216 /* Validate parameters */ 217 218 if ((SleepState > ACPI_S_STATES_MAX) || 219 !SleepTypeA || !SleepTypeB) 220 { 221 return_ACPI_STATUS (AE_BAD_PARAMETER); 222 } 223 224 /* Allocate the evaluation information block */ 225 226 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 227 if (!Info) 228 { 229 return_ACPI_STATUS (AE_NO_MEMORY); 230 } 231 232 Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); 233 234 /* Evaluate the namespace object containing the values for this state */ 235 236 Status = AcpiNsEvaluate (Info); 237 if (ACPI_FAILURE (Status)) 238 { 239 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 240 "%s while evaluating SleepState [%s]\n", 241 AcpiFormatException (Status), Info->Pathname)); 242 243 goto Cleanup; 244 } 245 246 /* Must have a return object */ 247 248 if (!Info->ReturnObject) 249 { 250 ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 251 Info->Pathname)); 252 Status = AE_NOT_EXIST; 253 } 254 255 /* It must be of type Package */ 256 257 else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE) 258 { 259 ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 260 Status = AE_AML_OPERAND_TYPE; 261 } 262 263 /* 264 * The package must have at least two elements. NOTE (March 2005): This 265 * goes against the current ACPI spec which defines this object as a 266 * package with one encoded DWORD element. However, existing practice 267 * by BIOS vendors seems to be to have 2 or more elements, at least 268 * one per sleep type (A/B). 269 */ 270 else if (Info->ReturnObject->Package.Count < 2) 271 { 272 ACPI_ERROR ((AE_INFO, 273 "Sleep State return package does not have at least two elements")); 274 Status = AE_AML_NO_OPERAND; 275 } 276 277 /* The first two elements must both be of type Integer */ 278 279 else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0]) 280 != ACPI_TYPE_INTEGER) || 281 (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1]) 282 != ACPI_TYPE_INTEGER)) 283 { 284 ACPI_ERROR ((AE_INFO, 285 "Sleep State return package elements are not both Integers (%s, %s)", 286 AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), 287 AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); 288 Status = AE_AML_OPERAND_TYPE; 289 } 290 else 291 { 292 /* Valid _Sx_ package size, type, and value */ 293 294 *SleepTypeA = (UINT8) 295 (Info->ReturnObject->Package.Elements[0])->Integer.Value; 296 *SleepTypeB = (UINT8) 297 (Info->ReturnObject->Package.Elements[1])->Integer.Value; 298 } 299 300 if (ACPI_FAILURE (Status)) 301 { 302 ACPI_EXCEPTION ((AE_INFO, Status, 303 "While evaluating SleepState [%s], bad Sleep object %p type %s", 304 Info->Pathname, Info->ReturnObject, 305 AcpiUtGetObjectTypeName (Info->ReturnObject))); 306 } 307 308 AcpiUtRemoveReference (Info->ReturnObject); 309 310 Cleanup: 311 ACPI_FREE (Info); 312 return_ACPI_STATUS (Status); 313 } 314 315 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 316 317 318 /******************************************************************************* 319 * 320 * FUNCTION: AcpiHwGetRegisterBitMask 321 * 322 * PARAMETERS: RegisterId - Index of ACPI Register to access 323 * 324 * RETURN: The bitmask to be used when accessing the register 325 * 326 * DESCRIPTION: Map RegisterId into a register bitmask. 327 * 328 ******************************************************************************/ 329 330 ACPI_BIT_REGISTER_INFO * 331 AcpiHwGetBitRegisterInfo ( 332 UINT32 RegisterId) 333 { 334 ACPI_FUNCTION_ENTRY (); 335 336 337 if (RegisterId > ACPI_BITREG_MAX) 338 { 339 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId)); 340 return (NULL); 341 } 342 343 return (&AcpiGbl_BitRegisterInfo[RegisterId]); 344 } 345 346 347 /******************************************************************************* 348 * 349 * FUNCTION: AcpiGetRegisterUnlocked 350 * 351 * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 352 * ReturnValue - Value that was read from the register 353 * 354 * RETURN: Status and the value read from specified Register. Value 355 * returned is normalized to bit0 (is shifted all the way right) 356 * 357 * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock. 358 * 359 ******************************************************************************/ 360 361 ACPI_STATUS 362 AcpiGetRegisterUnlocked ( 363 UINT32 RegisterId, 364 UINT32 *ReturnValue) 365 { 366 UINT32 RegisterValue = 0; 367 ACPI_BIT_REGISTER_INFO *BitRegInfo; 368 ACPI_STATUS Status; 369 370 371 ACPI_FUNCTION_TRACE (AcpiGetRegisterUnlocked); 372 373 374 /* Get the info structure corresponding to the requested ACPI Register */ 375 376 BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 377 if (!BitRegInfo) 378 { 379 return_ACPI_STATUS (AE_BAD_PARAMETER); 380 } 381 382 /* Read from the register */ 383 384 Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 385 &RegisterValue); 386 387 if (ACPI_SUCCESS (Status)) 388 { 389 /* Normalize the value that was read */ 390 391 RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) 392 >> BitRegInfo->BitPosition); 393 394 *ReturnValue = RegisterValue; 395 396 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n", 397 RegisterValue, BitRegInfo->ParentRegister)); 398 } 399 400 return_ACPI_STATUS (Status); 401 } 402 403 404 /******************************************************************************* 405 * 406 * FUNCTION: AcpiGetRegister 407 * 408 * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 409 * ReturnValue - Value that was read from the register 410 * 411 * RETURN: Status and the value read from specified Register. Value 412 * returned is normalized to bit0 (is shifted all the way right) 413 * 414 * DESCRIPTION: ACPI BitRegister read function. 415 * 416 ******************************************************************************/ 417 418 ACPI_STATUS 419 AcpiGetRegister ( 420 UINT32 RegisterId, 421 UINT32 *ReturnValue) 422 { 423 ACPI_STATUS Status; 424 ACPI_CPU_FLAGS Flags; 425 426 427 Flags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 428 Status = AcpiGetRegisterUnlocked (RegisterId, ReturnValue); 429 AcpiOsReleaseLock (AcpiGbl_HardwareLock, Flags); 430 431 return (Status); 432 } 433 434 ACPI_EXPORT_SYMBOL (AcpiGetRegister) 435 436 437 /******************************************************************************* 438 * 439 * FUNCTION: AcpiSetRegister 440 * 441 * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 442 * Value - (only used on write) value to write to the 443 * Register, NOT pre-normalized to the bit pos 444 * 445 * RETURN: Status 446 * 447 * DESCRIPTION: ACPI Bit Register write function. 448 * 449 ******************************************************************************/ 450 451 ACPI_STATUS 452 AcpiSetRegister ( 453 UINT32 RegisterId, 454 UINT32 Value) 455 { 456 UINT32 RegisterValue = 0; 457 ACPI_BIT_REGISTER_INFO *BitRegInfo; 458 ACPI_STATUS Status; 459 ACPI_CPU_FLAGS LockFlags; 460 461 462 ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId); 463 464 465 /* Get the info structure corresponding to the requested ACPI Register */ 466 467 BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 468 if (!BitRegInfo) 469 { 470 ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId)); 471 return_ACPI_STATUS (AE_BAD_PARAMETER); 472 } 473 474 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 475 476 /* Always do a register read first so we can insert the new bits */ 477 478 Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 479 &RegisterValue); 480 if (ACPI_FAILURE (Status)) 481 { 482 goto UnlockAndExit; 483 } 484 485 /* 486 * Decode the Register ID 487 * Register ID = [Register block ID] | [bit ID] 488 * 489 * Check bit ID to fine locate Register offset. 490 * Check Mask to determine Register offset, and then read-write. 491 */ 492 switch (BitRegInfo->ParentRegister) 493 { 494 case ACPI_REGISTER_PM1_STATUS: 495 496 /* 497 * Status Registers are different from the rest. Clear by 498 * writing 1, and writing 0 has no effect. So, the only relevant 499 * information is the single bit we're interested in, all others should 500 * be written as 0 so they will be left unchanged. 501 */ 502 Value = ACPI_REGISTER_PREPARE_BITS (Value, 503 BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 504 if (Value) 505 { 506 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 507 (UINT16) Value); 508 RegisterValue = 0; 509 } 510 break; 511 512 513 case ACPI_REGISTER_PM1_ENABLE: 514 515 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 516 BitRegInfo->AccessBitMask, Value); 517 518 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_ENABLE, 519 (UINT16) RegisterValue); 520 break; 521 522 523 case ACPI_REGISTER_PM1_CONTROL: 524 525 /* 526 * Write the PM1 Control register. 527 * Note that at this level, the fact that there are actually TWO 528 * registers (A and B - and B may not exist) is abstracted. 529 */ 530 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", 531 RegisterValue)); 532 533 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 534 BitRegInfo->AccessBitMask, Value); 535 536 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL, 537 (UINT16) RegisterValue); 538 break; 539 540 541 case ACPI_REGISTER_PM2_CONTROL: 542 543 Status = AcpiHwRegisterRead (ACPI_REGISTER_PM2_CONTROL, 544 &RegisterValue); 545 if (ACPI_FAILURE (Status)) 546 { 547 goto UnlockAndExit; 548 } 549 550 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", 551 RegisterValue, 552 ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address))); 553 554 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 555 BitRegInfo->AccessBitMask, Value); 556 557 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", 558 RegisterValue, 559 ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XPm2ControlBlock.Address))); 560 561 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM2_CONTROL, 562 (UINT8) (RegisterValue)); 563 break; 564 565 566 default: 567 break; 568 } 569 570 571 UnlockAndExit: 572 573 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 574 575 /* Normalize the value that was read */ 576 577 ACPI_DEBUG_EXEC (RegisterValue = 578 ((RegisterValue & BitRegInfo->AccessBitMask) >> 579 BitRegInfo->BitPosition)); 580 581 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n", 582 Value, RegisterValue, BitRegInfo->ParentRegister)); 583 return_ACPI_STATUS (Status); 584 } 585 586 ACPI_EXPORT_SYMBOL (AcpiSetRegister) 587 588 589 /****************************************************************************** 590 * 591 * FUNCTION: AcpiHwRegisterRead 592 * 593 * PARAMETERS: RegisterId - ACPI Register ID 594 * ReturnValue - Where the register value is returned 595 * 596 * RETURN: Status and the value read. 597 * 598 * DESCRIPTION: Read from the specified ACPI register 599 * 600 ******************************************************************************/ 601 602 ACPI_STATUS 603 AcpiHwRegisterRead ( 604 UINT32 RegisterId, 605 UINT32 *ReturnValue) 606 { 607 UINT32 Value1 = 0; 608 UINT32 Value2 = 0; 609 ACPI_STATUS Status; 610 611 612 ACPI_FUNCTION_TRACE (HwRegisterRead); 613 614 615 switch (RegisterId) 616 { 617 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ 618 619 Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aEventBlock); 620 if (ACPI_FAILURE (Status)) 621 { 622 goto Exit; 623 } 624 625 /* PM1B is optional */ 626 627 Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bEventBlock); 628 Value1 |= Value2; 629 break; 630 631 632 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ 633 634 Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable); 635 if (ACPI_FAILURE (Status)) 636 { 637 goto Exit; 638 } 639 640 /* PM1B is optional */ 641 642 Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable); 643 Value1 |= Value2; 644 break; 645 646 647 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ 648 649 Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT.XPm1aControlBlock); 650 if (ACPI_FAILURE (Status)) 651 { 652 goto Exit; 653 } 654 655 Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT.XPm1bControlBlock); 656 Value1 |= Value2; 657 break; 658 659 660 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 661 662 Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT.XPm2ControlBlock); 663 break; 664 665 666 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 667 668 Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT.XPmTimerBlock); 669 break; 670 671 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 672 673 Status = AcpiOsReadPort (AcpiGbl_FADT.SmiCommand, &Value1, 8); 674 break; 675 676 default: 677 ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 678 RegisterId)); 679 Status = AE_BAD_PARAMETER; 680 break; 681 } 682 683 Exit: 684 if (ACPI_SUCCESS (Status)) 685 { 686 *ReturnValue = Value1; 687 } 688 689 return_ACPI_STATUS (Status); 690 } 691 692 693 /****************************************************************************** 694 * 695 * FUNCTION: AcpiHwRegisterWrite 696 * 697 * PARAMETERS: RegisterId - ACPI Register ID 698 * Value - The value to write 699 * 700 * RETURN: Status 701 * 702 * DESCRIPTION: Write to the specified ACPI register 703 * 704 * NOTE: In accordance with the ACPI specification, this function automatically 705 * preserves the value of the following bits, meaning that these bits cannot be 706 * changed via this interface: 707 * 708 * PM1_CONTROL[0] = SCI_EN 709 * PM1_CONTROL[9] 710 * PM1_STATUS[11] 711 * 712 * ACPI References: 713 * 1) Hardware Ignored Bits: When software writes to a register with ignored 714 * bit fields, it preserves the ignored bit fields 715 * 2) SCI_EN: OSPM always preserves this bit position 716 * 717 ******************************************************************************/ 718 719 ACPI_STATUS 720 AcpiHwRegisterWrite ( 721 UINT32 RegisterId, 722 UINT32 Value) 723 { 724 ACPI_STATUS Status; 725 UINT32 ReadValue; 726 727 728 ACPI_FUNCTION_TRACE (HwRegisterWrite); 729 730 731 switch (RegisterId) 732 { 733 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ 734 735 /* Perform a read first to preserve certain bits (per ACPI spec) */ 736 737 Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, 738 &ReadValue); 739 if (ACPI_FAILURE (Status)) 740 { 741 goto Exit; 742 } 743 744 /* Insert the bits to be preserved */ 745 746 ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue); 747 748 /* Now we can write the data */ 749 750 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aEventBlock); 751 if (ACPI_FAILURE (Status)) 752 { 753 goto Exit; 754 } 755 756 /* PM1B is optional */ 757 758 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bEventBlock); 759 break; 760 761 762 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ 763 764 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable); 765 if (ACPI_FAILURE (Status)) 766 { 767 goto Exit; 768 } 769 770 /* PM1B is optional */ 771 772 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable); 773 break; 774 775 776 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ 777 778 /* 779 * Perform a read first to preserve certain bits (per ACPI spec) 780 * 781 * Note: This includes SCI_EN, we never want to change this bit 782 */ 783 Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL, 784 &ReadValue); 785 if (ACPI_FAILURE (Status)) 786 { 787 goto Exit; 788 } 789 790 /* Insert the bits to be preserved */ 791 792 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 793 794 /* Now we can write the data */ 795 796 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock); 797 if (ACPI_FAILURE (Status)) 798 { 799 goto Exit; 800 } 801 802 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock); 803 break; 804 805 806 case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ 807 808 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1aControlBlock); 809 break; 810 811 812 case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ 813 814 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT.XPm1bControlBlock); 815 break; 816 817 818 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 819 820 Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT.XPm2ControlBlock); 821 break; 822 823 824 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 825 826 Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT.XPmTimerBlock); 827 break; 828 829 830 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 831 832 /* SMI_CMD is currently always in IO space */ 833 834 Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 835 break; 836 837 838 default: 839 Status = AE_BAD_PARAMETER; 840 break; 841 } 842 843 Exit: 844 return_ACPI_STATUS (Status); 845 } 846 847 848 /****************************************************************************** 849 * 850 * FUNCTION: AcpiHwLowLevelRead 851 * 852 * PARAMETERS: Width - 8, 16, or 32 853 * Value - Where the value is returned 854 * Reg - GAS register structure 855 * 856 * RETURN: Status 857 * 858 * DESCRIPTION: Read from either memory or IO space. 859 * 860 ******************************************************************************/ 861 862 ACPI_STATUS 863 AcpiHwLowLevelRead ( 864 UINT32 Width, 865 UINT32 *Value, 866 ACPI_GENERIC_ADDRESS *Reg) 867 { 868 UINT64 Address; 869 ACPI_STATUS Status; 870 871 872 ACPI_FUNCTION_NAME (HwLowLevelRead); 873 874 875 /* 876 * Must have a valid pointer to a GAS structure, and 877 * a non-zero address within. However, don't return an error 878 * because the PM1A/B code must not fail if B isn't present. 879 */ 880 if (!Reg) 881 { 882 return (AE_OK); 883 } 884 885 /* Get a local copy of the address. Handles possible alignment issues */ 886 887 ACPI_MOVE_64_TO_64 (&Address, &Reg->Address); 888 if (!Address) 889 { 890 return (AE_OK); 891 } 892 *Value = 0; 893 894 /* 895 * Two address spaces supported: Memory or IO. 896 * PCI_Config is not supported here because the GAS struct is insufficient 897 */ 898 switch (Reg->SpaceId) 899 { 900 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 901 902 Status = AcpiOsReadMemory ( 903 (ACPI_PHYSICAL_ADDRESS) Address, Value, Width); 904 break; 905 906 907 case ACPI_ADR_SPACE_SYSTEM_IO: 908 909 Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) Address, Value, Width); 910 break; 911 912 913 default: 914 ACPI_ERROR ((AE_INFO, 915 "Unsupported address space: %X", Reg->SpaceId)); 916 return (AE_BAD_PARAMETER); 917 } 918 919 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 920 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", 921 *Value, Width, ACPI_FORMAT_UINT64 (Address), 922 AcpiUtGetRegionName (Reg->SpaceId))); 923 924 return (Status); 925 } 926 927 928 /****************************************************************************** 929 * 930 * FUNCTION: AcpiHwLowLevelWrite 931 * 932 * PARAMETERS: Width - 8, 16, or 32 933 * Value - To be written 934 * Reg - GAS register structure 935 * 936 * RETURN: Status 937 * 938 * DESCRIPTION: Write to either memory or IO space. 939 * 940 ******************************************************************************/ 941 942 ACPI_STATUS 943 AcpiHwLowLevelWrite ( 944 UINT32 Width, 945 UINT32 Value, 946 ACPI_GENERIC_ADDRESS *Reg) 947 { 948 UINT64 Address; 949 ACPI_STATUS Status; 950 951 952 ACPI_FUNCTION_NAME (HwLowLevelWrite); 953 954 955 /* 956 * Must have a valid pointer to a GAS structure, and 957 * a non-zero address within. However, don't return an error 958 * because the PM1A/B code must not fail if B isn't present. 959 */ 960 if (!Reg) 961 { 962 return (AE_OK); 963 } 964 965 /* Get a local copy of the address. Handles possible alignment issues */ 966 967 ACPI_MOVE_64_TO_64 (&Address, &Reg->Address); 968 if (!Address) 969 { 970 return (AE_OK); 971 } 972 973 /* 974 * Two address spaces supported: Memory or IO. 975 * PCI_Config is not supported here because the GAS struct is insufficient 976 */ 977 switch (Reg->SpaceId) 978 { 979 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 980 981 Status = AcpiOsWriteMemory ( 982 (ACPI_PHYSICAL_ADDRESS) Address, Value, Width); 983 break; 984 985 986 case ACPI_ADR_SPACE_SYSTEM_IO: 987 988 Status = AcpiOsWritePort ( 989 (ACPI_IO_ADDRESS) Address, Value, Width); 990 break; 991 992 993 default: 994 ACPI_ERROR ((AE_INFO, 995 "Unsupported address space: %X", Reg->SpaceId)); 996 return (AE_BAD_PARAMETER); 997 } 998 999 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 1000 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 1001 Value, Width, ACPI_FORMAT_UINT64 (Address), 1002 AcpiUtGetRegionName (Reg->SpaceId))); 1003 1004 return (Status); 1005 } 1006