hwregs.c revision 71867
1 2/******************************************************************************* 3 * 4 * Module Name: hwregs - Read/write access functions for the various ACPI 5 * control and status registers. 6 * $Revision: 88 $ 7 * 8 ******************************************************************************/ 9 10/****************************************************************************** 11 * 12 * 1. Copyright Notice 13 * 14 * Some or all of this work - Copyright (c) 1999, 2000, 2001, 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 "achware.h" 123#include "acnamesp.h" 124 125#define _COMPONENT HARDWARE 126 MODULE_NAME ("hwregs") 127 128 129/* This matches the #defines in actypes.h. */ 130 131NATIVE_CHAR *SleepStateTable[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_", 132 "\\_S4_","\\_S5_","\\_S4B"}; 133 134 135/******************************************************************************* 136 * 137 * FUNCTION: AcpiHwGetBitShift 138 * 139 * PARAMETERS: Mask - Input mask to determine bit shift from. 140 * Must have at least 1 bit set. 141 * 142 * RETURN: Bit location of the lsb of the mask 143 * 144 * DESCRIPTION: Returns the bit number for the low order bit that's set. 145 * 146 ******************************************************************************/ 147 148UINT32 149AcpiHwGetBitShift ( 150 UINT32 Mask) 151{ 152 UINT32 Shift; 153 154 155 FUNCTION_TRACE ("HwGetBitShift"); 156 157 158 for (Shift = 0; ((Mask >> Shift) & 1) == 0; Shift++) 159 { ; } 160 161 return_VALUE (Shift); 162} 163 164 165/******************************************************************************* 166 * 167 * FUNCTION: AcpiHwClearAcpiStatus 168 * 169 * PARAMETERS: none 170 * 171 * RETURN: none 172 * 173 * DESCRIPTION: Clears all fixed and general purpose status bits 174 * 175 ******************************************************************************/ 176 177void 178AcpiHwClearAcpiStatus (void) 179{ 180 UINT16 GpeLength; 181 UINT16 Index; 182 183 184 FUNCTION_TRACE ("HwClearAcpiStatus"); 185 186 187 DEBUG_PRINT (TRACE_IO, ("About to write %04X to %04X\n", 188 ALL_FIXED_STS_BITS, 189 (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1aEvtBlk.Address))); 190 191 192 AcpiCmAcquireMutex (ACPI_MTX_HARDWARE); 193 194 AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS); 195 196 197 if (ACPI_VALID_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address)) 198 { 199 AcpiOsOut16 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm1bEvtBlk.Address), 200 (UINT16) ALL_FIXED_STS_BITS); 201 } 202 203 /* now clear the GPE Bits */ 204 205 if (AcpiGbl_FADT->Gpe0BlkLen) 206 { 207 GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen); 208 209 for (Index = 0; Index < GpeLength; Index++) 210 { 211 AcpiOsOut8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + Index), 212 (UINT8) 0xff); 213 } 214 } 215 216 if (AcpiGbl_FADT->Gpe1BlkLen) 217 { 218 GpeLength = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe1BlkLen); 219 220 for (Index = 0; Index < GpeLength; Index++) 221 { 222 AcpiOsOut8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + Index), 223 (UINT8) 0xff); 224 } 225 } 226 227 AcpiCmReleaseMutex (ACPI_MTX_HARDWARE); 228 return_VOID; 229} 230 231 232/******************************************************************************* 233 * 234 * FUNCTION: AcpiHwObtainSleepTypeRegisterData 235 * 236 * PARAMETERS: SleepState - Numeric state requested 237 * *Slp_TypA - Pointer to byte to receive SLP_TYPa value 238 * *Slp_TypB - Pointer to byte to receive SLP_TYPb value 239 * 240 * RETURN: Status - ACPI status 241 * 242 * DESCRIPTION: AcpiHwObtainSleepTypeRegisterData() obtains the SLP_TYP and 243 * SLP_TYPb values for the sleep state requested. 244 * 245 ******************************************************************************/ 246 247ACPI_STATUS 248AcpiHwObtainSleepTypeRegisterData ( 249 UINT8 SleepState, 250 UINT8 *Slp_TypA, 251 UINT8 *Slp_TypB) 252{ 253 ACPI_STATUS Status = AE_OK; 254 ACPI_OPERAND_OBJECT *ObjDesc; 255 256 257 FUNCTION_TRACE ("HwObtainSleepTypeRegisterData"); 258 259 260 /* 261 * Validate parameters 262 */ 263 264 if ((SleepState > ACPI_S_STATES_MAX) || 265 !Slp_TypA || !Slp_TypB) 266 { 267 return_ACPI_STATUS (AE_BAD_PARAMETER); 268 } 269 270 /* 271 * AcpiEvaluate the namespace object containing the values for this state 272 */ 273 274 Status = AcpiNsEvaluateByName (SleepStateTable[SleepState], NULL, &ObjDesc); 275 if (ACPI_FAILURE (Status)) 276 { 277 return_ACPI_STATUS (Status); 278 } 279 280 if (!ObjDesc) 281 { 282 REPORT_ERROR (("Missing Sleep State object\n")); 283 return_ACPI_STATUS (AE_NOT_EXIST); 284 } 285 286 /* 287 * We got something, now ensure it is correct. The object must 288 * be a package and must have at least 2 numeric values as the 289 * two elements 290 */ 291 292 Status = AcpiCmResolvePackageReferences(ObjDesc); 293 294 if (ObjDesc->Package.Count < 2) 295 { 296 /* Must have at least two elements */ 297 298 REPORT_ERROR (("Sleep State package does not have at least two elements\n")); 299 Status = AE_ERROR; 300 } 301 302 else if (((ObjDesc->Package.Elements[0])->Common.Type != 303 ACPI_TYPE_INTEGER) || 304 ((ObjDesc->Package.Elements[1])->Common.Type != 305 ACPI_TYPE_INTEGER)) 306 { 307 /* Must have two */ 308 309 REPORT_ERROR (("Sleep State package elements are not both of type Number\n")); 310 Status = AE_ERROR; 311 } 312 313 else 314 { 315 /* 316 * Valid _Sx_ package size, type, and value 317 */ 318 *Slp_TypA = (UINT8) (ObjDesc->Package.Elements[0])->Integer.Value; 319 320 *Slp_TypB = (UINT8) (ObjDesc->Package.Elements[1])->Integer.Value; 321 } 322 323 324 if (ACPI_FAILURE (Status)) 325 { 326 DEBUG_PRINT (ACPI_ERROR, 327 ("SleepTypeRegisterData: Bad Sleep object %p type %X\n", 328 ObjDesc, ObjDesc->Common.Type)); 329 } 330 331 AcpiCmRemoveReference (ObjDesc); 332 333 return_ACPI_STATUS (Status); 334} 335 336 337/******************************************************************************* 338 * 339 * FUNCTION: AcpiHwRegisterBitAccess 340 * 341 * PARAMETERS: ReadWrite - Either ACPI_READ or ACPI_WRITE. 342 * UseLock - Lock the hardware 343 * RegisterId - index of ACPI Register to access 344 * Value - (only used on write) value to write to the 345 * Register. Shifted all the way right. 346 * 347 * RETURN: Value written to or read from specified Register. This value 348 * is shifted all the way right. 349 * 350 * DESCRIPTION: Generic ACPI Register read/write function. 351 * 352 ******************************************************************************/ 353 354UINT32 355AcpiHwRegisterBitAccess ( 356 NATIVE_UINT ReadWrite, 357 BOOLEAN UseLock, 358 UINT32 RegisterId, 359 ...) /* Value (only used on write) */ 360{ 361 UINT32 RegisterValue = 0; 362 UINT32 Mask = 0; 363 UINT32 Value = 0; 364 365 FUNCTION_TRACE ("HwRegisterBitAccess"); 366 367 368 if (ReadWrite == ACPI_WRITE) 369 { 370 va_list marker; 371 372 va_start (marker, RegisterId); 373 Value = va_arg (marker, UINT32); 374 va_end (marker); 375 } 376 377 if (ACPI_MTX_LOCK == UseLock) { 378 AcpiCmAcquireMutex (ACPI_MTX_HARDWARE); 379 } 380 381 /* 382 * Decode the Register ID 383 * Register id = Register block id | bit id 384 * 385 * Check bit id to fine locate Register offset. 386 * check Mask to determine Register offset, and then read-write. 387 */ 388 389 switch (REGISTER_BLOCK_ID(RegisterId)) 390 { 391 case PM1_STS: 392 393 switch (RegisterId) 394 { 395 case TMR_STS: 396 Mask = TMR_STS_MASK; 397 break; 398 399 case BM_STS: 400 Mask = BM_STS_MASK; 401 break; 402 403 case GBL_STS: 404 Mask = GBL_STS_MASK; 405 break; 406 407 case PWRBTN_STS: 408 Mask = PWRBTN_STS_MASK; 409 break; 410 411 case SLPBTN_STS: 412 Mask = SLPBTN_STS_MASK; 413 break; 414 415 case RTC_STS: 416 Mask = RTC_STS_MASK; 417 break; 418 419 case WAK_STS: 420 Mask = WAK_STS_MASK; 421 break; 422 423 default: 424 Mask = 0; 425 break; 426 } 427 428 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_STS); 429 430 if (ReadWrite == ACPI_WRITE) 431 { 432 /* 433 * Status Registers are different from the rest. Clear by 434 * writing 1, writing 0 has no effect. So, the only relevent 435 * information is the single bit we're interested in, all 436 * others should be written as 0 so they will be left 437 * unchanged 438 */ 439 440 Value <<= AcpiHwGetBitShift (Mask); 441 Value &= Mask; 442 443 if (Value) 444 { 445 AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_STS, (UINT16) Value); 446 447 RegisterValue = 0; 448 } 449 } 450 451 break; 452 453 454 case PM1_EN: 455 456 switch (RegisterId) 457 { 458 case TMR_EN: 459 Mask = TMR_EN_MASK; 460 break; 461 462 case GBL_EN: 463 Mask = GBL_EN_MASK; 464 break; 465 466 case PWRBTN_EN: 467 Mask = PWRBTN_EN_MASK; 468 break; 469 470 case SLPBTN_EN: 471 Mask = SLPBTN_EN_MASK; 472 break; 473 474 case RTC_EN: 475 Mask = RTC_EN_MASK; 476 break; 477 478 default: 479 Mask = 0; 480 break; 481 } 482 483 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_EN); 484 485 if (ReadWrite == ACPI_WRITE) 486 { 487 RegisterValue &= ~Mask; 488 Value <<= AcpiHwGetBitShift (Mask); 489 Value &= Mask; 490 RegisterValue |= Value; 491 492 AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (UINT16) RegisterValue); 493 } 494 495 break; 496 497 498 case PM1_CONTROL: 499 500 switch (RegisterId) 501 { 502 case SCI_EN: 503 Mask = SCI_EN_MASK; 504 break; 505 506 case BM_RLD: 507 Mask = BM_RLD_MASK; 508 break; 509 510 case GBL_RLS: 511 Mask = GBL_RLS_MASK; 512 break; 513 514 case SLP_TYPE_A: 515 case SLP_TYPE_B: 516 Mask = SLP_TYPE_X_MASK; 517 break; 518 519 case SLP_EN: 520 Mask = SLP_EN_MASK; 521 break; 522 523 default: 524 Mask = 0; 525 break; 526 } 527 528 529 /* 530 * Read the PM1 Control register. 531 * Note that at this level, the fact that there are actually TWO 532 * registers (A and B) and that B may not exist, are abstracted. 533 */ 534 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL); 535 536 DEBUG_PRINT (TRACE_IO, ("PM1 control: Read %X\n", RegisterValue)); 537 538 if (ReadWrite == ACPI_WRITE) 539 { 540 RegisterValue &= ~Mask; 541 Value <<= AcpiHwGetBitShift (Mask); 542 Value &= Mask; 543 RegisterValue |= Value; 544 545 /* 546 * SLP_TYPE_x Registers are written differently 547 * than any other control Registers with 548 * respect to A and B Registers. The value 549 * for A may be different than the value for B 550 * 551 * Therefore, pass the RegisterId, not just generic PM1_CONTROL, 552 * because we need to do different things. Yuck. 553 */ 554 555 AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 556 RegisterId, (UINT16) RegisterValue); 557 } 558 break; 559 560 561 case PM2_CONTROL: 562 563 switch (RegisterId) 564 { 565 case ARB_DIS: 566 Mask = ARB_DIS_MASK; 567 break; 568 569 default: 570 Mask = 0; 571 break; 572 } 573 574 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); 575 576 DEBUG_PRINT (TRACE_IO, ("PM2 control: Read %X from %p\n", 577 RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPm2CntBlk.Address))); 578 579 if (ReadWrite == ACPI_WRITE) 580 { 581 RegisterValue &= ~Mask; 582 Value <<= AcpiHwGetBitShift (Mask); 583 Value &= Mask; 584 RegisterValue |= Value; 585 586 DEBUG_PRINT (TRACE_IO, 587 ("About to write %04X to %p\n", RegisterValue, 588 AcpiGbl_FADT->XPm2CntBlk.Address)); 589 590 AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 591 PM2_CONTROL, (UINT8) (RegisterValue)); 592 } 593 break; 594 595 596 case PM_TIMER: 597 598 Mask = TMR_VAL_MASK; 599 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, 600 PM_TIMER); 601 DEBUG_PRINT (TRACE_IO, ("PM_TIMER: Read %X from %p\n", 602 RegisterValue, ACPI_GET_ADDRESS (AcpiGbl_FADT->XPmTmrBlk.Address))); 603 604 break; 605 606 607 case GPE1_EN_BLOCK: 608 case GPE1_STS_BLOCK: 609 case GPE0_EN_BLOCK: 610 case GPE0_STS_BLOCK: 611 612 /* Determine the bit to be accessed 613 * 614 * (UINT32) RegisterId: 615 * 31 24 16 8 0 616 * +--------+--------+--------+--------+ 617 * | gpe_block_id | gpe_bit_number | 618 * +--------+--------+--------+--------+ 619 * 620 * gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK 621 * gpe_bit_number is relative from the gpe_block (0x00~0xFF) 622 */ 623 624 Mask = REGISTER_BIT_ID(RegisterId); /* gpe_bit_number */ 625 RegisterId = REGISTER_BLOCK_ID(RegisterId) | (Mask >> 3); 626 Mask = AcpiGbl_DecodeTo8bit [Mask % 8]; 627 628 /* 629 * The base address of the GPE 0 Register Block 630 * Plus 1/2 the length of the GPE 0 Register Block 631 * The enable Register is the Register following the Status Register 632 * and each Register is defined as 1/2 of the total Register Block 633 */ 634 635 /* 636 * This sets the bit within EnableBit that needs to be written to 637 * the Register indicated in Mask to a 1, all others are 0 638 */ 639 640 /* Now get the current Enable Bits in the selected Reg */ 641 642 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId); 643 DEBUG_PRINT (TRACE_IO, ("GPE Enable bits: Read %X from %X\n", 644 RegisterValue, RegisterId)); 645 646 if (ReadWrite == ACPI_WRITE) 647 { 648 RegisterValue &= ~Mask; 649 Value <<= AcpiHwGetBitShift (Mask); 650 Value &= Mask; 651 RegisterValue |= Value; 652 653 /* This write will put the Action state into the General Purpose */ 654 /* Enable Register indexed by the value in Mask */ 655 656 DEBUG_PRINT (TRACE_IO, ("About to write %04X to %04X\n", 657 RegisterValue, RegisterId)); 658 AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, 659 RegisterId, (UINT8) RegisterValue); 660 RegisterValue = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, RegisterId); 661 } 662 break; 663 664 665 case SMI_CMD_BLOCK: 666 case PROCESSOR_BLOCK: 667 /* not used */ 668 default: 669 670 Mask = 0; 671 break; 672 } 673 674 if (ACPI_MTX_LOCK == UseLock) { 675 AcpiCmReleaseMutex (ACPI_MTX_HARDWARE); 676 } 677 678 679 RegisterValue &= Mask; 680 RegisterValue >>= AcpiHwGetBitShift (Mask); 681 682 DEBUG_PRINT (TRACE_IO, ("Register I/O: returning %X\n", RegisterValue)); 683 return_VALUE (RegisterValue); 684} 685 686 687/****************************************************************************** 688 * 689 * FUNCTION: AcpiHwRegisterRead 690 * 691 * PARAMETERS: UseLock - Mutex hw access. 692 * RegisterId - RegisterID + Offset. 693 * 694 * RETURN: Value read or written. 695 * 696 * DESCRIPTION: Acpi register read function. Registers are read at the 697 * given offset. 698 * 699 ******************************************************************************/ 700 701UINT32 702AcpiHwRegisterRead ( 703 BOOLEAN UseLock, 704 UINT32 RegisterId) 705{ 706 UINT32 Value = 0; 707 UINT32 BankOffset; 708 709 FUNCTION_TRACE ("AcpiHwRegisterRead"); 710 711 if (ACPI_MTX_LOCK == UseLock) 712 { 713 AcpiCmAcquireMutex (ACPI_MTX_HARDWARE); 714 } 715 716 717 switch (REGISTER_BLOCK_ID(RegisterId)) 718 { 719 case PM1_STS: /* 16-bit access */ 720 721 Value = AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, 0); 722 Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, 0); 723 break; 724 725 726 case PM1_EN: /* 16-bit access*/ 727 728 BankOffset = DIV_2 (AcpiGbl_FADT->Pm1EvtLen); 729 Value = AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset); 730 Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset); 731 break; 732 733 734 case PM1_CONTROL: /* 16-bit access */ 735 736 Value = AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1aCntBlk, 0); 737 Value |= AcpiHwLowLevelRead (16, &AcpiGbl_FADT->XPm1bCntBlk, 0); 738 break; 739 740 741 case PM2_CONTROL: /* 8-bit access */ 742 743 Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XPm2CntBlk, 0); 744 break; 745 746 747 case PM_TIMER: /* 32-bit access */ 748 749 Value = AcpiHwLowLevelRead (32, &AcpiGbl_FADT->XPmTmrBlk, 0); 750 break; 751 752 753 case GPE0_STS_BLOCK: /* 8-bit access */ 754 755 Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, 0); 756 break; 757 758 759 case GPE0_EN_BLOCK: /* 8-bit access */ 760 761 BankOffset = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen); 762 Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe0Blk, BankOffset); 763 break; 764 765 766 case GPE1_STS_BLOCK: /* 8-bit access */ 767 768 Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, 0); 769 break; 770 771 772 case GPE1_EN_BLOCK: /* 8-bit access */ 773 774 BankOffset = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen); 775 Value = AcpiHwLowLevelRead (8, &AcpiGbl_FADT->XGpe1Blk, BankOffset); 776 break; 777 778 779 case SMI_CMD_BLOCK: /* 8bit */ 780 781 Value = (UINT32) AcpiOsIn8 (AcpiGbl_FADT->SmiCmd); 782 break; 783 784 785 default: 786 Value = 0; 787 break; 788 } 789 790 791 if (ACPI_MTX_LOCK == UseLock) 792 { 793 AcpiCmReleaseMutex (ACPI_MTX_HARDWARE); 794 } 795 796 return_VALUE (Value); 797} 798 799 800/****************************************************************************** 801 * 802 * FUNCTION: AcpiHwRegisterWrite 803 * 804 * PARAMETERS: UseLock - Mutex hw access. 805 * RegisterId - RegisterID + Offset. 806 * 807 * RETURN: Value read or written. 808 * 809 * DESCRIPTION: Acpi register Write function. Registers are written at the 810 * given offset. 811 * 812 ******************************************************************************/ 813 814void 815AcpiHwRegisterWrite ( 816 BOOLEAN UseLock, 817 UINT32 RegisterId, 818 UINT32 Value) 819{ 820 UINT32 BankOffset; 821 822 FUNCTION_TRACE ("AcpiHwRegisterWrite"); 823 824 825 if (ACPI_MTX_LOCK == UseLock) 826 { 827 AcpiCmAcquireMutex (ACPI_MTX_HARDWARE); 828 } 829 830 831 switch (REGISTER_BLOCK_ID (RegisterId)) 832 { 833 case PM1_STS: /* 16-bit access */ 834 835 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, 0); 836 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, 0); 837 break; 838 839 840 case PM1_EN: /* 16-bit access*/ 841 842 BankOffset = DIV_2 (AcpiGbl_FADT->Pm1EvtLen); 843 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aEvtBlk, BankOffset); 844 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bEvtBlk, BankOffset); 845 break; 846 847 848 case PM1_CONTROL: /* 16-bit access */ 849 850 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0); 851 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0); 852 break; 853 854 855 case PM1A_CONTROL: /* 16-bit access */ 856 857 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1aCntBlk, 0); 858 break; 859 860 861 case PM1B_CONTROL: /* 16-bit access */ 862 863 AcpiHwLowLevelWrite (16, Value, &AcpiGbl_FADT->XPm1bCntBlk, 0); 864 break; 865 866 867 case PM2_CONTROL: /* 8-bit access */ 868 869 AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XPm2CntBlk, 0); 870 break; 871 872 873 case PM_TIMER: /* 32-bit access */ 874 875 AcpiHwLowLevelWrite (32, Value, &AcpiGbl_FADT->XPmTmrBlk, 0); 876 break; 877 878 879 case GPE0_STS_BLOCK: /* 8-bit access */ 880 881 AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, 0); 882 break; 883 884 885 case GPE0_EN_BLOCK: /* 8-bit access */ 886 887 BankOffset = DIV_2 (AcpiGbl_FADT->Gpe0BlkLen); 888 AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe0Blk, BankOffset); 889 break; 890 891 892 case GPE1_STS_BLOCK: /* 8-bit access */ 893 894 AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, 0); 895 break; 896 897 898 case GPE1_EN_BLOCK: /* 8-bit access */ 899 900 BankOffset = DIV_2 (AcpiGbl_FADT->Gpe1BlkLen); 901 AcpiHwLowLevelWrite (8, Value, &AcpiGbl_FADT->XGpe1Blk, BankOffset); 902 break; 903 904 905 case SMI_CMD_BLOCK: /* 8bit */ 906 907 /* For 2.0, SMI_CMD is always in IO space */ 908 /* TBD: what about 1.0? 0.71? */ 909 910 AcpiOsOut8 (AcpiGbl_FADT->SmiCmd, (UINT8) Value); 911 break; 912 913 914 default: 915 Value = 0; 916 break; 917 } 918 919 920 if (ACPI_MTX_LOCK == UseLock) 921 { 922 AcpiCmReleaseMutex (ACPI_MTX_HARDWARE); 923 } 924 925 return_VOID; 926} 927 928 929/****************************************************************************** 930 * 931 * FUNCTION: AcpiHwLowLevelRead 932 * 933 * PARAMETERS: Register - GAS register structure 934 * Offset - Offset from the base address in the GAS 935 * Width - 8, 16, or 32 936 * 937 * RETURN: Value read 938 * 939 * DESCRIPTION: Read from either memory, IO, or PCI config space. 940 * 941 ******************************************************************************/ 942 943UINT32 944AcpiHwLowLevelRead ( 945 UINT32 Width, 946 ACPI_GAS *Reg, 947 UINT32 Offset) 948{ 949 UINT32 Value = 0; 950 ACPI_PHYSICAL_ADDRESS MemAddress; 951 ACPI_IO_ADDRESS IoAddress; 952 UINT32 PciRegister; 953 UINT32 PciDevFunc; 954 955 956 /* 957 * Must have a valid pointer to a GAS structure, and 958 * a non-zero address within 959 */ 960 if ((!Reg) || 961 (!ACPI_VALID_ADDRESS (Reg->Address))) 962 { 963 return 0; 964 } 965 966 967 /* 968 * Three address spaces supported: 969 * Memory, Io, or PCI config. 970 */ 971 972 switch (Reg->AddressSpaceId) 973 { 974 case ADDRESS_SPACE_SYSTEM_MEMORY: 975 976 MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset); 977 978 switch (Width) 979 { 980 case 8: 981 Value = AcpiOsMemIn8 (MemAddress); 982 break; 983 case 16: 984 Value = AcpiOsMemIn16 (MemAddress); 985 break; 986 case 32: 987 Value = AcpiOsMemIn32 (MemAddress); 988 break; 989 } 990 break; 991 992 993 case ADDRESS_SPACE_SYSTEM_IO: 994 995 IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset); 996 997 switch (Width) 998 { 999 case 8: 1000 Value = AcpiOsIn8 (IoAddress); 1001 break; 1002 case 16: 1003 Value = AcpiOsIn16 (IoAddress); 1004 break; 1005 case 32: 1006 Value = AcpiOsIn32 (IoAddress); 1007 break; 1008 } 1009 break; 1010 1011 1012 case ADDRESS_SPACE_PCI_CONFIG: 1013 1014 PciDevFunc = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (Reg->Address)); 1015 PciRegister = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset; 1016 1017 switch (Width) 1018 { 1019 case 8: 1020 AcpiOsReadPciCfgByte (0, PciDevFunc, PciRegister, (UINT8 *) &Value); 1021 break; 1022 case 16: 1023 AcpiOsReadPciCfgWord (0, PciDevFunc, PciRegister, (UINT16 *) &Value); 1024 break; 1025 case 32: 1026 AcpiOsReadPciCfgDword (0, PciDevFunc, PciRegister, (UINT32 *) &Value); 1027 break; 1028 } 1029 break; 1030 } 1031 1032 return Value; 1033} 1034 1035 1036/****************************************************************************** 1037 * 1038 * FUNCTION: AcpiHwLowLevelWrite 1039 * 1040 * PARAMETERS: Width - 8, 16, or 32 1041 * Value - To be written 1042 * Register - GAS register structure 1043 * Offset - Offset from the base address in the GAS 1044 * 1045 * 1046 * RETURN: Value read 1047 * 1048 * DESCRIPTION: Read from either memory, IO, or PCI config space. 1049 * 1050 ******************************************************************************/ 1051 1052void 1053AcpiHwLowLevelWrite ( 1054 UINT32 Width, 1055 UINT32 Value, 1056 ACPI_GAS *Reg, 1057 UINT32 Offset) 1058{ 1059 ACPI_PHYSICAL_ADDRESS MemAddress; 1060 ACPI_IO_ADDRESS IoAddress; 1061 UINT32 PciRegister; 1062 UINT32 PciDevFunc; 1063 1064 1065 /* 1066 * Must have a valid pointer to a GAS structure, and 1067 * a non-zero address within 1068 */ 1069 if ((!Reg) || 1070 (!ACPI_VALID_ADDRESS (Reg->Address))) 1071 { 1072 return; 1073 } 1074 1075 1076 /* 1077 * Three address spaces supported: 1078 * Memory, Io, or PCI config. 1079 */ 1080 1081 switch (Reg->AddressSpaceId) 1082 { 1083 case ADDRESS_SPACE_SYSTEM_MEMORY: 1084 1085 MemAddress = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset); 1086 1087 switch (Width) 1088 { 1089 case 8: 1090 AcpiOsMemOut8 (MemAddress, (UINT8) Value); 1091 break; 1092 case 16: 1093 AcpiOsMemOut16 (MemAddress, (UINT16) Value); 1094 break; 1095 case 32: 1096 AcpiOsMemOut32 (MemAddress, (UINT32) Value); 1097 break; 1098 } 1099 break; 1100 1101 1102 case ADDRESS_SPACE_SYSTEM_IO: 1103 1104 IoAddress = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (Reg->Address) + Offset); 1105 1106 switch (Width) 1107 { 1108 case 8: 1109 AcpiOsOut8 (IoAddress, (UINT8) Value); 1110 break; 1111 case 16: 1112 AcpiOsOut16 (IoAddress, (UINT16) Value); 1113 break; 1114 case 32: 1115 AcpiOsOut32 (IoAddress, (UINT32) Value); 1116 break; 1117 } 1118 break; 1119 1120 1121 case ADDRESS_SPACE_PCI_CONFIG: 1122 1123 PciDevFunc = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (Reg->Address)); 1124 PciRegister = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (Reg->Address)) + Offset; 1125 1126 switch (Width) 1127 { 1128 case 8: 1129 AcpiOsWritePciCfgByte (0, PciDevFunc, PciRegister, (UINT8) Value); 1130 break; 1131 case 16: 1132 AcpiOsWritePciCfgWord (0, PciDevFunc, PciRegister, (UINT16) Value); 1133 break; 1134 case 32: 1135 AcpiOsWritePciCfgDword (0, PciDevFunc, PciRegister, (UINT32) Value); 1136 break; 1137 } 1138 break; 1139 } 1140} 1141