1193267Sjkim/****************************************************************************** 2193267Sjkim * 3193267Sjkim * Module Name: hwxface - Public ACPICA hardware interfaces 4193267Sjkim * 5193267Sjkim *****************************************************************************/ 6193267Sjkim 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, 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 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 47193267Sjkim 48193267Sjkim#define _COMPONENT ACPI_HARDWARE 49193267Sjkim ACPI_MODULE_NAME ("hwxface") 50193267Sjkim 51193267Sjkim 52193267Sjkim/****************************************************************************** 53193267Sjkim * 54193267Sjkim * FUNCTION: AcpiReset 55193267Sjkim * 56193267Sjkim * PARAMETERS: None 57193267Sjkim * 58193267Sjkim * RETURN: Status 59193267Sjkim * 60193267Sjkim * DESCRIPTION: Set reset register in memory or IO space. Note: Does not 61193267Sjkim * support reset register in PCI config space, this must be 62193267Sjkim * handled separately. 63193267Sjkim * 64193267Sjkim ******************************************************************************/ 65193267Sjkim 66193267SjkimACPI_STATUS 67193267SjkimAcpiReset ( 68193267Sjkim void) 69193267Sjkim{ 70193267Sjkim ACPI_GENERIC_ADDRESS *ResetReg; 71193267Sjkim ACPI_STATUS Status; 72193267Sjkim 73193267Sjkim 74193267Sjkim ACPI_FUNCTION_TRACE (AcpiReset); 75193267Sjkim 76193267Sjkim 77193267Sjkim ResetReg = &AcpiGbl_FADT.ResetRegister; 78193267Sjkim 79193267Sjkim /* Check if the reset register is supported */ 80193267Sjkim 81193267Sjkim if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) || 82193267Sjkim !ResetReg->Address) 83193267Sjkim { 84193267Sjkim return_ACPI_STATUS (AE_NOT_EXIST); 85193267Sjkim } 86193267Sjkim 87197104Sjkim if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) 88197104Sjkim { 89197104Sjkim /* 90197104Sjkim * For I/O space, write directly to the OSL. This bypasses the port 91197104Sjkim * validation mechanism, which may block a valid write to the reset 92197104Sjkim * register. 93197104Sjkim */ 94197104Sjkim Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, 95197104Sjkim AcpiGbl_FADT.ResetValue, ResetReg->BitWidth); 96197104Sjkim } 97197104Sjkim else 98197104Sjkim { 99197104Sjkim /* Write the reset value to the reset register */ 100193267Sjkim 101197104Sjkim Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg); 102197104Sjkim } 103197104Sjkim 104193267Sjkim return_ACPI_STATUS (Status); 105193267Sjkim} 106193267Sjkim 107193267SjkimACPI_EXPORT_SYMBOL (AcpiReset) 108193267Sjkim 109193267Sjkim 110193267Sjkim/****************************************************************************** 111193267Sjkim * 112193267Sjkim * FUNCTION: AcpiRead 113193267Sjkim * 114193267Sjkim * PARAMETERS: Value - Where the value is returned 115193267Sjkim * Reg - GAS register structure 116193267Sjkim * 117193267Sjkim * RETURN: Status 118193267Sjkim * 119193267Sjkim * DESCRIPTION: Read from either memory or IO space. 120193267Sjkim * 121197104Sjkim * LIMITATIONS: <These limitations also apply to AcpiWrite> 122197104Sjkim * BitWidth must be exactly 8, 16, 32, or 64. 123197104Sjkim * SpaceID must be SystemMemory or SystemIO. 124197104Sjkim * BitOffset and AccessWidth are currently ignored, as there has 125197104Sjkim * not been a need to implement these. 126197104Sjkim * 127193267Sjkim ******************************************************************************/ 128193267Sjkim 129193267SjkimACPI_STATUS 130193267SjkimAcpiRead ( 131197104Sjkim UINT64 *ReturnValue, 132193267Sjkim ACPI_GENERIC_ADDRESS *Reg) 133193267Sjkim{ 134254745Sjkim UINT32 ValueLo; 135254745Sjkim UINT32 ValueHi; 136193267Sjkim UINT32 Width; 137193267Sjkim UINT64 Address; 138193267Sjkim ACPI_STATUS Status; 139193267Sjkim 140193267Sjkim 141193267Sjkim ACPI_FUNCTION_NAME (AcpiRead); 142193267Sjkim 143193267Sjkim 144197104Sjkim if (!ReturnValue) 145193267Sjkim { 146193267Sjkim return (AE_BAD_PARAMETER); 147193267Sjkim } 148193267Sjkim 149197104Sjkim /* Validate contents of the GAS register. Allow 64-bit transfers */ 150193267Sjkim 151197104Sjkim Status = AcpiHwValidateRegister (Reg, 64, &Address); 152197104Sjkim if (ACPI_FAILURE (Status)) 153193267Sjkim { 154197104Sjkim return (Status); 155193267Sjkim } 156193267Sjkim 157193267Sjkim /* 158254745Sjkim * Two address spaces supported: Memory or I/O. PCI_Config is 159193267Sjkim * not supported here because the GAS structure is insufficient 160193267Sjkim */ 161197104Sjkim if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 162193267Sjkim { 163197104Sjkim Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 164231844Sjkim Address, ReturnValue, Reg->BitWidth); 165197104Sjkim if (ACPI_FAILURE (Status)) 166197104Sjkim { 167197104Sjkim return (Status); 168197104Sjkim } 169197104Sjkim } 170197104Sjkim else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 171197104Sjkim { 172254745Sjkim ValueLo = 0; 173254745Sjkim ValueHi = 0; 174254745Sjkim 175231844Sjkim Width = Reg->BitWidth; 176231844Sjkim if (Width == 64) 177231844Sjkim { 178231844Sjkim Width = 32; /* Break into two 32-bit transfers */ 179231844Sjkim } 180231844Sjkim 181197104Sjkim Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 182254745Sjkim Address, &ValueLo, Width); 183197104Sjkim if (ACPI_FAILURE (Status)) 184197104Sjkim { 185197104Sjkim return (Status); 186197104Sjkim } 187193267Sjkim 188197104Sjkim if (Reg->BitWidth == 64) 189197104Sjkim { 190197104Sjkim /* Read the top 32 bits */ 191193267Sjkim 192197104Sjkim Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 193254745Sjkim (Address + 4), &ValueHi, 32); 194197104Sjkim if (ACPI_FAILURE (Status)) 195197104Sjkim { 196197104Sjkim return (Status); 197197104Sjkim } 198197104Sjkim } 199254745Sjkim 200254745Sjkim /* Set the return value only if status is AE_OK */ 201254745Sjkim 202254745Sjkim *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32)); 203193267Sjkim } 204193267Sjkim 205193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 206197104Sjkim "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", 207197104Sjkim ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, 208197104Sjkim ACPI_FORMAT_UINT64 (Address), 209193267Sjkim AcpiUtGetRegionName (Reg->SpaceId))); 210193267Sjkim 211254745Sjkim return (AE_OK); 212193267Sjkim} 213193267Sjkim 214193267SjkimACPI_EXPORT_SYMBOL (AcpiRead) 215193267Sjkim 216193267Sjkim 217193267Sjkim/****************************************************************************** 218193267Sjkim * 219193267Sjkim * FUNCTION: AcpiWrite 220193267Sjkim * 221197104Sjkim * PARAMETERS: Value - Value to be written 222193267Sjkim * Reg - GAS register structure 223193267Sjkim * 224193267Sjkim * RETURN: Status 225193267Sjkim * 226193267Sjkim * DESCRIPTION: Write to either memory or IO space. 227193267Sjkim * 228193267Sjkim ******************************************************************************/ 229193267Sjkim 230193267SjkimACPI_STATUS 231193267SjkimAcpiWrite ( 232197104Sjkim UINT64 Value, 233193267Sjkim ACPI_GENERIC_ADDRESS *Reg) 234193267Sjkim{ 235193267Sjkim UINT32 Width; 236193267Sjkim UINT64 Address; 237193267Sjkim ACPI_STATUS Status; 238193267Sjkim 239193267Sjkim 240193267Sjkim ACPI_FUNCTION_NAME (AcpiWrite); 241193267Sjkim 242193267Sjkim 243197104Sjkim /* Validate contents of the GAS register. Allow 64-bit transfers */ 244193267Sjkim 245197104Sjkim Status = AcpiHwValidateRegister (Reg, 64, &Address); 246197104Sjkim if (ACPI_FAILURE (Status)) 247193267Sjkim { 248197104Sjkim return (Status); 249193267Sjkim } 250193267Sjkim 251193267Sjkim /* 252197104Sjkim * Two address spaces supported: Memory or IO. PCI_Config is 253197104Sjkim * not supported here because the GAS structure is insufficient 254193267Sjkim */ 255197104Sjkim if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 256193267Sjkim { 257197104Sjkim Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 258231844Sjkim Address, Value, Reg->BitWidth); 259197104Sjkim if (ACPI_FAILURE (Status)) 260197104Sjkim { 261197104Sjkim return (Status); 262197104Sjkim } 263197104Sjkim } 264197104Sjkim else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 265197104Sjkim { 266231844Sjkim Width = Reg->BitWidth; 267231844Sjkim if (Width == 64) 268231844Sjkim { 269231844Sjkim Width = 32; /* Break into two 32-bit transfers */ 270231844Sjkim } 271231844Sjkim 272197104Sjkim Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 273197104Sjkim Address, ACPI_LODWORD (Value), Width); 274197104Sjkim if (ACPI_FAILURE (Status)) 275197104Sjkim { 276197104Sjkim return (Status); 277197104Sjkim } 278193267Sjkim 279197104Sjkim if (Reg->BitWidth == 64) 280197104Sjkim { 281197104Sjkim Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 282197104Sjkim (Address + 4), ACPI_HIDWORD (Value), 32); 283197104Sjkim if (ACPI_FAILURE (Status)) 284197104Sjkim { 285197104Sjkim return (Status); 286197104Sjkim } 287197104Sjkim } 288193267Sjkim } 289193267Sjkim 290193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 291197104Sjkim "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", 292197104Sjkim ACPI_FORMAT_UINT64 (Value), Reg->BitWidth, 293197104Sjkim ACPI_FORMAT_UINT64 (Address), 294193267Sjkim AcpiUtGetRegionName (Reg->SpaceId))); 295193267Sjkim 296193267Sjkim return (Status); 297193267Sjkim} 298193267Sjkim 299193267SjkimACPI_EXPORT_SYMBOL (AcpiWrite) 300193267Sjkim 301193267Sjkim 302231844Sjkim#if (!ACPI_REDUCED_HARDWARE) 303193267Sjkim/******************************************************************************* 304193267Sjkim * 305193267Sjkim * FUNCTION: AcpiReadBitRegister 306193267Sjkim * 307193267Sjkim * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 308193267Sjkim * ReturnValue - Value that was read from the register, 309193267Sjkim * normalized to bit position zero. 310193267Sjkim * 311193267Sjkim * RETURN: Status and the value read from the specified Register. Value 312193267Sjkim * returned is normalized to bit0 (is shifted all the way right) 313193267Sjkim * 314193267Sjkim * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock. 315193267Sjkim * 316193267Sjkim * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 317193267Sjkim * PM2 Control. 318193267Sjkim * 319193267Sjkim * Note: The hardware lock is not required when reading the ACPI bit registers 320193267Sjkim * since almost all of them are single bit and it does not matter that 321193267Sjkim * the parent hardware register can be split across two physical 322193267Sjkim * registers. The only multi-bit field is SLP_TYP in the PM1 control 323193267Sjkim * register, but this field does not cross an 8-bit boundary (nor does 324193267Sjkim * it make much sense to actually read this field.) 325193267Sjkim * 326193267Sjkim ******************************************************************************/ 327193267Sjkim 328193267SjkimACPI_STATUS 329193267SjkimAcpiReadBitRegister ( 330193267Sjkim UINT32 RegisterId, 331193267Sjkim UINT32 *ReturnValue) 332193267Sjkim{ 333193267Sjkim ACPI_BIT_REGISTER_INFO *BitRegInfo; 334193267Sjkim UINT32 RegisterValue; 335193267Sjkim UINT32 Value; 336193267Sjkim ACPI_STATUS Status; 337193267Sjkim 338193267Sjkim 339193267Sjkim ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId); 340193267Sjkim 341193267Sjkim 342193267Sjkim /* Get the info structure corresponding to the requested ACPI Register */ 343193267Sjkim 344193267Sjkim BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 345193267Sjkim if (!BitRegInfo) 346193267Sjkim { 347193267Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 348193267Sjkim } 349193267Sjkim 350193267Sjkim /* Read the entire parent register */ 351193267Sjkim 352193267Sjkim Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 353193267Sjkim &RegisterValue); 354193267Sjkim if (ACPI_FAILURE (Status)) 355193267Sjkim { 356193267Sjkim return_ACPI_STATUS (Status); 357193267Sjkim } 358193267Sjkim 359193267Sjkim /* Normalize the value that was read, mask off other bits */ 360193267Sjkim 361193267Sjkim Value = ((RegisterValue & BitRegInfo->AccessBitMask) 362193267Sjkim >> BitRegInfo->BitPosition); 363193267Sjkim 364193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 365193267Sjkim "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", 366193267Sjkim RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value)); 367193267Sjkim 368193267Sjkim *ReturnValue = Value; 369193267Sjkim return_ACPI_STATUS (AE_OK); 370193267Sjkim} 371193267Sjkim 372193267SjkimACPI_EXPORT_SYMBOL (AcpiReadBitRegister) 373193267Sjkim 374193267Sjkim 375193267Sjkim/******************************************************************************* 376193267Sjkim * 377193267Sjkim * FUNCTION: AcpiWriteBitRegister 378193267Sjkim * 379193267Sjkim * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 380193267Sjkim * Value - Value to write to the register, in bit 381245582Sjkim * position zero. The bit is automatically 382193267Sjkim * shifted to the correct position. 383193267Sjkim * 384193267Sjkim * RETURN: Status 385193267Sjkim * 386193267Sjkim * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock 387193267Sjkim * since most operations require a read/modify/write sequence. 388193267Sjkim * 389193267Sjkim * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 390193267Sjkim * PM2 Control. 391193267Sjkim * 392193267Sjkim * Note that at this level, the fact that there may be actually two 393193267Sjkim * hardware registers (A and B - and B may not exist) is abstracted. 394193267Sjkim * 395193267Sjkim ******************************************************************************/ 396193267Sjkim 397193267SjkimACPI_STATUS 398193267SjkimAcpiWriteBitRegister ( 399193267Sjkim UINT32 RegisterId, 400193267Sjkim UINT32 Value) 401193267Sjkim{ 402193267Sjkim ACPI_BIT_REGISTER_INFO *BitRegInfo; 403193267Sjkim ACPI_CPU_FLAGS LockFlags; 404193267Sjkim UINT32 RegisterValue; 405193267Sjkim ACPI_STATUS Status = AE_OK; 406193267Sjkim 407193267Sjkim 408193267Sjkim ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId); 409193267Sjkim 410193267Sjkim 411193267Sjkim /* Get the info structure corresponding to the requested ACPI Register */ 412193267Sjkim 413193267Sjkim BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 414193267Sjkim if (!BitRegInfo) 415193267Sjkim { 416193267Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 417193267Sjkim } 418193267Sjkim 419193267Sjkim LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 420193267Sjkim 421193267Sjkim /* 422193267Sjkim * At this point, we know that the parent register is one of the 423193267Sjkim * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control 424193267Sjkim */ 425193267Sjkim if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS) 426193267Sjkim { 427193267Sjkim /* 428193267Sjkim * 1) Case for PM1 Enable, PM1 Control, and PM2 Control 429193267Sjkim * 430193267Sjkim * Perform a register read to preserve the bits that we are not 431193267Sjkim * interested in 432193267Sjkim */ 433193267Sjkim Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 434193267Sjkim &RegisterValue); 435193267Sjkim if (ACPI_FAILURE (Status)) 436193267Sjkim { 437193267Sjkim goto UnlockAndExit; 438193267Sjkim } 439193267Sjkim 440193267Sjkim /* 441193267Sjkim * Insert the input bit into the value that was just read 442193267Sjkim * and write the register 443193267Sjkim */ 444193267Sjkim ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 445193267Sjkim BitRegInfo->AccessBitMask, Value); 446193267Sjkim 447193267Sjkim Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister, 448193267Sjkim RegisterValue); 449193267Sjkim } 450193267Sjkim else 451193267Sjkim { 452193267Sjkim /* 453193267Sjkim * 2) Case for PM1 Status 454193267Sjkim * 455193267Sjkim * The Status register is different from the rest. Clear an event 456193267Sjkim * by writing 1, writing 0 has no effect. So, the only relevant 457193267Sjkim * information is the single bit we're interested in, all others 458193267Sjkim * should be written as 0 so they will be left unchanged. 459193267Sjkim */ 460193267Sjkim RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value, 461193267Sjkim BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 462193267Sjkim 463193267Sjkim /* No need to write the register if value is all zeros */ 464193267Sjkim 465193267Sjkim if (RegisterValue) 466193267Sjkim { 467193267Sjkim Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 468193267Sjkim RegisterValue); 469193267Sjkim } 470193267Sjkim } 471193267Sjkim 472193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_IO, 473193267Sjkim "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", 474193267Sjkim RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue)); 475193267Sjkim 476193267Sjkim 477193267SjkimUnlockAndExit: 478193267Sjkim 479193267Sjkim AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 480193267Sjkim return_ACPI_STATUS (Status); 481193267Sjkim} 482193267Sjkim 483193267SjkimACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) 484193267Sjkim 485231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 486193267Sjkim 487231844Sjkim 488193267Sjkim/******************************************************************************* 489193267Sjkim * 490193267Sjkim * FUNCTION: AcpiGetSleepTypeData 491193267Sjkim * 492193267Sjkim * PARAMETERS: SleepState - Numeric sleep state 493193267Sjkim * *SleepTypeA - Where SLP_TYPa is returned 494193267Sjkim * *SleepTypeB - Where SLP_TYPb is returned 495193267Sjkim * 496245582Sjkim * RETURN: Status 497193267Sjkim * 498245582Sjkim * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested 499245582Sjkim * sleep state via the appropriate \_Sx object. 500193267Sjkim * 501245582Sjkim * The sleep state package returned from the corresponding \_Sx_ object 502245582Sjkim * must contain at least one integer. 503245582Sjkim * 504245582Sjkim * March 2005: 505245582Sjkim * Added support for a package that contains two integers. This 506245582Sjkim * goes against the ACPI specification which defines this object as a 507245582Sjkim * package with one encoded DWORD integer. However, existing practice 508245582Sjkim * by many BIOS vendors is to return a package with 2 or more integer 509245582Sjkim * elements, at least one per sleep type (A/B). 510245582Sjkim * 511245582Sjkim * January 2013: 512245582Sjkim * Therefore, we must be prepared to accept a package with either a 513245582Sjkim * single integer or multiple integers. 514245582Sjkim * 515245582Sjkim * The single integer DWORD format is as follows: 516245582Sjkim * BYTE 0 - Value for the PM1A SLP_TYP register 517245582Sjkim * BYTE 1 - Value for the PM1B SLP_TYP register 518245582Sjkim * BYTE 2-3 - Reserved 519245582Sjkim * 520245582Sjkim * The dual integer format is as follows: 521245582Sjkim * Integer 0 - Value for the PM1A SLP_TYP register 522245582Sjkim * Integer 1 - Value for the PM1A SLP_TYP register 523245582Sjkim * 524193267Sjkim ******************************************************************************/ 525193267Sjkim 526193267SjkimACPI_STATUS 527193267SjkimAcpiGetSleepTypeData ( 528193267Sjkim UINT8 SleepState, 529193267Sjkim UINT8 *SleepTypeA, 530193267Sjkim UINT8 *SleepTypeB) 531193267Sjkim{ 532245582Sjkim ACPI_STATUS Status; 533193267Sjkim ACPI_EVALUATE_INFO *Info; 534245582Sjkim ACPI_OPERAND_OBJECT **Elements; 535193267Sjkim 536193267Sjkim 537193267Sjkim ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 538193267Sjkim 539193267Sjkim 540193267Sjkim /* Validate parameters */ 541193267Sjkim 542193267Sjkim if ((SleepState > ACPI_S_STATES_MAX) || 543245582Sjkim !SleepTypeA || !SleepTypeB) 544193267Sjkim { 545193267Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 546193267Sjkim } 547193267Sjkim 548193267Sjkim /* Allocate the evaluation information block */ 549193267Sjkim 550193267Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 551193267Sjkim if (!Info) 552193267Sjkim { 553193267Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 554193267Sjkim } 555193267Sjkim 556245582Sjkim /* 557245582Sjkim * Evaluate the \_Sx namespace object containing the register values 558245582Sjkim * for this state 559245582Sjkim */ 560249663Sjkim Info->RelativePathname = ACPI_CAST_PTR ( 561249663Sjkim char, AcpiGbl_SleepStateNames[SleepState]); 562193267Sjkim Status = AcpiNsEvaluate (Info); 563193267Sjkim if (ACPI_FAILURE (Status)) 564193267Sjkim { 565193267Sjkim goto Cleanup; 566193267Sjkim } 567193267Sjkim 568193267Sjkim /* Must have a return object */ 569193267Sjkim 570193267Sjkim if (!Info->ReturnObject) 571193267Sjkim { 572193267Sjkim ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 573249663Sjkim Info->RelativePathname)); 574245582Sjkim Status = AE_AML_NO_RETURN_VALUE; 575245582Sjkim goto Cleanup; 576193267Sjkim } 577193267Sjkim 578245582Sjkim /* Return object must be of type Package */ 579193267Sjkim 580245582Sjkim if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 581193267Sjkim { 582193267Sjkim ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 583193267Sjkim Status = AE_AML_OPERAND_TYPE; 584245582Sjkim goto Cleanup1; 585193267Sjkim } 586193267Sjkim 587193267Sjkim /* 588245582Sjkim * Any warnings about the package length or the object types have 589245582Sjkim * already been issued by the predefined name module -- there is no 590245582Sjkim * need to repeat them here. 591193267Sjkim */ 592245582Sjkim Elements = Info->ReturnObject->Package.Elements; 593245582Sjkim switch (Info->ReturnObject->Package.Count) 594193267Sjkim { 595245582Sjkim case 0: 596250838Sjkim 597245582Sjkim Status = AE_AML_PACKAGE_LIMIT; 598245582Sjkim break; 599193267Sjkim 600245582Sjkim case 1: 601250838Sjkim 602245582Sjkim if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER) 603245582Sjkim { 604245582Sjkim Status = AE_AML_OPERAND_TYPE; 605245582Sjkim break; 606245582Sjkim } 607193267Sjkim 608245582Sjkim /* A valid _Sx_ package with one integer */ 609193267Sjkim 610245582Sjkim *SleepTypeA = (UINT8) Elements[0]->Integer.Value; 611245582Sjkim *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8); 612245582Sjkim break; 613245582Sjkim 614245582Sjkim case 2: 615245582Sjkim default: 616250838Sjkim 617245582Sjkim if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) || 618245582Sjkim (Elements[1]->Common.Type != ACPI_TYPE_INTEGER)) 619245582Sjkim { 620245582Sjkim Status = AE_AML_OPERAND_TYPE; 621245582Sjkim break; 622245582Sjkim } 623245582Sjkim 624245582Sjkim /* A valid _Sx_ package with two integers */ 625245582Sjkim 626245582Sjkim *SleepTypeA = (UINT8) Elements[0]->Integer.Value; 627245582Sjkim *SleepTypeB = (UINT8) Elements[1]->Integer.Value; 628245582Sjkim break; 629193267Sjkim } 630193267Sjkim 631245582SjkimCleanup1: 632245582Sjkim AcpiUtRemoveReference (Info->ReturnObject); 633245582Sjkim 634245582SjkimCleanup: 635193267Sjkim if (ACPI_FAILURE (Status)) 636193267Sjkim { 637193267Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 638249663Sjkim "While evaluating Sleep State [%s]", Info->RelativePathname)); 639193267Sjkim } 640193267Sjkim 641193267Sjkim ACPI_FREE (Info); 642193267Sjkim return_ACPI_STATUS (Status); 643193267Sjkim} 644193267Sjkim 645193267SjkimACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 646