1 2 /******************************************************************************* 3 * 4 * Module Name: hwregs - Read/write access functions for the various ACPI 5 * control and status registers. 6 * $Revision: 1.183 $ 7 * 8 ******************************************************************************/ 9 10 /****************************************************************************** 11 * 12 * 1. Copyright Notice 13 * 14 * Some or all of this work - Copyright (c) 1999 - 2006, 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: Flags - Lock the hardware or not 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 * NOTE: TBD: Flags parameter is obsolete, to be removed 141 * 142 ******************************************************************************/ 143 144 ACPI_STATUS 145 AcpiHwClearAcpiStatus ( 146 UINT32 Flags) 147 { 148 ACPI_STATUS Status; 149 ACPI_CPU_FLAGS LockFlags = 0; 150 151 152 ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 153 154 155 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %04X\n", 156 ACPI_BITMASK_ALL_FIXED_STATUS, 157 (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address))); 158 159 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 160 161 Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 162 ACPI_REGISTER_PM1_STATUS, 163 ACPI_BITMASK_ALL_FIXED_STATUS); 164 if (ACPI_FAILURE (Status)) 165 { 166 goto UnlockAndExit; 167 } 168 169 /* Clear the fixed events */ 170 171 if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address)) 172 { 173 Status = AcpiHwLowLevelWrite (16, ACPI_BITMASK_ALL_FIXED_STATUS, 174 &AcpiGbl_FADT->XPm1bEvtBlk); 175 if (ACPI_FAILURE (Status)) 176 { 177 goto UnlockAndExit; 178 } 179 } 180 181 /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 182 183 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock); 184 185 UnlockAndExit: 186 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 187 return_ACPI_STATUS (Status); 188 } 189 190 191 /******************************************************************************* 192 * 193 * FUNCTION: AcpiGetSleepTypeData 194 * 195 * PARAMETERS: SleepState - Numeric sleep state 196 * *SleepTypeA - Where SLP_TYPa is returned 197 * *SleepTypeB - Where SLP_TYPb is returned 198 * 199 * RETURN: Status - ACPI status 200 * 201 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep 202 * state. 203 * 204 ******************************************************************************/ 205 206 ACPI_STATUS 207 AcpiGetSleepTypeData ( 208 UINT8 SleepState, 209 UINT8 *SleepTypeA, 210 UINT8 *SleepTypeB) 211 { 212 ACPI_STATUS Status = AE_OK; 213 ACPI_EVALUATE_INFO *Info; 214 215 216 ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 217 218 219 /* Validate parameters */ 220 221 if ((SleepState > ACPI_S_STATES_MAX) || 222 !SleepTypeA || !SleepTypeB) 223 { 224 return_ACPI_STATUS (AE_BAD_PARAMETER); 225 } 226 227 /* Allocate the evaluation information block */ 228 229 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 230 if (!Info) 231 { 232 return_ACPI_STATUS (AE_NO_MEMORY); 233 } 234 235 Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); 236 237 /* Evaluate the namespace object containing the values for this state */ 238 239 Status = AcpiNsEvaluate (Info); 240 if (ACPI_FAILURE (Status)) 241 { 242 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 243 "%s while evaluating SleepState [%s]\n", 244 AcpiFormatException (Status), Info->Pathname)); 245 246 goto Cleanup; 247 } 248 249 /* Must have a return object */ 250 251 if (!Info->ReturnObject) 252 { 253 ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 254 Info->Pathname)); 255 Status = AE_NOT_EXIST; 256 } 257 258 /* It must be of type Package */ 259 260 else if (ACPI_GET_OBJECT_TYPE (Info->ReturnObject) != ACPI_TYPE_PACKAGE) 261 { 262 ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 263 Status = AE_AML_OPERAND_TYPE; 264 } 265 266 /* 267 * The package must have at least two elements. NOTE (March 2005): This 268 * goes against the current ACPI spec which defines this object as a 269 * package with one encoded DWORD element. However, existing practice 270 * by BIOS vendors seems to be to have 2 or more elements, at least 271 * one per sleep type (A/B). 272 */ 273 else if (Info->ReturnObject->Package.Count < 2) 274 { 275 ACPI_ERROR ((AE_INFO, 276 "Sleep State return package does not have at least two elements")); 277 Status = AE_AML_NO_OPERAND; 278 } 279 280 /* The first two elements must both be of type Integer */ 281 282 else if ((ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[0]) 283 != ACPI_TYPE_INTEGER) || 284 (ACPI_GET_OBJECT_TYPE (Info->ReturnObject->Package.Elements[1]) 285 != ACPI_TYPE_INTEGER)) 286 { 287 ACPI_ERROR ((AE_INFO, 288 "Sleep State return package elements are not both Integers (%s, %s)", 289 AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), 290 AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); 291 Status = AE_AML_OPERAND_TYPE; 292 } 293 else 294 { 295 /* Valid _Sx_ package size, type, and value */ 296 297 *SleepTypeA = (UINT8) 298 (Info->ReturnObject->Package.Elements[0])->Integer.Value; 299 *SleepTypeB = (UINT8) 300 (Info->ReturnObject->Package.Elements[1])->Integer.Value; 301 } 302 303 if (ACPI_FAILURE (Status)) 304 { 305 ACPI_EXCEPTION ((AE_INFO, Status, 306 "While evaluating SleepState [%s], bad Sleep object %p type %s", 307 Info->Pathname, Info->ReturnObject, 308 AcpiUtGetObjectTypeName (Info->ReturnObject))); 309 } 310 311 AcpiUtRemoveReference (Info->ReturnObject); 312 313 Cleanup: 314 ACPI_FREE (Info); 315 return_ACPI_STATUS (Status); 316 } 317 318 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 319 320 321 /******************************************************************************* 322 * 323 * FUNCTION: AcpiHwGetRegisterBitMask 324 * 325 * PARAMETERS: RegisterId - Index of ACPI Register to access 326 * 327 * RETURN: The bitmask to be used when accessing the register 328 * 329 * DESCRIPTION: Map RegisterId into a register bitmask. 330 * 331 ******************************************************************************/ 332 333 ACPI_BIT_REGISTER_INFO * 334 AcpiHwGetBitRegisterInfo ( 335 UINT32 RegisterId) 336 { 337 ACPI_FUNCTION_ENTRY (); 338 339 340 if (RegisterId > ACPI_BITREG_MAX) 341 { 342 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: %X", RegisterId)); 343 return (NULL); 344 } 345 346 return (&AcpiGbl_BitRegisterInfo[RegisterId]); 347 } 348 349 350 /******************************************************************************* 351 * 352 * FUNCTION: AcpiGetRegister 353 * 354 * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 355 * ReturnValue - Value that was read from the register 356 * Flags - Lock the hardware or not 357 * 358 * RETURN: Status and the value read from specified Register. Value 359 * returned is normalized to bit0 (is shifted all the way right) 360 * 361 * DESCRIPTION: ACPI BitRegister read function. 362 * 363 * NOTE: TBD: Flags parameter is obsolete, to be removed 364 * 365 ******************************************************************************/ 366 367 ACPI_STATUS 368 AcpiGetRegister ( 369 UINT32 RegisterId, 370 UINT32 *ReturnValue, 371 UINT32 Flags) 372 { 373 UINT32 RegisterValue = 0; 374 ACPI_BIT_REGISTER_INFO *BitRegInfo; 375 ACPI_STATUS Status; 376 377 378 ACPI_FUNCTION_TRACE (AcpiGetRegister); 379 380 381 /* Get the info structure corresponding to the requested ACPI Register */ 382 383 BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 384 if (!BitRegInfo) 385 { 386 return_ACPI_STATUS (AE_BAD_PARAMETER); 387 } 388 389 /* Read from the register */ 390 391 Status = AcpiHwRegisterRead (ACPI_MTX_LOCK, 392 BitRegInfo->ParentRegister, &RegisterValue); 393 394 if (ACPI_SUCCESS (Status)) 395 { 396 /* Normalize the value that was read */ 397 398 RegisterValue = ((RegisterValue & BitRegInfo->AccessBitMask) 399 >> BitRegInfo->BitPosition); 400 401 *ReturnValue = RegisterValue; 402 403 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read value %8.8X register %X\n", 404 RegisterValue, BitRegInfo->ParentRegister)); 405 } 406 407 return_ACPI_STATUS (Status); 408 } 409 410 ACPI_EXPORT_SYMBOL (AcpiGetRegister) 411 412 413 /******************************************************************************* 414 * 415 * FUNCTION: AcpiSetRegister 416 * 417 * PARAMETERS: RegisterId - ID of ACPI BitRegister to access 418 * Value - (only used on write) value to write to the 419 * Register, NOT pre-normalized to the bit pos 420 * Flags - Lock the hardware or not 421 * 422 * RETURN: Status 423 * 424 * DESCRIPTION: ACPI Bit Register write function. 425 * 426 * NOTE: TBD: Flags parameter is obsolete, to be removed 427 * 428 ******************************************************************************/ 429 430 ACPI_STATUS 431 AcpiSetRegister ( 432 UINT32 RegisterId, 433 UINT32 Value, 434 UINT32 Flags) 435 { 436 UINT32 RegisterValue = 0; 437 ACPI_BIT_REGISTER_INFO *BitRegInfo; 438 ACPI_STATUS Status; 439 ACPI_CPU_FLAGS LockFlags; 440 441 442 ACPI_FUNCTION_TRACE_U32 (AcpiSetRegister, RegisterId); 443 444 445 /* Get the info structure corresponding to the requested ACPI Register */ 446 447 BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 448 if (!BitRegInfo) 449 { 450 ACPI_ERROR ((AE_INFO, "Bad ACPI HW RegisterId: %X", RegisterId)); 451 return_ACPI_STATUS (AE_BAD_PARAMETER); 452 } 453 454 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 455 456 /* Always do a register read first so we can insert the new bits */ 457 458 Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 459 BitRegInfo->ParentRegister, &RegisterValue); 460 if (ACPI_FAILURE (Status)) 461 { 462 goto UnlockAndExit; 463 } 464 465 /* 466 * Decode the Register ID 467 * Register ID = [Register block ID] | [bit ID] 468 * 469 * Check bit ID to fine locate Register offset. 470 * Check Mask to determine Register offset, and then read-write. 471 */ 472 switch (BitRegInfo->ParentRegister) 473 { 474 case ACPI_REGISTER_PM1_STATUS: 475 476 /* 477 * Status Registers are different from the rest. Clear by 478 * writing 1, and writing 0 has no effect. So, the only relevant 479 * information is the single bit we're interested in, all others should 480 * be written as 0 so they will be left unchanged. 481 */ 482 Value = ACPI_REGISTER_PREPARE_BITS (Value, 483 BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 484 if (Value) 485 { 486 Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 487 ACPI_REGISTER_PM1_STATUS, (UINT16) Value); 488 RegisterValue = 0; 489 } 490 break; 491 492 493 case ACPI_REGISTER_PM1_ENABLE: 494 495 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 496 BitRegInfo->AccessBitMask, Value); 497 498 Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 499 ACPI_REGISTER_PM1_ENABLE, (UINT16) RegisterValue); 500 break; 501 502 503 case ACPI_REGISTER_PM1_CONTROL: 504 505 /* 506 * Write the PM1 Control register. 507 * Note that at this level, the fact that there are actually TWO 508 * registers (A and B - and B may not exist) is abstracted. 509 */ 510 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", 511 RegisterValue)); 512 513 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 514 BitRegInfo->AccessBitMask, Value); 515 516 Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 517 ACPI_REGISTER_PM1_CONTROL, (UINT16) RegisterValue); 518 break; 519 520 521 case ACPI_REGISTER_PM2_CONTROL: 522 523 Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 524 ACPI_REGISTER_PM2_CONTROL, &RegisterValue); 525 if (ACPI_FAILURE (Status)) 526 { 527 goto UnlockAndExit; 528 } 529 530 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM2 control: Read %X from %8.8X%8.8X\n", 531 RegisterValue, 532 ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS ( 533 AcpiGbl_FADT->XPm2CntBlk.Address)))); 534 535 ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 536 BitRegInfo->AccessBitMask, Value); 537 538 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %4.4X to %8.8X%8.8X\n", 539 RegisterValue, 540 ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS ( 541 AcpiGbl_FADT->XPm2CntBlk.Address)))); 542 543 Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 544 ACPI_REGISTER_PM2_CONTROL, (UINT8) (RegisterValue)); 545 break; 546 547 548 default: 549 break; 550 } 551 552 553 UnlockAndExit: 554 555 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 556 557 /* Normalize the value that was read */ 558 559 ACPI_DEBUG_EXEC (RegisterValue = 560 ((RegisterValue & BitRegInfo->AccessBitMask) >> 561 BitRegInfo->BitPosition)); 562 563 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Set bits: %8.8X actual %8.8X register %X\n", 564 Value, RegisterValue, BitRegInfo->ParentRegister)); 565 return_ACPI_STATUS (Status); 566 } 567 568 ACPI_EXPORT_SYMBOL (AcpiSetRegister) 569 570 571 /****************************************************************************** 572 * 573 * FUNCTION: AcpiHwRegisterRead 574 * 575 * PARAMETERS: UseLock - Lock hardware? True/False 576 * RegisterId - ACPI Register ID 577 * ReturnValue - Where the register value is returned 578 * 579 * RETURN: Status and the value read. 580 * 581 * DESCRIPTION: Read from the specified ACPI register 582 * 583 ******************************************************************************/ 584 585 ACPI_STATUS 586 AcpiHwRegisterRead ( 587 BOOLEAN UseLock, 588 UINT32 RegisterId, 589 UINT32 *ReturnValue) 590 { 591 UINT32 Value1 = 0; 592 UINT32 Value2 = 0; 593 ACPI_STATUS Status; 594 ACPI_CPU_FLAGS LockFlags = 0; 595 596 597 ACPI_FUNCTION_TRACE (HwRegisterRead); 598 599 600 if (ACPI_MTX_LOCK == UseLock) 601 { 602 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 603 } 604 605 switch (RegisterId) 606 { 607 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ 608 609 Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aEvtBlk); 610 if (ACPI_FAILURE (Status)) 611 { 612 goto UnlockAndExit; 613 } 614 615 /* PM1B is optional */ 616 617 Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bEvtBlk); 618 Value1 |= Value2; 619 break; 620 621 622 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ 623 624 Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_XPm1aEnable); 625 if (ACPI_FAILURE (Status)) 626 { 627 goto UnlockAndExit; 628 } 629 630 /* PM1B is optional */ 631 632 Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_XPm1bEnable); 633 Value1 |= Value2; 634 break; 635 636 637 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ 638 639 Status = AcpiHwLowLevelRead (16, &Value1, &AcpiGbl_FADT->XPm1aCntBlk); 640 if (ACPI_FAILURE (Status)) 641 { 642 goto UnlockAndExit; 643 } 644 645 Status = AcpiHwLowLevelRead (16, &Value2, &AcpiGbl_FADT->XPm1bCntBlk); 646 Value1 |= Value2; 647 break; 648 649 650 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 651 652 Status = AcpiHwLowLevelRead (8, &Value1, &AcpiGbl_FADT->XPm2CntBlk); 653 break; 654 655 656 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 657 658 Status = AcpiHwLowLevelRead (32, &Value1, &AcpiGbl_FADT->XPmTmrBlk); 659 break; 660 661 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 662 663 Status = AcpiOsReadPort (AcpiGbl_FADT->SmiCmd, &Value1, 8); 664 break; 665 666 default: 667 ACPI_ERROR ((AE_INFO, "Unknown Register ID: %X", 668 RegisterId)); 669 Status = AE_BAD_PARAMETER; 670 break; 671 } 672 673 UnlockAndExit: 674 if (ACPI_MTX_LOCK == UseLock) 675 { 676 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 677 } 678 679 if (ACPI_SUCCESS (Status)) 680 { 681 *ReturnValue = Value1; 682 } 683 684 return_ACPI_STATUS (Status); 685 } 686 687 688 /****************************************************************************** 689 * 690 * FUNCTION: AcpiHwRegisterWrite 691 * 692 * PARAMETERS: UseLock - Lock hardware? True/False 693 * RegisterId - ACPI Register ID 694 * Value - The value to write 695 * 696 * RETURN: Status 697 * 698 * DESCRIPTION: Write to the specified ACPI register 699 * 700 * NOTE: In accordance with the ACPI specification, this function automatically 701 * preserves the value of the following bits, meaning that these bits cannot be 702 * changed via this interface: 703 * 704 * PM1_CONTROL[0] = SCI_EN 705 * PM1_CONTROL[9] 706 * PM1_STATUS[11] 707 * 708 * ACPI References: 709 * 1) Hardware Ignored Bits: When software writes to a register with ignored 710 * bit fields, it preserves the ignored bit fields 711 * 2) SCI_EN: OSPM always preserves this bit position 712 * 713 ******************************************************************************/ 714 715 ACPI_STATUS 716 AcpiHwRegisterWrite ( 717 BOOLEAN UseLock, 718 UINT32 RegisterId, 719 UINT32 Value) 720 { 721 ACPI_STATUS Status; 722 ACPI_CPU_FLAGS LockFlags = 0; 723 UINT32 ReadValue; 724 725 726 ACPI_FUNCTION_TRACE (HwRegisterWrite); 727 728 729 if (ACPI_MTX_LOCK == UseLock) 730 { 731 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 732 } 733 734 switch (RegisterId) 735 { 736 case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ 737 738 /* Perform a read first to preserve certain bits (per ACPI spec) */ 739 740 Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 741 ACPI_REGISTER_PM1_STATUS, &ReadValue); 742 if (ACPI_FAILURE (Status)) 743 { 744 goto UnlockAndExit; 745 } 746 747 /* Insert the bits to be preserved */ 748 749 ACPI_INSERT_BITS (Value, ACPI_PM1_STATUS_PRESERVED_BITS, ReadValue); 750 751 /* Now we can write the data */ 752 753 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk); 754 if (ACPI_FAILURE (Status)) 755 { 756 goto UnlockAndExit; 757 } 758 759 /* PM1B is optional */ 760 761 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk); 762 break; 763 764 765 case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ 766 767 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1aEnable); 768 if (ACPI_FAILURE (Status)) 769 { 770 goto UnlockAndExit; 771 } 772 773 /* PM1B is optional */ 774 775 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_XPm1bEnable); 776 break; 777 778 779 case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ 780 781 /* 782 * Perform a read first to preserve certain bits (per ACPI spec) 783 * 784 * Note: This includes SCI_EN, we never want to change this bit 785 */ 786 Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 787 ACPI_REGISTER_PM1_CONTROL, &ReadValue); 788 if (ACPI_FAILURE (Status)) 789 { 790 goto UnlockAndExit; 791 } 792 793 /* Insert the bits to be preserved */ 794 795 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 796 797 /* Now we can write the data */ 798 799 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk); 800 if (ACPI_FAILURE (Status)) 801 { 802 goto UnlockAndExit; 803 } 804 805 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk); 806 break; 807 808 809 case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ 810 811 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk); 812 break; 813 814 815 case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ 816 817 Status = AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk); 818 break; 819 820 821 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 822 823 Status = AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk); 824 break; 825 826 827 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 828 829 Status = AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk); 830 break; 831 832 833 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 834 835 /* SMI_CMD is currently always in IO space */ 836 837 Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, Value, 8); 838 break; 839 840 841 default: 842 Status = AE_BAD_PARAMETER; 843 break; 844 } 845 846 UnlockAndExit: 847 if (ACPI_MTX_LOCK == UseLock) 848 { 849 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 850 } 851 852 return_ACPI_STATUS (Status); 853 } 854 855 856 /****************************************************************************** 857 * 858 * FUNCTION: AcpiHwLowLevelRead 859 * 860 * PARAMETERS: Width - 8, 16, or 32 861 * Value - Where the value is returned 862 * Reg - GAS register structure 863 * 864 * RETURN: Status 865 * 866 * DESCRIPTION: Read from either memory or IO space. 867 * 868 ******************************************************************************/ 869 870 ACPI_STATUS 871 AcpiHwLowLevelRead ( 872 UINT32 Width, 873 UINT32 *Value, 874 ACPI_GENERIC_ADDRESS *Reg) 875 { 876 UINT64 Address; 877 ACPI_STATUS Status; 878 879 880 ACPI_FUNCTION_NAME (HwLowLevelRead); 881 882 883 /* 884 * Must have a valid pointer to a GAS structure, and 885 * a non-zero address within. However, don't return an error 886 * because the PM1A/B code must not fail if B isn't present. 887 */ 888 if (!Reg) 889 { 890 return (AE_OK); 891 } 892 893 /* Get a local copy of the address. Handles possible alignment issues */ 894 895 ACPI_MOVE_64_TO_64 (&Address, &Reg->Address); 896 if (!ACPI_VALID_ADDRESS (Address)) 897 { 898 return (AE_OK); 899 } 900 *Value = 0; 901 902 /* 903 * Two address spaces supported: Memory or IO. 904 * PCI_Config is not supported here because the GAS struct is insufficient 905 */ 906 switch (Reg->AddressSpaceId) 907 { 908 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 909 910 Status = AcpiOsReadMemory ( 911 (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Address), 912 Value, Width); 913 break; 914 915 916 case ACPI_ADR_SPACE_SYSTEM_IO: 917 918 Status = AcpiOsReadPort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Address), 919 Value, Width); 920 break; 921 922 923 default: 924 ACPI_ERROR ((AE_INFO, 925 "Unsupported address space: %X", Reg->AddressSpaceId)); 926 return (AE_BAD_PARAMETER); 927 } 928 929 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 930 "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", 931 *Value, Width, 932 ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Address)), 933 AcpiUtGetRegionName (Reg->AddressSpaceId))); 934 935 return (Status); 936 } 937 938 939 /****************************************************************************** 940 * 941 * FUNCTION: AcpiHwLowLevelWrite 942 * 943 * PARAMETERS: Width - 8, 16, or 32 944 * Value - To be written 945 * Reg - GAS register structure 946 * 947 * RETURN: Status 948 * 949 * DESCRIPTION: Write to either memory or IO space. 950 * 951 ******************************************************************************/ 952 953 ACPI_STATUS 954 AcpiHwLowLevelWrite ( 955 UINT32 Width, 956 UINT32 Value, 957 ACPI_GENERIC_ADDRESS *Reg) 958 { 959 UINT64 Address; 960 ACPI_STATUS Status; 961 962 963 ACPI_FUNCTION_NAME (HwLowLevelWrite); 964 965 966 /* 967 * Must have a valid pointer to a GAS structure, and 968 * a non-zero address within. However, don't return an error 969 * because the PM1A/B code must not fail if B isn't present. 970 */ 971 if (!Reg) 972 { 973 return (AE_OK); 974 } 975 976 /* Get a local copy of the address. Handles possible alignment issues */ 977 978 ACPI_MOVE_64_TO_64 (&Address, &Reg->Address); 979 if (!ACPI_VALID_ADDRESS (Address)) 980 { 981 return (AE_OK); 982 } 983 984 /* 985 * Two address spaces supported: Memory or IO. 986 * PCI_Config is not supported here because the GAS struct is insufficient 987 */ 988 switch (Reg->AddressSpaceId) 989 { 990 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 991 992 Status = AcpiOsWriteMemory ( 993 (ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (Address), 994 Value, Width); 995 break; 996 997 998 case ACPI_ADR_SPACE_SYSTEM_IO: 999 1000 Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (Address), 1001 Value, Width); 1002 break; 1003 1004 1005 default: 1006 ACPI_ERROR ((AE_INFO, 1007 "Unsupported address space: %X", Reg->AddressSpaceId)); 1008 return (AE_BAD_PARAMETER); 1009 } 1010 1011 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 1012 "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", 1013 Value, Width, 1014 ACPI_FORMAT_UINT64 (ACPI_GET_ADDRESS (Address)), 1015 AcpiUtGetRegionName (Reg->AddressSpaceId))); 1016 1017 return (Status); 1018 } 1019