![]() |
|
|||
File indexing completed on 2025-05-11 08:24:02
0001 /******************************************************************************* 0002 * 0003 * Module Name: hwregs - Read/write access functions for the various ACPI 0004 * control and status registers. 0005 * 0006 ******************************************************************************/ 0007 0008 /****************************************************************************** 0009 * 0010 * 1. Copyright Notice 0011 * 0012 * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp. 0013 * All rights reserved. 0014 * 0015 * 2. License 0016 * 0017 * 2.1. This is your license from Intel Corp. under its intellectual property 0018 * rights. You may have additional license terms from the party that provided 0019 * you this software, covering your right to use that party's intellectual 0020 * property rights. 0021 * 0022 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 0023 * copy of the source code appearing in this file ("Covered Code") an 0024 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 0025 * base code distributed originally by Intel ("Original Intel Code") to copy, 0026 * make derivatives, distribute, use and display any portion of the Covered 0027 * Code in any form, with the right to sublicense such rights; and 0028 * 0029 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 0030 * license (with the right to sublicense), under only those claims of Intel 0031 * patents that are infringed by the Original Intel Code, to make, use, sell, 0032 * offer to sell, and import the Covered Code and derivative works thereof 0033 * solely to the minimum extent necessary to exercise the above copyright 0034 * license, and in no event shall the patent license extend to any additions 0035 * to or modifications of the Original Intel Code. No other license or right 0036 * is granted directly or by implication, estoppel or otherwise; 0037 * 0038 * The above copyright and patent license is granted only if the following 0039 * conditions are met: 0040 * 0041 * 3. Conditions 0042 * 0043 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 0044 * Redistribution of source code of any substantial portion of the Covered 0045 * Code or modification with rights to further distribute source must include 0046 * the above Copyright Notice, the above License, this list of Conditions, 0047 * and the following Disclaimer and Export Compliance provision. In addition, 0048 * Licensee must cause all Covered Code to which Licensee contributes to 0049 * contain a file documenting the changes Licensee made to create that Covered 0050 * Code and the date of any change. Licensee must include in that file the 0051 * documentation of any changes made by any predecessor Licensee. Licensee 0052 * must include a prominent statement that the modification is derived, 0053 * directly or indirectly, from Original Intel Code. 0054 * 0055 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 0056 * Redistribution of source code of any substantial portion of the Covered 0057 * Code or modification without rights to further distribute source must 0058 * include the following Disclaimer and Export Compliance provision in the 0059 * documentation and/or other materials provided with distribution. In 0060 * addition, Licensee may not authorize further sublicense of source of any 0061 * portion of the Covered Code, and must include terms to the effect that the 0062 * license from Licensee to its licensee is limited to the intellectual 0063 * property embodied in the software Licensee provides to its licensee, and 0064 * not to intellectual property embodied in modifications its licensee may 0065 * make. 0066 * 0067 * 3.3. Redistribution of Executable. Redistribution in executable form of any 0068 * substantial portion of the Covered Code or modification must reproduce the 0069 * above Copyright Notice, and the following Disclaimer and Export Compliance 0070 * provision in the documentation and/or other materials provided with the 0071 * distribution. 0072 * 0073 * 3.4. Intel retains all right, title, and interest in and to the Original 0074 * Intel Code. 0075 * 0076 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 0077 * Intel shall be used in advertising or otherwise to promote the sale, use or 0078 * other dealings in products derived from or relating to the Covered Code 0079 * without prior written authorization from Intel. 0080 * 0081 * 4. Disclaimer and Export Compliance 0082 * 0083 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 0084 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 0085 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 0086 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 0087 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 0088 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 0089 * PARTICULAR PURPOSE. 0090 * 0091 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 0092 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 0093 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 0094 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 0095 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 0096 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 0097 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 0098 * LIMITED REMEDY. 0099 * 0100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 0101 * software or system incorporating such software without first obtaining any 0102 * required license or other approval from the U. S. Department of Commerce or 0103 * any other agency or department of the United States Government. In the 0104 * event Licensee exports any such software from the United States or 0105 * re-exports any such software from a foreign destination, Licensee shall 0106 * ensure that the distribution and export/re-export of the software is in 0107 * compliance with all laws, regulations, orders, or other restrictions of the 0108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 0109 * any of its subsidiaries will export/re-export any technical data, process, 0110 * software, or service, directly or indirectly, to any country for which the 0111 * United States government or any agency thereof requires an export license, 0112 * other governmental approval, or letter of assurance, without first obtaining 0113 * such license, approval or letter. 0114 * 0115 ***************************************************************************** 0116 * 0117 * Alternatively, you may choose to be licensed under the terms of the 0118 * following license: 0119 * 0120 * Redistribution and use in source and binary forms, with or without 0121 * modification, are permitted provided that the following conditions 0122 * are met: 0123 * 1. Redistributions of source code must retain the above copyright 0124 * notice, this list of conditions, and the following disclaimer, 0125 * without modification. 0126 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 0127 * substantially similar to the "NO WARRANTY" disclaimer below 0128 * ("Disclaimer") and any redistribution must be conditioned upon 0129 * including a substantially similar Disclaimer requirement for further 0130 * binary redistribution. 0131 * 3. Neither the names of the above-listed copyright holders nor the names 0132 * of any contributors may be used to endorse or promote products derived 0133 * from this software without specific prior written permission. 0134 * 0135 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 0136 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 0137 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 0138 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 0139 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 0140 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 0141 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0142 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0143 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0144 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0145 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0146 * 0147 * Alternatively, you may choose to be licensed under the terms of the 0148 * GNU General Public License ("GPL") version 2 as published by the Free 0149 * Software Foundation. 0150 * 0151 *****************************************************************************/ 0152 0153 #include "acpi.h" 0154 #include "accommon.h" 0155 #include "acevents.h" 0156 0157 #define _COMPONENT ACPI_HARDWARE 0158 ACPI_MODULE_NAME ("hwregs") 0159 0160 0161 #if (!ACPI_REDUCED_HARDWARE) 0162 0163 /* Local Prototypes */ 0164 0165 static UINT8 0166 AcpiHwGetAccessBitWidth ( 0167 UINT64 Address, 0168 ACPI_GENERIC_ADDRESS *Reg, 0169 UINT8 MaxBitWidth); 0170 0171 static ACPI_STATUS 0172 AcpiHwReadMultiple ( 0173 UINT32 *Value, 0174 ACPI_GENERIC_ADDRESS *RegisterA, 0175 ACPI_GENERIC_ADDRESS *RegisterB); 0176 0177 static ACPI_STATUS 0178 AcpiHwWriteMultiple ( 0179 UINT32 Value, 0180 ACPI_GENERIC_ADDRESS *RegisterA, 0181 ACPI_GENERIC_ADDRESS *RegisterB); 0182 0183 #endif /* !ACPI_REDUCED_HARDWARE */ 0184 0185 0186 /****************************************************************************** 0187 * 0188 * FUNCTION: AcpiHwGetAccessBitWidth 0189 * 0190 * PARAMETERS: Address - GAS register address 0191 * Reg - GAS register structure 0192 * MaxBitWidth - Max BitWidth supported (32 or 64) 0193 * 0194 * RETURN: Status 0195 * 0196 * DESCRIPTION: Obtain optimal access bit width 0197 * 0198 ******************************************************************************/ 0199 0200 static UINT8 0201 AcpiHwGetAccessBitWidth ( 0202 UINT64 Address, 0203 ACPI_GENERIC_ADDRESS *Reg, 0204 UINT8 MaxBitWidth) 0205 { 0206 UINT8 AccessBitWidth; 0207 0208 0209 /* 0210 * GAS format "register", used by FADT: 0211 * 1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64; 0212 * 2. AccessSize field is ignored and BitWidth field is used for 0213 * determining the boundary of the IO accesses. 0214 * GAS format "region", used by APEI registers: 0215 * 1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64; 0216 * 2. AccessSize field is used for determining the boundary of the 0217 * IO accesses; 0218 * 3. BitOffset/BitWidth fields are used to describe the "region". 0219 * 0220 * Note: This algorithm assumes that the "Address" fields should always 0221 * contain aligned values. 0222 */ 0223 if (!Reg->BitOffset && Reg->BitWidth && 0224 ACPI_IS_POWER_OF_TWO (Reg->BitWidth) && 0225 ACPI_IS_ALIGNED (Reg->BitWidth, 8)) 0226 { 0227 AccessBitWidth = Reg->BitWidth; 0228 } 0229 else if (Reg->AccessWidth) 0230 { 0231 AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth); 0232 } 0233 else 0234 { 0235 AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 ( 0236 Reg->BitOffset + Reg->BitWidth); 0237 if (AccessBitWidth <= 8) 0238 { 0239 AccessBitWidth = 8; 0240 } 0241 else 0242 { 0243 while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3)) 0244 { 0245 AccessBitWidth >>= 1; 0246 } 0247 } 0248 } 0249 0250 /* Maximum IO port access bit width is 32 */ 0251 0252 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) 0253 { 0254 MaxBitWidth = 32; 0255 } 0256 0257 /* 0258 * Return access width according to the requested maximum access bit width, 0259 * as the caller should know the format of the register and may enforce 0260 * a 32-bit accesses. 0261 */ 0262 if (AccessBitWidth < MaxBitWidth) 0263 { 0264 return (AccessBitWidth); 0265 } 0266 return (MaxBitWidth); 0267 } 0268 0269 0270 /****************************************************************************** 0271 * 0272 * FUNCTION: AcpiHwValidateRegister 0273 * 0274 * PARAMETERS: Reg - GAS register structure 0275 * MaxBitWidth - Max BitWidth supported (32 or 64) 0276 * Address - Pointer to where the gas->address 0277 * is returned 0278 * 0279 * RETURN: Status 0280 * 0281 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS 0282 * pointer, Address, SpaceId, BitWidth, and BitOffset. 0283 * 0284 ******************************************************************************/ 0285 0286 ACPI_STATUS 0287 AcpiHwValidateRegister ( 0288 ACPI_GENERIC_ADDRESS *Reg, 0289 UINT8 MaxBitWidth, 0290 UINT64 *Address) 0291 { 0292 UINT8 BitWidth; 0293 UINT8 AccessWidth; 0294 0295 0296 /* Must have a valid pointer to a GAS structure */ 0297 0298 if (!Reg) 0299 { 0300 return (AE_BAD_PARAMETER); 0301 } 0302 0303 /* 0304 * Copy the target address. This handles possible alignment issues. 0305 * Address must not be null. A null address also indicates an optional 0306 * ACPI register that is not supported, so no error message. 0307 */ 0308 ACPI_MOVE_64_TO_64 (Address, &Reg->Address); 0309 if (!(*Address)) 0310 { 0311 return (AE_BAD_ADDRESS); 0312 } 0313 0314 /* Validate the SpaceID */ 0315 0316 if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 0317 (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 0318 { 0319 ACPI_ERROR ((AE_INFO, 0320 "Unsupported address space: 0x%X", Reg->SpaceId)); 0321 return (AE_SUPPORT); 0322 } 0323 0324 /* Validate the AccessWidth */ 0325 0326 if (Reg->AccessWidth > 4) 0327 { 0328 ACPI_ERROR ((AE_INFO, 0329 "Unsupported register access width: 0x%X", Reg->AccessWidth)); 0330 return (AE_SUPPORT); 0331 } 0332 0333 /* Validate the BitWidth, convert AccessWidth into number of bits */ 0334 0335 AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth); 0336 BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth); 0337 if (MaxBitWidth < BitWidth) 0338 { 0339 ACPI_WARNING ((AE_INFO, 0340 "Requested bit width 0x%X is smaller than register bit width 0x%X", 0341 MaxBitWidth, BitWidth)); 0342 return (AE_SUPPORT); 0343 } 0344 0345 return (AE_OK); 0346 } 0347 0348 0349 /****************************************************************************** 0350 * 0351 * FUNCTION: AcpiHwRead 0352 * 0353 * PARAMETERS: Value - Where the value is returned 0354 * Reg - GAS register structure 0355 * 0356 * RETURN: Status 0357 * 0358 * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max 0359 * version of AcpiRead. 0360 * 0361 * LIMITATIONS: <These limitations also apply to AcpiHwWrite> 0362 * SpaceID must be SystemMemory or SystemIO. 0363 * 0364 ******************************************************************************/ 0365 0366 ACPI_STATUS 0367 AcpiHwRead ( 0368 UINT64 *Value, 0369 ACPI_GENERIC_ADDRESS *Reg) 0370 { 0371 UINT64 Address; 0372 UINT8 AccessWidth; 0373 UINT32 BitWidth; 0374 UINT8 BitOffset; 0375 UINT64 Value64; 0376 UINT32 Value32; 0377 UINT8 Index; 0378 ACPI_STATUS Status; 0379 0380 0381 ACPI_FUNCTION_NAME (HwRead); 0382 0383 0384 /* Validate contents of the GAS register */ 0385 0386 Status = AcpiHwValidateRegister (Reg, 64, &Address); 0387 if (ACPI_FAILURE (Status)) 0388 { 0389 return (Status); 0390 } 0391 0392 /* 0393 * Initialize entire 64-bit return value to zero, convert AccessWidth 0394 * into number of bits based 0395 */ 0396 *Value = 0; 0397 AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64); 0398 BitWidth = Reg->BitOffset + Reg->BitWidth; 0399 BitOffset = Reg->BitOffset; 0400 0401 /* 0402 * Two address spaces supported: Memory or IO. PCI_Config is 0403 * not supported here because the GAS structure is insufficient 0404 */ 0405 Index = 0; 0406 while (BitWidth) 0407 { 0408 if (BitOffset >= AccessWidth) 0409 { 0410 Value64 = 0; 0411 BitOffset -= AccessWidth; 0412 } 0413 else 0414 { 0415 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 0416 { 0417 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 0418 Address + Index * ACPI_DIV_8 (AccessWidth), 0419 &Value64, AccessWidth); 0420 } 0421 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 0422 { 0423 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 0424 Address + Index * ACPI_DIV_8 (AccessWidth), 0425 &Value32, AccessWidth); 0426 Value64 = (UINT64) Value32; 0427 } 0428 } 0429 0430 /* 0431 * Use offset style bit writes because "Index * AccessWidth" is 0432 * ensured to be less than 64-bits by AcpiHwValidateRegister(). 0433 */ 0434 ACPI_SET_BITS (Value, Index * AccessWidth, 0435 ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64); 0436 0437 BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth; 0438 Index++; 0439 } 0440 0441 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 0442 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", 0443 ACPI_FORMAT_UINT64 (*Value), AccessWidth, 0444 ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId))); 0445 0446 return (Status); 0447 } 0448 0449 0450 /****************************************************************************** 0451 * 0452 * FUNCTION: AcpiHwWrite 0453 * 0454 * PARAMETERS: Value - Value to be written 0455 * Reg - GAS register structure 0456 * 0457 * RETURN: Status 0458 * 0459 * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max 0460 * version of AcpiWrite. 0461 * 0462 ******************************************************************************/ 0463 0464 ACPI_STATUS 0465 AcpiHwWrite ( 0466 UINT64 Value, 0467 ACPI_GENERIC_ADDRESS *Reg) 0468 { 0469 UINT64 Address; 0470 UINT8 AccessWidth; 0471 UINT32 BitWidth; 0472 UINT8 BitOffset; 0473 UINT64 Value64; 0474 UINT8 Index; 0475 ACPI_STATUS Status; 0476 0477 0478 ACPI_FUNCTION_NAME (HwWrite); 0479 0480 0481 /* Validate contents of the GAS register */ 0482 0483 Status = AcpiHwValidateRegister (Reg, 64, &Address); 0484 if (ACPI_FAILURE (Status)) 0485 { 0486 return (Status); 0487 } 0488 0489 /* Convert AccessWidth into number of bits based */ 0490 0491 AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64); 0492 BitWidth = Reg->BitOffset + Reg->BitWidth; 0493 BitOffset = Reg->BitOffset; 0494 0495 /* 0496 * Two address spaces supported: Memory or IO. PCI_Config is 0497 * not supported here because the GAS structure is insufficient 0498 */ 0499 Index = 0; 0500 while (BitWidth) 0501 { 0502 /* 0503 * Use offset style bit reads because "Index * AccessWidth" is 0504 * ensured to be less than 64-bits by AcpiHwValidateRegister(). 0505 */ 0506 Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth, 0507 ACPI_MASK_BITS_ABOVE_64 (AccessWidth)); 0508 0509 if (BitOffset >= AccessWidth) 0510 { 0511 BitOffset -= AccessWidth; 0512 } 0513 else 0514 { 0515 if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 0516 { 0517 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 0518 Address + Index * ACPI_DIV_8 (AccessWidth), 0519 Value64, AccessWidth); 0520 } 0521 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 0522 { 0523 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 0524 Address + Index * ACPI_DIV_8 (AccessWidth), 0525 (UINT32) Value64, AccessWidth); 0526 } 0527 } 0528 0529 /* 0530 * Index * AccessWidth is ensured to be less than 32-bits by 0531 * AcpiHwValidateRegister(). 0532 */ 0533 BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth; 0534 Index++; 0535 } 0536 0537 ACPI_DEBUG_PRINT ((ACPI_DB_IO, 0538 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", 0539 ACPI_FORMAT_UINT64 (Value), AccessWidth, 0540 ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId))); 0541 0542 return (Status); 0543 } 0544 0545 0546 #if (!ACPI_REDUCED_HARDWARE) 0547 /******************************************************************************* 0548 * 0549 * FUNCTION: AcpiHwClearAcpiStatus 0550 * 0551 * PARAMETERS: None 0552 * 0553 * RETURN: Status 0554 * 0555 * DESCRIPTION: Clears all fixed and general purpose status bits 0556 * 0557 ******************************************************************************/ 0558 0559 ACPI_STATUS 0560 AcpiHwClearAcpiStatus ( 0561 void) 0562 { 0563 ACPI_STATUS Status; 0564 ACPI_CPU_FLAGS LockFlags = 0; 0565 0566 0567 ACPI_FUNCTION_TRACE (HwClearAcpiStatus); 0568 0569 0570 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", 0571 ACPI_BITMASK_ALL_FIXED_STATUS, 0572 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); 0573 0574 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 0575 0576 /* Clear the fixed events in PM1 A/B */ 0577 0578 Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 0579 ACPI_BITMASK_ALL_FIXED_STATUS); 0580 0581 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 0582 0583 if (ACPI_FAILURE (Status)) 0584 { 0585 goto Exit; 0586 } 0587 0588 /* Clear the GPE Bits in all GPE registers in all GPE blocks */ 0589 0590 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 0591 0592 Exit: 0593 return_ACPI_STATUS (Status); 0594 } 0595 0596 0597 /******************************************************************************* 0598 * 0599 * FUNCTION: AcpiHwGetBitRegisterInfo 0600 * 0601 * PARAMETERS: RegisterId - Index of ACPI Register to access 0602 * 0603 * RETURN: The bitmask to be used when accessing the register 0604 * 0605 * DESCRIPTION: Map RegisterId into a register bitmask. 0606 * 0607 ******************************************************************************/ 0608 0609 ACPI_BIT_REGISTER_INFO * 0610 AcpiHwGetBitRegisterInfo ( 0611 UINT32 RegisterId) 0612 { 0613 ACPI_FUNCTION_ENTRY (); 0614 0615 0616 if (RegisterId > ACPI_BITREG_MAX) 0617 { 0618 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId)); 0619 return (NULL); 0620 } 0621 0622 return (&AcpiGbl_BitRegisterInfo[RegisterId]); 0623 } 0624 0625 0626 /****************************************************************************** 0627 * 0628 * FUNCTION: AcpiHwWritePm1Control 0629 * 0630 * PARAMETERS: Pm1aControl - Value to be written to PM1A control 0631 * Pm1bControl - Value to be written to PM1B control 0632 * 0633 * RETURN: Status 0634 * 0635 * DESCRIPTION: Write the PM1 A/B control registers. These registers are 0636 * different than the PM1 A/B status and enable registers 0637 * in that different values can be written to the A/B registers. 0638 * Most notably, the SLP_TYP bits can be different, as per the 0639 * values returned from the _Sx predefined methods. 0640 * 0641 ******************************************************************************/ 0642 0643 ACPI_STATUS 0644 AcpiHwWritePm1Control ( 0645 UINT32 Pm1aControl, 0646 UINT32 Pm1bControl) 0647 { 0648 ACPI_STATUS Status; 0649 0650 0651 ACPI_FUNCTION_TRACE (HwWritePm1Control); 0652 0653 0654 Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); 0655 if (ACPI_FAILURE (Status)) 0656 { 0657 return_ACPI_STATUS (Status); 0658 } 0659 0660 if (AcpiGbl_FADT.XPm1bControlBlock.Address) 0661 { 0662 Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); 0663 } 0664 return_ACPI_STATUS (Status); 0665 } 0666 0667 0668 /****************************************************************************** 0669 * 0670 * FUNCTION: AcpiHwRegisterRead 0671 * 0672 * PARAMETERS: RegisterId - ACPI Register ID 0673 * ReturnValue - Where the register value is returned 0674 * 0675 * RETURN: Status and the value read. 0676 * 0677 * DESCRIPTION: Read from the specified ACPI register 0678 * 0679 ******************************************************************************/ 0680 0681 ACPI_STATUS 0682 AcpiHwRegisterRead ( 0683 UINT32 RegisterId, 0684 UINT32 *ReturnValue) 0685 { 0686 UINT32 Value = 0; 0687 UINT64 Value64; 0688 ACPI_STATUS Status; 0689 0690 0691 ACPI_FUNCTION_TRACE (HwRegisterRead); 0692 0693 0694 switch (RegisterId) 0695 { 0696 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 0697 0698 Status = AcpiHwReadMultiple (&Value, 0699 &AcpiGbl_XPm1aStatus, 0700 &AcpiGbl_XPm1bStatus); 0701 break; 0702 0703 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 0704 0705 Status = AcpiHwReadMultiple (&Value, 0706 &AcpiGbl_XPm1aEnable, 0707 &AcpiGbl_XPm1bEnable); 0708 break; 0709 0710 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 0711 0712 Status = AcpiHwReadMultiple (&Value, 0713 &AcpiGbl_FADT.XPm1aControlBlock, 0714 &AcpiGbl_FADT.XPm1bControlBlock); 0715 0716 /* 0717 * Zero the write-only bits. From the ACPI specification, "Hardware 0718 * Write-Only Bits": "Upon reads to registers with write-only bits, 0719 * software masks out all write-only bits." 0720 */ 0721 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; 0722 break; 0723 0724 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 0725 0726 Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock); 0727 if (ACPI_SUCCESS (Status)) 0728 { 0729 Value = (UINT32) Value64; 0730 } 0731 break; 0732 0733 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 0734 0735 Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock); 0736 if (ACPI_SUCCESS (Status)) 0737 { 0738 Value = (UINT32) Value64; 0739 } 0740 0741 break; 0742 0743 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 0744 0745 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8); 0746 break; 0747 0748 default: 0749 0750 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", 0751 RegisterId)); 0752 Status = AE_BAD_PARAMETER; 0753 break; 0754 } 0755 0756 if (ACPI_SUCCESS (Status)) 0757 { 0758 *ReturnValue = (UINT32) Value; 0759 } 0760 0761 return_ACPI_STATUS (Status); 0762 } 0763 0764 0765 /****************************************************************************** 0766 * 0767 * FUNCTION: AcpiHwRegisterWrite 0768 * 0769 * PARAMETERS: RegisterId - ACPI Register ID 0770 * Value - The value to write 0771 * 0772 * RETURN: Status 0773 * 0774 * DESCRIPTION: Write to the specified ACPI register 0775 * 0776 * NOTE: In accordance with the ACPI specification, this function automatically 0777 * preserves the value of the following bits, meaning that these bits cannot be 0778 * changed via this interface: 0779 * 0780 * PM1_CONTROL[0] = SCI_EN 0781 * PM1_CONTROL[9] 0782 * PM1_STATUS[11] 0783 * 0784 * ACPI References: 0785 * 1) Hardware Ignored Bits: When software writes to a register with ignored 0786 * bit fields, it preserves the ignored bit fields 0787 * 2) SCI_EN: OSPM always preserves this bit position 0788 * 0789 ******************************************************************************/ 0790 0791 ACPI_STATUS 0792 AcpiHwRegisterWrite ( 0793 UINT32 RegisterId, 0794 UINT32 Value) 0795 { 0796 ACPI_STATUS Status; 0797 UINT32 ReadValue; 0798 UINT64 ReadValue64; 0799 0800 0801 ACPI_FUNCTION_TRACE (HwRegisterWrite); 0802 0803 0804 switch (RegisterId) 0805 { 0806 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ 0807 /* 0808 * Handle the "ignored" bit in PM1 Status. According to the ACPI 0809 * specification, ignored bits are to be preserved when writing. 0810 * Normally, this would mean a read/modify/write sequence. However, 0811 * preserving a bit in the status register is different. Writing a 0812 * one clears the status, and writing a zero preserves the status. 0813 * Therefore, we must always write zero to the ignored bit. 0814 * 0815 * This behavior is clarified in the ACPI 4.0 specification. 0816 */ 0817 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; 0818 0819 Status = AcpiHwWriteMultiple (Value, 0820 &AcpiGbl_XPm1aStatus, 0821 &AcpiGbl_XPm1bStatus); 0822 break; 0823 0824 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ 0825 0826 Status = AcpiHwWriteMultiple (Value, 0827 &AcpiGbl_XPm1aEnable, 0828 &AcpiGbl_XPm1bEnable); 0829 break; 0830 0831 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ 0832 /* 0833 * Perform a read first to preserve certain bits (per ACPI spec) 0834 * Note: This includes SCI_EN, we never want to change this bit 0835 */ 0836 Status = AcpiHwReadMultiple (&ReadValue, 0837 &AcpiGbl_FADT.XPm1aControlBlock, 0838 &AcpiGbl_FADT.XPm1bControlBlock); 0839 if (ACPI_FAILURE (Status)) 0840 { 0841 goto Exit; 0842 } 0843 0844 /* Insert the bits to be preserved */ 0845 0846 ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); 0847 0848 /* Now we can write the data */ 0849 0850 Status = AcpiHwWriteMultiple (Value, 0851 &AcpiGbl_FADT.XPm1aControlBlock, 0852 &AcpiGbl_FADT.XPm1bControlBlock); 0853 break; 0854 0855 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ 0856 /* 0857 * For control registers, all reserved bits must be preserved, 0858 * as per the ACPI spec. 0859 */ 0860 Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock); 0861 if (ACPI_FAILURE (Status)) 0862 { 0863 goto Exit; 0864 } 0865 ReadValue = (UINT32) ReadValue64; 0866 0867 /* Insert the bits to be preserved */ 0868 0869 ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); 0870 0871 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); 0872 break; 0873 0874 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ 0875 0876 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); 0877 break; 0878 0879 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ 0880 0881 /* SMI_CMD is currently always in IO space */ 0882 0883 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); 0884 break; 0885 0886 default: 0887 0888 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", 0889 RegisterId)); 0890 Status = AE_BAD_PARAMETER; 0891 break; 0892 } 0893 0894 Exit: 0895 return_ACPI_STATUS (Status); 0896 } 0897 0898 0899 /****************************************************************************** 0900 * 0901 * FUNCTION: AcpiHwReadMultiple 0902 * 0903 * PARAMETERS: Value - Where the register value is returned 0904 * RegisterA - First ACPI register (required) 0905 * RegisterB - Second ACPI register (optional) 0906 * 0907 * RETURN: Status 0908 * 0909 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) 0910 * 0911 ******************************************************************************/ 0912 0913 static ACPI_STATUS 0914 AcpiHwReadMultiple ( 0915 UINT32 *Value, 0916 ACPI_GENERIC_ADDRESS *RegisterA, 0917 ACPI_GENERIC_ADDRESS *RegisterB) 0918 { 0919 UINT32 ValueA = 0; 0920 UINT32 ValueB = 0; 0921 UINT64 Value64; 0922 ACPI_STATUS Status; 0923 0924 0925 /* The first register is always required */ 0926 0927 Status = AcpiHwRead (&Value64, RegisterA); 0928 if (ACPI_FAILURE (Status)) 0929 { 0930 return (Status); 0931 } 0932 ValueA = (UINT32) Value64; 0933 0934 /* Second register is optional */ 0935 0936 if (RegisterB->Address) 0937 { 0938 Status = AcpiHwRead (&Value64, RegisterB); 0939 if (ACPI_FAILURE (Status)) 0940 { 0941 return (Status); 0942 } 0943 ValueB = (UINT32) Value64; 0944 } 0945 0946 /* 0947 * OR the two return values together. No shifting or masking is necessary, 0948 * because of how the PM1 registers are defined in the ACPI specification: 0949 * 0950 * "Although the bits can be split between the two register blocks (each 0951 * register block has a unique pointer within the FADT), the bit positions 0952 * are maintained. The register block with unimplemented bits (that is, 0953 * those implemented in the other register block) always returns zeros, 0954 * and writes have no side effects" 0955 */ 0956 *Value = (ValueA | ValueB); 0957 return (AE_OK); 0958 } 0959 0960 0961 /****************************************************************************** 0962 * 0963 * FUNCTION: AcpiHwWriteMultiple 0964 * 0965 * PARAMETERS: Value - The value to write 0966 * RegisterA - First ACPI register (required) 0967 * RegisterB - Second ACPI register (optional) 0968 * 0969 * RETURN: Status 0970 * 0971 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) 0972 * 0973 ******************************************************************************/ 0974 0975 static ACPI_STATUS 0976 AcpiHwWriteMultiple ( 0977 UINT32 Value, 0978 ACPI_GENERIC_ADDRESS *RegisterA, 0979 ACPI_GENERIC_ADDRESS *RegisterB) 0980 { 0981 ACPI_STATUS Status; 0982 0983 0984 /* The first register is always required */ 0985 0986 Status = AcpiHwWrite (Value, RegisterA); 0987 if (ACPI_FAILURE (Status)) 0988 { 0989 return (Status); 0990 } 0991 0992 /* 0993 * Second register is optional 0994 * 0995 * No bit shifting or clearing is necessary, because of how the PM1 0996 * registers are defined in the ACPI specification: 0997 * 0998 * "Although the bits can be split between the two register blocks (each 0999 * register block has a unique pointer within the FADT), the bit positions 1000 * are maintained. The register block with unimplemented bits (that is, 1001 * those implemented in the other register block) always returns zeros, 1002 * and writes have no side effects" 1003 */ 1004 if (RegisterB->Address) 1005 { 1006 Status = AcpiHwWrite (Value, RegisterB); 1007 } 1008 1009 return (Status); 1010 } 1011 1012 #endif /* !ACPI_REDUCED_HARDWARE */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |