hwxface.c revision 241973
1175383Sjhb/****************************************************************************** 2175383Sjhb * 3175383Sjhb * Module Name: hwxface - Public ACPICA hardware interfaces 4175383Sjhb * 5175383Sjhb *****************************************************************************/ 6175383Sjhb 7175383Sjhb/* 8175383Sjhb * Copyright (C) 2000 - 2012, Intel Corp. 9175383Sjhb * All rights reserved. 10175383Sjhb * 11175383Sjhb * Redistribution and use in source and binary forms, with or without 12175383Sjhb * modification, are permitted provided that the following conditions 13175383Sjhb * are met: 14175383Sjhb * 1. Redistributions of source code must retain the above copyright 15175383Sjhb * notice, this list of conditions, and the following disclaimer, 16175383Sjhb * without modification. 17175383Sjhb * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18175383Sjhb * substantially similar to the "NO WARRANTY" disclaimer below 19175383Sjhb * ("Disclaimer") and any redistribution must be conditioned upon 20175383Sjhb * including a substantially similar Disclaimer requirement for further 21175383Sjhb * binary redistribution. 22175383Sjhb * 3. Neither the names of the above-listed copyright holders nor the names 23175383Sjhb * of any contributors may be used to endorse or promote products derived 24175383Sjhb * from this software without specific prior written permission. 25175383Sjhb * 26175383Sjhb * Alternatively, this software may be distributed under the terms of the 27175383Sjhb * GNU General Public License ("GPL") version 2 as published by the Free 28175383Sjhb * Software Foundation. 29175383Sjhb * 30175383Sjhb * NO WARRANTY 31175383Sjhb * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32175383Sjhb * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33175383Sjhb * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34175383Sjhb * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35175383Sjhb * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36175383Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37175383Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38175383Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39289437Sngie * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40175383Sjhb * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41175383Sjhb * POSSIBILITY OF SUCH DAMAGES. 42175383Sjhb */ 43175383Sjhb 44175383Sjhb#include <contrib/dev/acpica/include/acpi.h> 45289437Sngie#include <contrib/dev/acpica/include/accommon.h> 46175383Sjhb#include <contrib/dev/acpica/include/acnamesp.h> 47289437Sngie 48289437Sngie#define _COMPONENT ACPI_HARDWARE 49175383Sjhb ACPI_MODULE_NAME ("hwxface") 50289437Sngie 51289437Sngie 52289437Sngie/****************************************************************************** 53289437Sngie * 54289437Sngie * FUNCTION: AcpiReset 55289437Sngie * 56289437Sngie * PARAMETERS: None 57289437Sngie * 58289437Sngie * RETURN: Status 59289437Sngie * 60289437Sngie * DESCRIPTION: Set reset register in memory or IO space. Note: Does not 61289437Sngie * support reset register in PCI config space, this must be 62289437Sngie * handled separately. 63289437Sngie * 64289437Sngie ******************************************************************************/ 65289437Sngie 66175383SjhbACPI_STATUS 67175383SjhbAcpiReset ( 68175383Sjhb void) 69175383Sjhb{ 70175383Sjhb ACPI_GENERIC_ADDRESS *ResetReg; 71175383Sjhb ACPI_STATUS Status; 72175383Sjhb 73175383Sjhb 74175383Sjhb ACPI_FUNCTION_TRACE (AcpiReset); 75289437Sngie 76289437Sngie 77289437Sngie ResetReg = &AcpiGbl_FADT.ResetRegister; 78289437Sngie 79175383Sjhb /* Check if the reset register is supported */ 80175383Sjhb 81175383Sjhb if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) || 82175383Sjhb !ResetReg->Address) 83175383Sjhb { 84175383Sjhb return_ACPI_STATUS (AE_NOT_EXIST); 85175383Sjhb } 86175383Sjhb 87175383Sjhb if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) 88289437Sngie { 89289437Sngie /* 90289437Sngie * For I/O space, write directly to the OSL. This bypasses the port 91289437Sngie * validation mechanism, which may block a valid write to the reset 92175383Sjhb * register. 93175383Sjhb */ 94175383Sjhb Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, 95175383Sjhb AcpiGbl_FADT.ResetValue, ResetReg->BitWidth); 96175383Sjhb } 97175383Sjhb else 98175383Sjhb { 99175383Sjhb /* Write the reset value to the reset register */ 100175383Sjhb 101175383Sjhb Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg); 102175383Sjhb } 103175383Sjhb 104289437Sngie return_ACPI_STATUS (Status); 105289437Sngie} 106289437Sngie 107175383SjhbACPI_EXPORT_SYMBOL (AcpiReset) 108289437Sngie 109289437Sngie 110289437Sngie/****************************************************************************** 111175383Sjhb * 112289437Sngie * FUNCTION: AcpiRead 113289437Sngie * 114289437Sngie * PARAMETERS: Value - Where the value is returned 115289437Sngie * Reg - GAS register structure 116175383Sjhb * 117175383Sjhb * RETURN: Status 118175383Sjhb * 119289437Sngie * DESCRIPTION: Read from either memory or IO space. 120289437Sngie * 121175383Sjhb * LIMITATIONS: <These limitations also apply to AcpiWrite> 122175383Sjhb * BitWidth must be exactly 8, 16, 32, or 64. 123289437Sngie * SpaceID must be SystemMemory or SystemIO. 124289437Sngie * BitOffset and AccessWidth are currently ignored, as there has 125175383Sjhb * not been a need to implement these. 126175383Sjhb * 127175383Sjhb ******************************************************************************/ 128175383Sjhb 129289437SngieACPI_STATUS 130289437SngieAcpiRead ( 131175383Sjhb UINT64 *ReturnValue, 132175383Sjhb ACPI_GENERIC_ADDRESS *Reg) 133175383Sjhb{ 134175383Sjhb UINT32 Value; 135175383Sjhb UINT32 Width; 136175383Sjhb UINT64 Address; 137175383Sjhb ACPI_STATUS Status; 138175383Sjhb 139175383Sjhb 140289437Sngie ACPI_FUNCTION_NAME (AcpiRead); 141175383Sjhb 142289437Sngie 143175383Sjhb if (!ReturnValue) 144175383Sjhb { 145175383Sjhb return (AE_BAD_PARAMETER); 146175383Sjhb } 147289437Sngie 148175383Sjhb /* Validate contents of the GAS register. Allow 64-bit transfers */ 149289437Sngie 150175383Sjhb Status = AcpiHwValidateRegister (Reg, 64, &Address); 151175383Sjhb if (ACPI_FAILURE (Status)) 152175383Sjhb { 153175383Sjhb return (Status); 154175383Sjhb } 155289437Sngie 156289437Sngie /* Initialize entire 64-bit return value to zero */ 157175383Sjhb 158175383Sjhb *ReturnValue = 0; 159175383Sjhb Value = 0; 160289437Sngie 161289437Sngie /* 162175383Sjhb * Two address spaces supported: Memory or IO. PCI_Config is 163175383Sjhb * not supported here because the GAS structure is insufficient 164175383Sjhb */ 165175383Sjhb if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 166175383Sjhb { 167289437Sngie Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) 168289437Sngie Address, ReturnValue, Reg->BitWidth); 169175383Sjhb if (ACPI_FAILURE (Status)) 170175383Sjhb { 171175383Sjhb return (Status); 172175383Sjhb } 173175383Sjhb } 174175383Sjhb else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 175175383Sjhb { 176289437Sngie Width = Reg->BitWidth; 177175383Sjhb if (Width == 64) 178289437Sngie { 179289437Sngie Width = 32; /* Break into two 32-bit transfers */ 180175383Sjhb } 181175383Sjhb 182175383Sjhb Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 183175383Sjhb Address, &Value, Width); 184289437Sngie if (ACPI_FAILURE (Status)) 185175383Sjhb { 186289437Sngie return (Status); 187175383Sjhb } 188175383Sjhb *ReturnValue = Value; 189175383Sjhb 190175383Sjhb if (Reg->BitWidth == 64) 191289437Sngie { 192175383Sjhb /* Read the top 32 bits */ 193175383Sjhb 194289437Sngie Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) 195175383Sjhb (Address + 4), &Value, 32); 196175383Sjhb if (ACPI_FAILURE (Status)) 197175383Sjhb { 198175383Sjhb return (Status); 199175383Sjhb } 200289437Sngie *ReturnValue |= ((UINT64) Value << 32); 201175383Sjhb } 202175383Sjhb } 203289437Sngie 204289437Sngie ACPI_DEBUG_PRINT ((ACPI_DB_IO, 205175383Sjhb "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", 206175383Sjhb ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth, 207175383Sjhb ACPI_FORMAT_UINT64 (Address), 208175383Sjhb AcpiUtGetRegionName (Reg->SpaceId))); 209289437Sngie 210289437Sngie return (Status); 211289437Sngie} 212175383Sjhb 213289437SngieACPI_EXPORT_SYMBOL (AcpiRead) 214175383Sjhb 215175383Sjhb 216175383Sjhb/****************************************************************************** 217175383Sjhb * 218175383Sjhb * FUNCTION: AcpiWrite 219175383Sjhb * 220175383Sjhb * PARAMETERS: Value - Value to be written 221289437Sngie * Reg - GAS register structure 222175383Sjhb * 223175383Sjhb * RETURN: Status 224289437Sngie * 225175383Sjhb * DESCRIPTION: Write to either memory or IO space. 226175383Sjhb * 227175383Sjhb ******************************************************************************/ 228289437Sngie 229175383SjhbACPI_STATUS 230289437SngieAcpiWrite ( 231175383Sjhb UINT64 Value, 232175383Sjhb ACPI_GENERIC_ADDRESS *Reg) 233175383Sjhb{ 234175383Sjhb UINT32 Width; 235289437Sngie UINT64 Address; 236175383Sjhb ACPI_STATUS Status; 237175383Sjhb 238289437Sngie 239289437Sngie ACPI_FUNCTION_NAME (AcpiWrite); 240175383Sjhb 241175383Sjhb 242175383Sjhb /* Validate contents of the GAS register. Allow 64-bit transfers */ 243289437Sngie 244289437Sngie Status = AcpiHwValidateRegister (Reg, 64, &Address); 245289437Sngie if (ACPI_FAILURE (Status)) 246175383Sjhb { 247289437Sngie return (Status); 248175383Sjhb } 249175383Sjhb 250175383Sjhb /* 251175383Sjhb * Two address spaces supported: Memory or IO. PCI_Config is 252289437Sngie * not supported here because the GAS structure is insufficient 253289437Sngie */ 254175383Sjhb if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) 255175383Sjhb { 256175383Sjhb Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) 257289437Sngie Address, Value, Reg->BitWidth); 258175383Sjhb if (ACPI_FAILURE (Status)) 259175383Sjhb { 260289437Sngie return (Status); 261289437Sngie } 262175383Sjhb } 263175383Sjhb else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ 264175383Sjhb { 265175383Sjhb Width = Reg->BitWidth; 266175383Sjhb if (Width == 64) 267289437Sngie { 268289437Sngie Width = 32; /* Break into two 32-bit transfers */ 269175383Sjhb } 270175383Sjhb 271289437Sngie Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 272289437Sngie Address, ACPI_LODWORD (Value), Width); 273289437Sngie if (ACPI_FAILURE (Status)) 274175383Sjhb { 275175383Sjhb return (Status); 276289437Sngie } 277289437Sngie 278175383Sjhb if (Reg->BitWidth == 64) 279175383Sjhb { 280289437Sngie Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) 281289437Sngie (Address + 4), ACPI_HIDWORD (Value), 32); 282289437Sngie if (ACPI_FAILURE (Status)) 283175383Sjhb { 284175383Sjhb return (Status); 285289437Sngie } 286289437Sngie } 287175383Sjhb } 288175383Sjhb 289175383Sjhb ACPI_DEBUG_PRINT ((ACPI_DB_IO, 290175383Sjhb "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", 291175383Sjhb ACPI_FORMAT_UINT64 (Value), Reg->BitWidth, 292289437Sngie ACPI_FORMAT_UINT64 (Address), 293175383Sjhb AcpiUtGetRegionName (Reg->SpaceId))); 294175383Sjhb 295175383Sjhb return (Status); 296175383Sjhb} 297175383Sjhb 298289437SngieACPI_EXPORT_SYMBOL (AcpiWrite) 299289437Sngie 300175383Sjhb 301175383Sjhb#if (!ACPI_REDUCED_HARDWARE) 302175383Sjhb/******************************************************************************* 303175383Sjhb * 304175383Sjhb * FUNCTION: AcpiReadBitRegister 305289437Sngie * 306289437Sngie * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 307175383Sjhb * ReturnValue - Value that was read from the register, 308175383Sjhb * normalized to bit position zero. 309175383Sjhb * 310175383Sjhb * RETURN: Status and the value read from the specified Register. Value 311175383Sjhb * returned is normalized to bit0 (is shifted all the way right) 312289437Sngie * 313289437Sngie * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock. 314175383Sjhb * 315175383Sjhb * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 316175383Sjhb * PM2 Control. 317175383Sjhb * 318175383Sjhb * Note: The hardware lock is not required when reading the ACPI bit registers 319175383Sjhb * since almost all of them are single bit and it does not matter that 320175383Sjhb * the parent hardware register can be split across two physical 321175383Sjhb * registers. The only multi-bit field is SLP_TYP in the PM1 control 322175383Sjhb * register, but this field does not cross an 8-bit boundary (nor does 323175383Sjhb * it make much sense to actually read this field.) 324289437Sngie * 325289437Sngie ******************************************************************************/ 326175383Sjhb 327175383SjhbACPI_STATUS 328175383SjhbAcpiReadBitRegister ( 329175383Sjhb UINT32 RegisterId, 330175383Sjhb UINT32 *ReturnValue) 331289437Sngie{ 332289437Sngie ACPI_BIT_REGISTER_INFO *BitRegInfo; 333175383Sjhb UINT32 RegisterValue; 334175383Sjhb UINT32 Value; 335175383Sjhb ACPI_STATUS Status; 336289437Sngie 337289437Sngie 338289437Sngie ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId); 339289437Sngie 340175383Sjhb 341175383Sjhb /* Get the info structure corresponding to the requested ACPI Register */ 342289437Sngie 343175383Sjhb BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 344175383Sjhb if (!BitRegInfo) 345289437Sngie { 346175383Sjhb return_ACPI_STATUS (AE_BAD_PARAMETER); 347175383Sjhb } 348289437Sngie 349289437Sngie /* Read the entire parent register */ 350175383Sjhb 351175383Sjhb Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 352175383Sjhb &RegisterValue); 353175383Sjhb if (ACPI_FAILURE (Status)) 354289437Sngie { 355289437Sngie return_ACPI_STATUS (Status); 356175383Sjhb } 357289437Sngie 358175383Sjhb /* Normalize the value that was read, mask off other bits */ 359289437Sngie 360175383Sjhb Value = ((RegisterValue & BitRegInfo->AccessBitMask) 361175383Sjhb >> BitRegInfo->BitPosition); 362175383Sjhb 363289437Sngie ACPI_DEBUG_PRINT ((ACPI_DB_IO, 364175383Sjhb "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", 365175383Sjhb RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value)); 366175383Sjhb 367175383Sjhb *ReturnValue = Value; 368289437Sngie return_ACPI_STATUS (AE_OK); 369175383Sjhb} 370175383Sjhb 371175383SjhbACPI_EXPORT_SYMBOL (AcpiReadBitRegister) 372175383Sjhb 373289437Sngie 374175383Sjhb/******************************************************************************* 375175383Sjhb * 376175383Sjhb * FUNCTION: AcpiWriteBitRegister 377175383Sjhb * 378175383Sjhb * PARAMETERS: RegisterId - ID of ACPI Bit Register to access 379175383Sjhb * Value - Value to write to the register, in bit 380289437Sngie * position zero. The bit is automaticallly 381175383Sjhb * shifted to the correct position. 382289437Sngie * 383175383Sjhb * RETURN: Status 384175383Sjhb * 385175383Sjhb * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock 386289437Sngie * since most operations require a read/modify/write sequence. 387175383Sjhb * 388175383Sjhb * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and 389175383Sjhb * PM2 Control. 390175383Sjhb * 391289437Sngie * Note that at this level, the fact that there may be actually two 392175383Sjhb * hardware registers (A and B - and B may not exist) is abstracted. 393175383Sjhb * 394175383Sjhb ******************************************************************************/ 395175383Sjhb 396289437SngieACPI_STATUS 397289437SngieAcpiWriteBitRegister ( 398175383Sjhb UINT32 RegisterId, 399175383Sjhb UINT32 Value) 400175383Sjhb{ 401175383Sjhb ACPI_BIT_REGISTER_INFO *BitRegInfo; 402289437Sngie ACPI_CPU_FLAGS LockFlags; 403289437Sngie UINT32 RegisterValue; 404175383Sjhb ACPI_STATUS Status = AE_OK; 405175383Sjhb 406175383Sjhb 407175383Sjhb ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId); 408175383Sjhb 409289437Sngie 410289437Sngie /* Get the info structure corresponding to the requested ACPI Register */ 411175383Sjhb 412175383Sjhb BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId); 413175383Sjhb if (!BitRegInfo) 414175383Sjhb { 415175383Sjhb return_ACPI_STATUS (AE_BAD_PARAMETER); 416175383Sjhb } 417175383Sjhb 418175383Sjhb LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); 419175383Sjhb 420175383Sjhb /* 421289437Sngie * At this point, we know that the parent register is one of the 422289437Sngie * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control 423175383Sjhb */ 424175383Sjhb if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS) 425175383Sjhb { 426175383Sjhb /* 427175383Sjhb * 1) Case for PM1 Enable, PM1 Control, and PM2 Control 428175383Sjhb * 429175383Sjhb * Perform a register read to preserve the bits that we are not 430175383Sjhb * interested in 431175383Sjhb */ 432289437Sngie Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister, 433175383Sjhb &RegisterValue); 434175383Sjhb if (ACPI_FAILURE (Status)) 435175383Sjhb { 436289437Sngie goto UnlockAndExit; 437175383Sjhb } 438175383Sjhb 439175383Sjhb /* 440175383Sjhb * Insert the input bit into the value that was just read 441289437Sngie * and write the register 442175383Sjhb */ 443175383Sjhb ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition, 444175383Sjhb BitRegInfo->AccessBitMask, Value); 445175383Sjhb 446289437Sngie Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister, 447175383Sjhb RegisterValue); 448175383Sjhb } 449175383Sjhb else 450175383Sjhb { 451175383Sjhb /* 452175383Sjhb * 2) Case for PM1 Status 453175383Sjhb * 454175383Sjhb * The Status register is different from the rest. Clear an event 455289437Sngie * by writing 1, writing 0 has no effect. So, the only relevant 456175383Sjhb * information is the single bit we're interested in, all others 457175383Sjhb * should be written as 0 so they will be left unchanged. 458175383Sjhb */ 459175383Sjhb RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value, 460175383Sjhb BitRegInfo->BitPosition, BitRegInfo->AccessBitMask); 461175383Sjhb 462175383Sjhb /* No need to write the register if value is all zeros */ 463289437Sngie 464175383Sjhb if (RegisterValue) 465175383Sjhb { 466175383Sjhb Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, 467175383Sjhb RegisterValue); 468175383Sjhb } 469175383Sjhb } 470289437Sngie 471175383Sjhb ACPI_DEBUG_PRINT ((ACPI_DB_IO, 472175383Sjhb "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", 473175383Sjhb RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue)); 474175383Sjhb 475289437Sngie 476175383SjhbUnlockAndExit: 477175383Sjhb 478175383Sjhb AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); 479175383Sjhb return_ACPI_STATUS (Status); 480289437Sngie} 481175383Sjhb 482175383SjhbACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) 483175383Sjhb 484175383Sjhb#endif /* !ACPI_REDUCED_HARDWARE */ 485175383Sjhb 486175383Sjhb 487175383Sjhb/******************************************************************************* 488175383Sjhb * 489289437Sngie * FUNCTION: AcpiGetSleepTypeData 490175383Sjhb * 491175383Sjhb * PARAMETERS: SleepState - Numeric sleep state 492175383Sjhb * *SleepTypeA - Where SLP_TYPa is returned 493175383Sjhb * *SleepTypeB - Where SLP_TYPb is returned 494175383Sjhb * 495289437Sngie * RETURN: Status - ACPI status 496175383Sjhb * 497175383Sjhb * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep 498175383Sjhb * state. 499175383Sjhb * 500175383Sjhb ******************************************************************************/ 501175383Sjhb 502175383SjhbACPI_STATUS 503175383SjhbAcpiGetSleepTypeData ( 504175383Sjhb UINT8 SleepState, 505289437Sngie UINT8 *SleepTypeA, 506175383Sjhb UINT8 *SleepTypeB) 507175383Sjhb{ 508175383Sjhb ACPI_STATUS Status = AE_OK; 509175383Sjhb ACPI_EVALUATE_INFO *Info; 510289437Sngie 511175383Sjhb 512175383Sjhb ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData); 513175383Sjhb 514175383Sjhb 515289437Sngie /* Validate parameters */ 516175383Sjhb 517175383Sjhb if ((SleepState > ACPI_S_STATES_MAX) || 518175383Sjhb !SleepTypeA || 519175383Sjhb !SleepTypeB) 520175383Sjhb { 521175383Sjhb return_ACPI_STATUS (AE_BAD_PARAMETER); 522175383Sjhb } 523175383Sjhb 524175383Sjhb /* Allocate the evaluation information block */ 525175383Sjhb 526289437Sngie Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 527175383Sjhb if (!Info) 528175383Sjhb { 529175383Sjhb return_ACPI_STATUS (AE_NO_MEMORY); 530175383Sjhb } 531175383Sjhb 532175383Sjhb Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]); 533175383Sjhb 534175383Sjhb /* Evaluate the namespace object containing the values for this state */ 535175383Sjhb 536175383Sjhb Status = AcpiNsEvaluate (Info); 537175383Sjhb if (ACPI_FAILURE (Status)) 538175383Sjhb { 539175383Sjhb ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 540175383Sjhb "%s while evaluating SleepState [%s]\n", 541175383Sjhb AcpiFormatException (Status), Info->Pathname)); 542175383Sjhb 543175383Sjhb goto Cleanup; 544175383Sjhb } 545175383Sjhb 546175383Sjhb /* Must have a return object */ 547175383Sjhb 548175383Sjhb if (!Info->ReturnObject) 549175383Sjhb { 550289437Sngie ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", 551175383Sjhb Info->Pathname)); 552175383Sjhb Status = AE_NOT_EXIST; 553175383Sjhb } 554175383Sjhb 555289437Sngie /* It must be of type Package */ 556175383Sjhb 557175383Sjhb else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) 558175383Sjhb { 559175383Sjhb ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package")); 560175383Sjhb Status = AE_AML_OPERAND_TYPE; 561175383Sjhb } 562289437Sngie 563175383Sjhb /* 564175383Sjhb * The package must have at least two elements. NOTE (March 2005): This 565175383Sjhb * goes against the current ACPI spec which defines this object as a 566175383Sjhb * package with one encoded DWORD element. However, existing practice 567289437Sngie * by BIOS vendors seems to be to have 2 or more elements, at least 568175383Sjhb * one per sleep type (A/B). 569175383Sjhb */ 570175383Sjhb else if (Info->ReturnObject->Package.Count < 2) 571175383Sjhb { 572289437Sngie ACPI_ERROR ((AE_INFO, 573175383Sjhb "Sleep State return package does not have at least two elements")); 574175383Sjhb Status = AE_AML_NO_OPERAND; 575175383Sjhb } 576175383Sjhb 577175383Sjhb /* The first two elements must both be of type Integer */ 578175383Sjhb 579175383Sjhb else if (((Info->ReturnObject->Package.Elements[0])->Common.Type 580175383Sjhb != ACPI_TYPE_INTEGER) || 581175383Sjhb ((Info->ReturnObject->Package.Elements[1])->Common.Type 582175383Sjhb != ACPI_TYPE_INTEGER)) 583175383Sjhb { 584175383Sjhb ACPI_ERROR ((AE_INFO, 585175383Sjhb "Sleep State return package elements are not both Integers " 586175383Sjhb "(%s, %s)", 587289437Sngie AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]), 588175383Sjhb AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1]))); 589175383Sjhb Status = AE_AML_OPERAND_TYPE; 590175383Sjhb } 591175383Sjhb else 592175383Sjhb { 593175383Sjhb /* Valid _Sx_ package size, type, and value */ 594175383Sjhb 595289437Sngie *SleepTypeA = (UINT8) 596289437Sngie (Info->ReturnObject->Package.Elements[0])->Integer.Value; 597289437Sngie *SleepTypeB = (UINT8) 598175383Sjhb (Info->ReturnObject->Package.Elements[1])->Integer.Value; 599289437Sngie } 600289437Sngie 601175383Sjhb if (ACPI_FAILURE (Status)) 602289437Sngie { 603289437Sngie ACPI_EXCEPTION ((AE_INFO, Status, 604289437Sngie "While evaluating SleepState [%s], bad Sleep object %p type %s", 605289437Sngie Info->Pathname, Info->ReturnObject, 606289437Sngie AcpiUtGetObjectTypeName (Info->ReturnObject))); 607289437Sngie } 608289437Sngie 609289437Sngie AcpiUtRemoveReference (Info->ReturnObject); 610289437Sngie 611289437SngieCleanup: 612289437Sngie ACPI_FREE (Info); 613289437Sngie return_ACPI_STATUS (Status); 614289437Sngie} 615289437Sngie 616289437SngieACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) 617289437Sngie