1193267Sjkim/****************************************************************************** 2193267Sjkim * 3193267Sjkim * Module Name: hwxface - Public ACPICA hardware interfaces 4193267Sjkim * 5193267Sjkim *****************************************************************************/ 6193267Sjkim 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9193267Sjkim * All rights reserved. 10193267Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25193267Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29193267Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43193267Sjkim 44281075Sdim#define EXPORT_ACPI_INTERFACES 45281075Sdim 46193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 47193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 48193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 49193267Sjkim 50193267Sjkim#define _COMPONENT ACPI_HARDWARE 51193267Sjkim ACPI_MODULE_NAME ("hwxface") 52193267Sjkim 53193267Sjkim 54193267Sjkim/****************************************************************************** 55193267Sjkim * 56193267Sjkim * FUNCTION: AcpiReset 57193267Sjkim * 58193267Sjkim * PARAMETERS: None 59193267Sjkim * 60193267Sjkim * RETURN: Status 61193267Sjkim * 62193267Sjkim * DESCRIPTION: Set reset register in memory or IO space. Note: Does not 63193267Sjkim * support reset register in PCI config space, this must be 64193267Sjkim * handled separately. 65193267Sjkim * 66193267Sjkim ******************************************************************************/ 67193267Sjkim 68193267SjkimACPI_STATUS 69193267SjkimAcpiReset ( 70193267Sjkim void) 71193267Sjkim{ 72193267Sjkim ACPI_GENERIC_ADDRESS *ResetReg; 73193267Sjkim ACPI_STATUS Status; 74193267Sjkim 75193267Sjkim 76193267Sjkim ACPI_FUNCTION_TRACE (AcpiReset); 77193267Sjkim 78193267Sjkim 79193267Sjkim ResetReg = &AcpiGbl_FADT.ResetRegister; 80193267Sjkim 81193267Sjkim /* Check if the reset register is supported */ 82193267Sjkim 83193267Sjkim if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) || 84193267Sjkim !ResetReg->Address) 85193267Sjkim { 86193267Sjkim return_ACPI_STATUS (AE_NOT_EXIST); 87193267Sjkim } 88193267Sjkim 89197104Sjkim if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) 90197104Sjkim { 91197104Sjkim /* 92197104Sjkim * For I/O space, write directly to the OSL. This bypasses the port 93197104Sjkim * validation mechanism, which may block a valid write to the reset 94197104Sjkim * register. 95281075Sdim * 96281075Sdim * NOTE: 97281075Sdim * The ACPI spec requires the reset register width to be 8, so we 98281075Sdim * hardcode it here and ignore the FADT value. This maintains 99281075Sdim * compatibility with other ACPI implementations that have allowed 100281075Sdim * BIOS code with bad register width values to go unnoticed. 101197104Sjkim */ 102197104Sjkim Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, 103281075Sdim AcpiGbl_FADT.ResetValue, ACPI_RESET_REGISTER_WIDTH); 104197104Sjkim } 105197104Sjkim else 106197104Sjkim { 107197104Sjkim /* Write the reset value to the reset register */ 108193267Sjkim 109197104Sjkim Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg); 110197104Sjkim } 111197104Sjkim 112193267Sjkim return_ACPI_STATUS (Status); 113193267Sjkim} 114193267Sjkim 115193267SjkimACPI_EXPORT_SYMBOL (AcpiReset) 116193267Sjkim 117193267Sjkim 118193267Sjkim/****************************************************************************** 119193267Sjkim * 120193267Sjkim * FUNCTION: AcpiRead 121193267Sjkim * 122193267Sjkim * PARAMETERS: Value - Where the value is returned 123193267Sjkim * Reg - GAS register structure 124193267Sjkim * 125193267Sjkim * RETURN: Status 126193267Sjkim * 127193267Sjkim * DESCRIPTION: Read from either memory or IO space. 128193267Sjkim * 129197104Sjkim * LIMITATIONS: <These limitations also apply to AcpiWrite> 130197104Sjkim * BitWidth must be exactly 8, 16, 32, or 64. 131197104Sjkim * SpaceID must be SystemMemory or SystemIO. 132197104Sjkim * BitOffset and AccessWidth are currently ignored, as there has 133197104Sjkim * not been a need to implement these. 134197104Sjkim * 135193267Sjkim ******************************************************************************/ 136193267Sjkim 137193267SjkimACPI_STATUS 138193267SjkimAcpiRead ( 139197104Sjkim UINT64 *ReturnValue, 140193267Sjkim ACPI_GENERIC_ADDRESS *Reg) 141193267Sjkim{ 142254745Sjkim UINT32 ValueLo; 143254745Sjkim UINT32 ValueHi; 144193267Sjkim UINT32 Width; 145193267Sjkim UINT64 Address; 146193267Sjkim ACPI_STATUS Status; 147193267Sjkim 148193267Sjkim 149193267Sjkim ACPI_FUNCTION_NAME (AcpiRead); 150193267Sjkim 151193267Sjkim 152197104Sjkim if (!ReturnValue) 153193267Sjkim { 154193267Sjkim return (AE_BAD_PARAMETER); 155193267Sjkim } 156193267Sjkim 157197104Sjkim /* Validate contents of the GAS register. Allow 64-bit transfers */ 158193267Sjkim 159197104Sjkim Status = AcpiHwValidateRegister (Reg, 64, &Address); 160197104Sjkim if (ACPI_FAILURE (Status)) 161193267Sjkim { 162197104Sjkim return (Status); 163193267Sjkim } 164193267Sjkim 165193267Sjkim /* 166254745Sjkim * Two address spaces supported: Memory or I/O. PCI_Config is 167193267Sjkim * not supported here because the GAS structure is insufficient 168193267Sjkim */ 169197104Sjkim if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 170193267Sjkim { 171197104Sjkim Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 172306536Sjkim Address, ReturnValue, Reg->BitWidth); 173197104Sjkim if (ACPI_FAILURE (Status)) 174197104Sjkim { 175197104Sjkim return (Status); 176197104Sjkim } 177197104Sjkim } 178197104Sjkim else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 179197104Sjkim { 180254745Sjkim ValueLo = 0; 181254745Sjkim ValueHi = 0; 182254745Sjkim 183231844Sjkim Width = Reg->BitWidth; 184231844Sjkim if (Width == 64) 185231844Sjkim { 186231844Sjkim Width = 32; /* Break into two 32-bit transfers */ 187231844Sjkim } 188231844Sjkim 189197104Sjkim Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 190306536Sjkim Address, &ValueLo, Width); 191197104Sjkim if (ACPI_FAILURE (Status)) 192197104Sjkim { 193197104Sjkim return (Status); 194197104Sjkim } 195193267Sjkim 196197104Sjkim if (Reg->BitWidth == 64) 197197104Sjkim { 198197104Sjkim /* Read the top 32 bits */ 199193267Sjkim 200197104Sjkim Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 201306536Sjkim (Address + 4), &ValueHi, 32); 202197104Sjkim if (ACPI_FAILURE (Status)) 203197104Sjkim { 204197104Sjkim return (Status); 205197104Sjkim } 206197104Sjkim } 207254745Sjkim 208254745Sjkim /* Set the return value only if status is AE_OK */ 209254745Sjkim 210254745Sjkim *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32)); 211193267Sjkim } 212193267Sjkim 213193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 214197104Sjkim "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", 215197104Sjkim ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, 216197104Sjkim ACPI_FORMAT_UINT64 (Address), 217193267Sjkim AcpiUtGetRegionName (Reg->SpaceId))); 218193267Sjkim 219254745Sjkim return (AE_OK); 220193267Sjkim} 221193267Sjkim 222193267SjkimACPI_EXPORT_SYMBOL (AcpiRead) 223193267Sjkim 224193267Sjkim 225193267Sjkim/****************************************************************************** 226193267Sjkim * 227193267Sjkim * FUNCTION: AcpiWrite 228193267Sjkim * 229197104Sjkim * PARAMETERS: Value - Value to be written 230193267Sjkim * Reg - GAS register structure 231193267Sjkim * 232193267Sjkim * RETURN: Status 233193267Sjkim * 234193267Sjkim * DESCRIPTION: Write to either memory or IO space. 235193267Sjkim * 236193267Sjkim ******************************************************************************/ 237193267Sjkim 238193267SjkimACPI_STATUS 239193267SjkimAcpiWrite ( 240197104Sjkim UINT64 Value, 241193267Sjkim ACPI_GENERIC_ADDRESS *Reg) 242193267Sjkim{ 243193267Sjkim UINT32 Width; 244193267Sjkim UINT64 Address; 245193267Sjkim ACPI_STATUS Status; 246193267Sjkim 247193267Sjkim 248193267Sjkim ACPI_FUNCTION_NAME (AcpiWrite); 249193267Sjkim 250193267Sjkim 251197104Sjkim /* Validate contents of the GAS register. Allow 64-bit transfers */ 252193267Sjkim 253197104Sjkim Status = AcpiHwValidateRegister (Reg, 64, &Address); 254197104Sjkim if (ACPI_FAILURE (Status)) 255193267Sjkim { 256197104Sjkim return (Status); 257193267Sjkim } 258193267Sjkim 259193267Sjkim /* 260197104Sjkim * Two address spaces supported: Memory or IO. PCI_Config is 261197104Sjkim * not supported here because the GAS structure is insufficient 262193267Sjkim */ 263197104Sjkim if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 264193267Sjkim { 265197104Sjkim Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 266306536Sjkim Address, Value, Reg->BitWidth); 267197104Sjkim if (ACPI_FAILURE (Status)) 268197104Sjkim { 269197104Sjkim return (Status); 270197104Sjkim } 271197104Sjkim } 272197104Sjkim else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 273197104Sjkim { 274231844Sjkim Width = Reg->BitWidth; 275231844Sjkim if (Width == 64) 276231844Sjkim { 277231844Sjkim Width = 32; /* Break into two 32-bit transfers */ 278231844Sjkim } 279231844Sjkim 280197104Sjkim Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 281306536Sjkim Address, ACPI_LODWORD (Value), Width); 282197104Sjkim if (ACPI_FAILURE (Status)) 283197104Sjkim { 284197104Sjkim return (Status); 285197104Sjkim } 286193267Sjkim 287197104Sjkim if (Reg->BitWidth == 64) 288197104Sjkim { 289197104Sjkim Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 290306536Sjkim (Address + 4), ACPI_HIDWORD (Value), 32); 291197104Sjkim if (ACPI_FAILURE (Status)) 292197104Sjkim { 293197104Sjkim return (Status); 294197104Sjkim } 295197104Sjkim } 296193267Sjkim } 297193267Sjkim 298193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 299197104Sjkim "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", 300197104Sjkim ACPI_FORMAT_UINT64 (Value), Reg->BitWidth, 301197104Sjkim ACPI_FORMAT_UINT64 (Address), 302193267Sjkim AcpiUtGetRegionName (Reg->SpaceId))); 303193267Sjkim 304193267Sjkim return (Status); 305193267Sjkim} 306193267Sjkim 307193267SjkimACPI_EXPORT_SYMBOL (AcpiWrite) 308193267Sjkim 309193267Sjkim 310231844Sjkim#if (!ACPI_REDUCED_HARDWARE) 311193267Sjkim/******************************************************************************* 312193267Sjkim * 313193267Sjkim * FUNCTION: AcpiReadBitRegister 314193267Sjkim * 315193267Sjkim * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 316193267Sjkim * ReturnValue - Value that was read from the register, 317193267Sjkim * normalized to bit position zero. 318193267Sjkim * 319193267Sjkim * RETURN: Status and the value read from the specified Register. Value 320193267Sjkim * returned is normalized to bit0 (is shifted all the way right) 321193267Sjkim * 322193267Sjkim * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock. 323193267Sjkim * 324193267Sjkim * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 325193267Sjkim * PM2 Control. 326193267Sjkim * 327193267Sjkim * Note: The hardware lock is not required when reading the ACPI bit registers 328193267Sjkim * since almost all of them are single bit and it does not matter that 329193267Sjkim * the parent hardware register can be split across two physical 330193267Sjkim * registers. The only multi-bit field is SLP_TYP in the PM1 control 331193267Sjkim * register, but this field does not cross an 8-bit boundary (nor does 332193267Sjkim * it make much sense to actually read this field.) 333193267Sjkim * 334193267Sjkim ******************************************************************************/ 335193267Sjkim 336193267SjkimACPI_STATUS 337193267SjkimAcpiReadBitRegister ( 338193267Sjkim UINT32 RegisterId, 339193267Sjkim UINT32 *ReturnValue) 340193267Sjkim{ 341193267Sjkim ACPI_BIT_REGISTER_INFO *BitRegInfo; 342193267Sjkim UINT32 RegisterValue; 343193267Sjkim UINT32 Value; 344193267Sjkim ACPI_STATUS Status; 345193267Sjkim 346193267Sjkim 347193267Sjkim ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId); 348193267Sjkim 349193267Sjkim 350193267Sjkim /* Get the info structure corresponding to the requested ACPI Register */ 351193267Sjkim 352193267Sjkim BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 353193267Sjkim if (!BitRegInfo) 354193267Sjkim { 355193267Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 356193267Sjkim } 357193267Sjkim 358193267Sjkim /* Read the entire parent register */ 359193267Sjkim 360193267Sjkim Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 361306536Sjkim &RegisterValue); 362193267Sjkim if (ACPI_FAILURE (Status)) 363193267Sjkim { 364193267Sjkim return_ACPI_STATUS (Status); 365193267Sjkim } 366193267Sjkim 367193267Sjkim /* Normalize the value that was read, mask off other bits */ 368193267Sjkim 369193267Sjkim Value = ((RegisterValue & BitRegInfo->AccessBitMask) 370306536Sjkim >> BitRegInfo->BitPosition); 371193267Sjkim 372193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 373193267Sjkim "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", 374193267Sjkim RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value)); 375193267Sjkim 376193267Sjkim *ReturnValue = Value; 377193267Sjkim return_ACPI_STATUS (AE_OK); 378193267Sjkim} 379193267Sjkim 380193267SjkimACPI_EXPORT_SYMBOL (AcpiReadBitRegister) 381193267Sjkim 382193267Sjkim 383193267Sjkim/******************************************************************************* 384193267Sjkim * 385193267Sjkim * FUNCTION: AcpiWriteBitRegister 386193267Sjkim * 387193267Sjkim * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 388193267Sjkim * Value - Value to write to the register, in bit 389245582Sjkim * position zero. The bit is automatically 390193267Sjkim * shifted to the correct position. 391193267Sjkim * 392193267Sjkim * RETURN: Status 393193267Sjkim * 394193267Sjkim * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock 395193267Sjkim * since most operations require a read/modify/write sequence. 396193267Sjkim * 397193267Sjkim * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 398193267Sjkim * PM2 Control. 399193267Sjkim * 400193267Sjkim * Note that at this level, the fact that there may be actually two 401193267Sjkim * hardware registers (A and B - and B may not exist) is abstracted. 402193267Sjkim * 403193267Sjkim ******************************************************************************/ 404193267Sjkim 405193267SjkimACPI_STATUS 406193267SjkimAcpiWriteBitRegister ( 407193267Sjkim UINT32 RegisterId, 408193267Sjkim UINT32 Value) 409193267Sjkim{ 410193267Sjkim ACPI_BIT_REGISTER_INFO *BitRegInfo; 411193267Sjkim ACPI_CPU_FLAGS LockFlags; 412193267Sjkim UINT32 RegisterValue; 413193267Sjkim ACPI_STATUS Status = AE_OK; 414193267Sjkim 415193267Sjkim 416193267Sjkim ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId); 417193267Sjkim 418193267Sjkim 419193267Sjkim /* Get the info structure corresponding to the requested ACPI Register */ 420193267Sjkim 421193267Sjkim BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 422193267Sjkim if (!BitRegInfo) 423193267Sjkim { 424193267Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 425193267Sjkim } 426193267Sjkim 427193267Sjkim LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 428193267Sjkim 429193267Sjkim /* 430193267Sjkim * At this point, we know that the parent register is one of the 431193267Sjkim * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control 432193267Sjkim */ 433193267Sjkim if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS) 434193267Sjkim { 435193267Sjkim /* 436193267Sjkim * 1) Case for PM1 Enable, PM1 Control, and PM2 Control 437193267Sjkim * 438193267Sjkim * Perform a register read to preserve the bits that we are not 439193267Sjkim * interested in 440193267Sjkim */ 441193267Sjkim Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 442306536Sjkim &RegisterValue); 443193267Sjkim if (ACPI_FAILURE (Status)) 444193267Sjkim { 445193267Sjkim goto UnlockAndExit; 446193267Sjkim } 447193267Sjkim 448193267Sjkim /* 449193267Sjkim * Insert the input bit into the value that was just read 450193267Sjkim * and write the register 451193267Sjkim */ 452193267Sjkim ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 453193267Sjkim BitRegInfo->AccessBitMask, Value); 454193267Sjkim 455193267Sjkim Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister, 456306536Sjkim RegisterValue); 457193267Sjkim } 458193267Sjkim else 459193267Sjkim { 460193267Sjkim /* 461193267Sjkim * 2) Case for PM1 Status 462193267Sjkim * 463193267Sjkim * The Status register is different from the rest. Clear an event 464193267Sjkim * by writing 1, writing 0 has no effect. So, the only relevant 465193267Sjkim * information is the single bit we're interested in, all others 466193267Sjkim * should be written as 0 so they will be left unchanged. 467193267Sjkim */ 468193267Sjkim RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value, 469193267Sjkim BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 470193267Sjkim 471193267Sjkim /* No need to write the register if value is all zeros */ 472193267Sjkim 473193267Sjkim if (RegisterValue) 474193267Sjkim { 475193267Sjkim Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 476306536Sjkim RegisterValue); 477193267Sjkim } 478193267Sjkim } 479193267Sjkim 480193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 481193267Sjkim "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", 482193267Sjkim RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue)); 483193267Sjkim 484193267Sjkim 485193267SjkimUnlockAndExit: 486193267Sjkim 487193267Sjkim AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 488193267Sjkim return_ACPI_STATUS (Status); 489193267Sjkim} 490193267Sjkim 491193267SjkimACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) 492193267Sjkim 493231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 494193267Sjkim 495231844Sjkim 496193267Sjkim/******************************************************************************* 497193267Sjkim * 498193267Sjkim * FUNCTION: AcpiGetSleepTypeData 499193267Sjkim * 500193267Sjkim * PARAMETERS: SleepState - Numeric sleep state 501193267Sjkim * *SleepTypeA - Where SLP_TYPa is returned 502193267Sjkim * *SleepTypeB - Where SLP_TYPb is returned 503193267Sjkim * 504245582Sjkim * RETURN: Status 505193267Sjkim * 506245582Sjkim * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested 507245582Sjkim * sleep state via the appropriate \_Sx object. 508193267Sjkim * 509245582Sjkim * The sleep state package returned from the corresponding \_Sx_ object 510245582Sjkim * must contain at least one integer. 511245582Sjkim * 512245582Sjkim * March 2005: 513245582Sjkim * Added support for a package that contains two integers. This 514245582Sjkim * goes against the ACPI specification which defines this object as a 515245582Sjkim * package with one encoded DWORD integer. However, existing practice 516245582Sjkim * by many BIOS vendors is to return a package with 2 or more integer 517245582Sjkim * elements, at least one per sleep type (A/B). 518245582Sjkim * 519245582Sjkim * January 2013: 520245582Sjkim * Therefore, we must be prepared to accept a package with either a 521245582Sjkim * single integer or multiple integers. 522245582Sjkim * 523245582Sjkim * The single integer DWORD format is as follows: 524245582Sjkim * BYTE 0 - Value for the PM1A SLP_TYP register 525245582Sjkim * BYTE 1 - Value for the PM1B SLP_TYP register 526245582Sjkim * BYTE 2-3 - Reserved 527245582Sjkim * 528245582Sjkim * The dual integer format is as follows: 529245582Sjkim * Integer 0 - Value for the PM1A SLP_TYP register 530245582Sjkim * Integer 1 - Value for the PM1A SLP_TYP register 531245582Sjkim * 532193267Sjkim ******************************************************************************/ 533193267Sjkim 534193267SjkimACPI_STATUS 535193267SjkimAcpiGetSleepTypeData ( 536193267Sjkim UINT8 SleepState, 537193267Sjkim UINT8 *SleepTypeA, 538193267Sjkim UINT8 *SleepTypeB) 539193267Sjkim{ 540245582Sjkim ACPI_STATUS Status; 541193267Sjkim ACPI_EVALUATE_INFO *Info; 542245582Sjkim ACPI_OPERAND_OBJECT **Elements; 543193267Sjkim 544193267Sjkim 545193267Sjkim ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 546193267Sjkim 547193267Sjkim 548193267Sjkim /* Validate parameters */ 549193267Sjkim 550193267Sjkim if ((SleepState > ACPI_S_STATES_MAX) || 551245582Sjkim !SleepTypeA || !SleepTypeB) 552193267Sjkim { 553193267Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 554193267Sjkim } 555193267Sjkim 556193267Sjkim /* Allocate the evaluation information block */ 557193267Sjkim 558193267Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 559193267Sjkim if (!Info) 560193267Sjkim { 561193267Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 562193267Sjkim } 563193267Sjkim 564245582Sjkim /* 565245582Sjkim * Evaluate the \_Sx namespace object containing the register values 566245582Sjkim * for this state 567245582Sjkim */ 568306536Sjkim Info->RelativePathname = AcpiGbl_SleepStateNames[SleepState]; 569306536Sjkim 570193267Sjkim Status = AcpiNsEvaluate (Info); 571193267Sjkim if (ACPI_FAILURE (Status)) 572193267Sjkim { 573306536Sjkim if (Status == AE_NOT_FOUND) 574306536Sjkim { 575306536Sjkim /* The _Sx states are optional, ignore NOT_FOUND */ 576306536Sjkim 577306536Sjkim goto FinalCleanup; 578306536Sjkim } 579306536Sjkim 580306536Sjkim goto WarningCleanup; 581193267Sjkim } 582193267Sjkim 583193267Sjkim /* Must have a return object */ 584193267Sjkim 585193267Sjkim if (!Info->ReturnObject) 586193267Sjkim { 587193267Sjkim ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 588249663Sjkim Info->RelativePathname)); 589245582Sjkim Status = AE_AML_NO_RETURN_VALUE; 590306536Sjkim goto WarningCleanup; 591193267Sjkim } 592193267Sjkim 593245582Sjkim /* Return object must be of type Package */ 594193267Sjkim 595245582Sjkim if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 596193267Sjkim { 597193267Sjkim ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 598193267Sjkim Status = AE_AML_OPERAND_TYPE; 599306536Sjkim goto ReturnValueCleanup; 600193267Sjkim } 601193267Sjkim 602193267Sjkim /* 603245582Sjkim * Any warnings about the package length or the object types have 604245582Sjkim * already been issued by the predefined name module -- there is no 605245582Sjkim * need to repeat them here. 606193267Sjkim */ 607245582Sjkim Elements = Info->ReturnObject->Package.Elements; 608245582Sjkim switch (Info->ReturnObject->Package.Count) 609193267Sjkim { 610245582Sjkim case 0: 611250838Sjkim 612245582Sjkim Status = AE_AML_PACKAGE_LIMIT; 613245582Sjkim break; 614193267Sjkim 615245582Sjkim case 1: 616250838Sjkim 617245582Sjkim if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER) 618245582Sjkim { 619245582Sjkim Status = AE_AML_OPERAND_TYPE; 620245582Sjkim break; 621245582Sjkim } 622193267Sjkim 623245582Sjkim /* A valid _Sx_ package with one integer */ 624193267Sjkim 625245582Sjkim *SleepTypeA = (UINT8) Elements[0]->Integer.Value; 626245582Sjkim *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8); 627245582Sjkim break; 628245582Sjkim 629245582Sjkim case 2: 630245582Sjkim default: 631250838Sjkim 632245582Sjkim if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) || 633245582Sjkim (Elements[1]->Common.Type != ACPI_TYPE_INTEGER)) 634245582Sjkim { 635245582Sjkim Status = AE_AML_OPERAND_TYPE; 636245582Sjkim break; 637245582Sjkim } 638245582Sjkim 639245582Sjkim /* A valid _Sx_ package with two integers */ 640245582Sjkim 641245582Sjkim *SleepTypeA = (UINT8) Elements[0]->Integer.Value; 642245582Sjkim *SleepTypeB = (UINT8) Elements[1]->Integer.Value; 643245582Sjkim break; 644193267Sjkim } 645193267Sjkim 646306536SjkimReturnValueCleanup: 647245582Sjkim AcpiUtRemoveReference (Info->ReturnObject); 648245582Sjkim 649306536SjkimWarningCleanup: 650193267Sjkim if (ACPI_FAILURE (Status)) 651193267Sjkim { 652193267Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 653306536Sjkim "While evaluating Sleep State [%s]", 654306536Sjkim Info->RelativePathname)); 655193267Sjkim } 656193267Sjkim 657306536SjkimFinalCleanup: 658193267Sjkim ACPI_FREE (Info); 659193267Sjkim return_ACPI_STATUS (Status); 660193267Sjkim} 661193267Sjkim 662193267SjkimACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 663