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