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