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