Print this page
update to acpica-unix2-20130927
acpica-unix2-20130823
PANKOVs restructure

*** 1,14 **** - /****************************************************************************** * * Module Name: hwxface - Public ACPICA hardware interfaces * *****************************************************************************/ /* ! * Copyright (C) 2000 - 2011, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: --- 1,13 ---- /****************************************************************************** * * Module Name: hwxface - Public ACPICA hardware interfaces * *****************************************************************************/ /* ! * Copyright (C) 2000 - 2013, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met:
*** 40,49 **** --- 39,50 ---- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ + #define EXPORT_ACPI_INTERFACES + #include "acpi.h" #include "accommon.h" #include "acnamesp.h" #define _COMPONENT ACPI_HARDWARE
*** 89,101 **** { /* * For I/O space, write directly to the OSL. This bypasses the port * validation mechanism, which may block a valid write to the reset * register. */ Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, ! AcpiGbl_FADT.ResetValue, ResetReg->BitWidth); } else { /* Write the reset value to the reset register */ --- 90,108 ---- { /* * For I/O space, write directly to the OSL. This bypasses the port * validation mechanism, which may block a valid write to the reset * register. + * + * NOTE: + * The ACPI spec requires the reset register width to be 8, so we + * hardcode it here and ignore the FADT value. This maintains + * compatibility with other ACPI implementations that have allowed + * BIOS code with bad register width values to go unnoticed. */ Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, ! AcpiGbl_FADT.ResetValue, ACPI_RESET_REGISTER_WIDTH); } else { /* Write the reset value to the reset register */
*** 130,140 **** ACPI_STATUS AcpiRead ( UINT64 *ReturnValue, ACPI_GENERIC_ADDRESS *Reg) { ! UINT32 Value; UINT32 Width; UINT64 Address; ACPI_STATUS Status; --- 137,148 ---- ACPI_STATUS AcpiRead ( UINT64 *ReturnValue, ACPI_GENERIC_ADDRESS *Reg) { ! UINT32 ValueLo; ! UINT32 ValueHi; UINT32 Width; UINT64 Address; ACPI_STATUS Status;
*** 152,230 **** if (ACPI_FAILURE (Status)) { return (Status); } - Width = Reg->BitWidth; - if (Width == 64) - { - Width = 32; /* Break into two 32-bit transfers */ - } - - /* Initialize entire 64-bit return value to zero */ - - *ReturnValue = 0; - Value = 0; - /* ! * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) ! Address, &Value, Width); if (ACPI_FAILURE (Status)) { return (Status); } ! *ReturnValue = Value; ! ! if (Reg->BitWidth == 64) { ! /* Read the top 32 bits */ ! Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) ! (Address + 4), &Value, 32); ! if (ACPI_FAILURE (Status)) { ! return (Status); } ! *ReturnValue |= ((UINT64) Value << 32); ! } ! } ! else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ ! { Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) ! Address, &Value, Width); if (ACPI_FAILURE (Status)) { return (Status); } - *ReturnValue = Value; if (Reg->BitWidth == 64) { /* Read the top 32 bits */ Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) ! (Address + 4), &Value, 32); if (ACPI_FAILURE (Status)) { return (Status); } - *ReturnValue |= ((UINT64) Value << 32); } } ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId))); ! return (Status); } ACPI_EXPORT_SYMBOL (AcpiRead) --- 160,224 ---- if (ACPI_FAILURE (Status)) { return (Status); } /* ! * Two address spaces supported: Memory or I/O. PCI_Config is * not supported here because the GAS structure is insufficient */ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) ! Address, ReturnValue, Reg->BitWidth); if (ACPI_FAILURE (Status)) { return (Status); } ! } ! else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { ! ValueLo = 0; ! ValueHi = 0; ! Width = Reg->BitWidth; ! if (Width == 64) { ! Width = 32; /* Break into two 32-bit transfers */ } ! Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) ! Address, &ValueLo, Width); if (ACPI_FAILURE (Status)) { return (Status); } if (Reg->BitWidth == 64) { /* Read the top 32 bits */ Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) ! (Address + 4), &ValueHi, 32); if (ACPI_FAILURE (Status)) { return (Status); } } + + /* Set the return value only if status is AE_OK */ + + *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32)); } ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, ACPI_FORMAT_UINT64 (Address), AcpiUtGetRegionName (Reg->SpaceId))); ! return (AE_OK); } ACPI_EXPORT_SYMBOL (AcpiRead)
*** 260,300 **** if (ACPI_FAILURE (Status)) { return (Status); } - Width = Reg->BitWidth; - if (Width == 64) - { - Width = 32; /* Break into two 32-bit transfers */ - } - /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) ! Address, ACPI_LODWORD (Value), Width); if (ACPI_FAILURE (Status)) { return (Status); } - - if (Reg->BitWidth == 64) - { - Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) - (Address + 4), ACPI_HIDWORD (Value), 32); - if (ACPI_FAILURE (Status)) - { - return (Status); } - } - } else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address, ACPI_LODWORD (Value), Width); if (ACPI_FAILURE (Status)) { return (Status); --- 254,284 ---- if (ACPI_FAILURE (Status)) { return (Status); } /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) ! Address, Value, Reg->BitWidth); if (ACPI_FAILURE (Status)) { return (Status); } } else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { + Width = Reg->BitWidth; + if (Width == 64) + { + Width = 32; /* Break into two 32-bit transfers */ + } + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address, ACPI_LODWORD (Value), Width); if (ACPI_FAILURE (Status)) { return (Status);
*** 321,330 **** --- 305,315 ---- } ACPI_EXPORT_SYMBOL (AcpiWrite) + #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: AcpiReadBitRegister * * PARAMETERS: RegisterId - ID of ACPI Bit Register to access
*** 399,409 **** * * FUNCTION: AcpiWriteBitRegister * * PARAMETERS: RegisterId - ID of ACPI Bit Register to access * Value - Value to write to the register, in bit ! * position zero. The bit is automaticallly * shifted to the correct position. * * RETURN: Status * * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock --- 384,394 ---- * * FUNCTION: AcpiWriteBitRegister * * PARAMETERS: RegisterId - ID of ACPI Bit Register to access * Value - Value to write to the register, in bit ! * position zero. The bit is automatically * shifted to the correct position. * * RETURN: Status * * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
*** 503,546 **** return_ACPI_STATUS (Status); } ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) /******************************************************************************* * * FUNCTION: AcpiGetSleepTypeData * * PARAMETERS: SleepState - Numeric sleep state * *SleepTypeA - Where SLP_TYPa is returned * *SleepTypeB - Where SLP_TYPb is returned * ! * RETURN: Status - ACPI status * ! * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep ! * state. * ******************************************************************************/ ACPI_STATUS AcpiGetSleepTypeData ( UINT8 SleepState, UINT8 *SleepTypeA, UINT8 *SleepTypeB) { ! ACPI_STATUS Status = AE_OK; ACPI_EVALUATE_INFO *Info; ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); /* Validate parameters */ if ((SleepState > ACPI_S_STATES_MAX) || ! !SleepTypeA || ! !SleepTypeB) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Allocate the evaluation information block */ --- 488,556 ---- return_ACPI_STATUS (Status); } ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) + #endif /* !ACPI_REDUCED_HARDWARE */ + /******************************************************************************* * * FUNCTION: AcpiGetSleepTypeData * * PARAMETERS: SleepState - Numeric sleep state * *SleepTypeA - Where SLP_TYPa is returned * *SleepTypeB - Where SLP_TYPb is returned * ! * RETURN: Status * ! * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested ! * sleep state via the appropriate \_Sx object. * + * The sleep state package returned from the corresponding \_Sx_ object + * must contain at least one integer. + * + * March 2005: + * Added support for a package that contains two integers. This + * goes against the ACPI specification which defines this object as a + * package with one encoded DWORD integer. However, existing practice + * by many BIOS vendors is to return a package with 2 or more integer + * elements, at least one per sleep type (A/B). + * + * January 2013: + * Therefore, we must be prepared to accept a package with either a + * single integer or multiple integers. + * + * The single integer DWORD format is as follows: + * BYTE 0 - Value for the PM1A SLP_TYP register + * BYTE 1 - Value for the PM1B SLP_TYP register + * BYTE 2-3 - Reserved + * + * The dual integer format is as follows: + * Integer 0 - Value for the PM1A SLP_TYP register + * Integer 1 - Value for the PM1A SLP_TYP register + * ******************************************************************************/ ACPI_STATUS AcpiGetSleepTypeData ( UINT8 SleepState, UINT8 *SleepTypeA, UINT8 *SleepTypeB) { ! ACPI_STATUS Status; ACPI_EVALUATE_INFO *Info; + ACPI_OPERAND_OBJECT **Elements; ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); /* Validate parameters */ if ((SleepState > ACPI_S_STATES_MAX) || ! !SleepTypeA || !SleepTypeB) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Allocate the evaluation information block */
*** 549,638 **** if (!Info) { return_ACPI_STATUS (AE_NO_MEMORY); } ! Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); ! ! /* Evaluate the namespace object containing the values for this state */ ! Status = AcpiNsEvaluate (Info); if (ACPI_FAILURE (Status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "%s while evaluating SleepState [%s]\n", - AcpiFormatException (Status), Info->Pathname)); - goto Cleanup; } /* Must have a return object */ if (!Info->ReturnObject) { ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", ! Info->Pathname)); ! Status = AE_NOT_EXIST; } ! /* It must be of type Package */ ! else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) { ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); Status = AE_AML_OPERAND_TYPE; } /* ! * The package must have at least two elements. NOTE (March 2005): This ! * goes against the current ACPI spec which defines this object as a ! * package with one encoded DWORD element. However, existing practice ! * by BIOS vendors seems to be to have 2 or more elements, at least ! * one per sleep type (A/B). */ ! else if (Info->ReturnObject->Package.Count < 2) { ! ACPI_ERROR ((AE_INFO, ! "Sleep State return package does not have at least two elements")); ! Status = AE_AML_NO_OPERAND; ! } ! /* The first two elements must both be of type Integer */ ! else if (((Info->ReturnObject->Package.Elements[0])->Common.Type ! != ACPI_TYPE_INTEGER) || ! ((Info->ReturnObject->Package.Elements[1])->Common.Type ! != ACPI_TYPE_INTEGER)) { - ACPI_ERROR ((AE_INFO, - "Sleep State return package elements are not both Integers " - "(%s, %s)", - AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), - AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); Status = AE_AML_OPERAND_TYPE; } ! else { ! /* Valid _Sx_ package size, type, and value */ ! *SleepTypeA = (UINT8) ! (Info->ReturnObject->Package.Elements[0])->Integer.Value; ! *SleepTypeB = (UINT8) ! (Info->ReturnObject->Package.Elements[1])->Integer.Value; } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, ! "While evaluating SleepState [%s], bad Sleep object %p type %s", ! Info->Pathname, Info->ReturnObject, ! AcpiUtGetObjectTypeName (Info->ReturnObject))); } - AcpiUtRemoveReference (Info->ReturnObject); - - Cleanup: ACPI_FREE (Info); return_ACPI_STATUS (Status); } ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) --- 559,653 ---- if (!Info) { return_ACPI_STATUS (AE_NO_MEMORY); } ! /* ! * Evaluate the \_Sx namespace object containing the register values ! * for this state ! */ ! Info->RelativePathname = ACPI_CAST_PTR ( ! char, AcpiGbl_SleepStateNames[SleepState]); Status = AcpiNsEvaluate (Info); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Must have a return object */ if (!Info->ReturnObject) { ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", ! Info->RelativePathname)); ! Status = AE_AML_NO_RETURN_VALUE; ! goto Cleanup; } ! /* Return object must be of type Package */ ! if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) { ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); Status = AE_AML_OPERAND_TYPE; + goto Cleanup1; } /* ! * Any warnings about the package length or the object types have ! * already been issued by the predefined name module -- there is no ! * need to repeat them here. */ ! Elements = Info->ReturnObject->Package.Elements; ! switch (Info->ReturnObject->Package.Count) { ! case 0: ! Status = AE_AML_PACKAGE_LIMIT; ! break; ! case 1: ! ! if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER) { Status = AE_AML_OPERAND_TYPE; + break; } ! ! /* A valid _Sx_ package with one integer */ ! ! *SleepTypeA = (UINT8) Elements[0]->Integer.Value; ! *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8); ! break; ! ! case 2: ! default: ! ! if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) || ! (Elements[1]->Common.Type != ACPI_TYPE_INTEGER)) { ! Status = AE_AML_OPERAND_TYPE; ! break; ! } ! /* A valid _Sx_ package with two integers */ ! ! *SleepTypeA = (UINT8) Elements[0]->Integer.Value; ! *SleepTypeB = (UINT8) Elements[1]->Integer.Value; ! break; } + Cleanup1: + AcpiUtRemoveReference (Info->ReturnObject); + + Cleanup: if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, ! "While evaluating Sleep State [%s]", Info->RelativePathname)); } ACPI_FREE (Info); return_ACPI_STATUS (Status); } ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)