hwxface.c revision 202771
1188497Sed
2188497Sed/******************************************************************************
3188497Sed *
4188497Sed * Module Name: hwxface - Public ACPICA hardware interfaces
5188497Sed *
6188497Sed *****************************************************************************/
7188497Sed
8188497Sed/******************************************************************************
9188497Sed *
10188497Sed * 1. Copyright Notice
11188497Sed *
12188497Sed * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
13188497Sed * All rights reserved.
14188497Sed *
15188497Sed * 2. License
16188497Sed *
17188497Sed * 2.1. This is your license from Intel Corp. under its intellectual property
18188497Sed * rights.  You may have additional license terms from the party that provided
19188497Sed * you this software, covering your right to use that party's intellectual
20188497Sed * property rights.
21188497Sed *
22188497Sed * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23188497Sed * copy of the source code appearing in this file ("Covered Code") an
24188497Sed * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25188497Sed * base code distributed originally by Intel ("Original Intel Code") to copy,
26188497Sed * make derivatives, distribute, use and display any portion of the Covered
27188497Sed * Code in any form, with the right to sublicense such rights; and
28188497Sed *
29188497Sed * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30188497Sed * license (with the right to sublicense), under only those claims of Intel
31188497Sed * patents that are infringed by the Original Intel Code, to make, use, sell,
32188497Sed * offer to sell, and import the Covered Code and derivative works thereof
33200133Sed * solely to the minimum extent necessary to exercise the above copyright
34188497Sed * license, and in no event shall the patent license extend to any additions
35188497Sed * to or modifications of the Original Intel Code.  No other license or right
36188497Sed * is granted directly or by implication, estoppel or otherwise;
37188497Sed *
38188497Sed * The above copyright and patent license is granted only if the following
39188497Sed * conditions are met:
40188497Sed *
41188497Sed * 3. Conditions
42188497Sed *
43188497Sed * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44188497Sed * Redistribution of source code of any substantial portion of the Covered
45188497Sed * Code or modification with rights to further distribute source must include
46188497Sed * the above Copyright Notice, the above License, this list of Conditions,
47188497Sed * and the following Disclaimer and Export Compliance provision.  In addition,
48188497Sed * Licensee must cause all Covered Code to which Licensee contributes to
49188497Sed * contain a file documenting the changes Licensee made to create that Covered
50188497Sed * Code and the date of any change.  Licensee must include in that file the
51188497Sed * documentation of any changes made by any predecessor Licensee.  Licensee
52188497Sed * must include a prominent statement that the modification is derived,
53188497Sed * directly or indirectly, from Original Intel Code.
54188497Sed *
55188497Sed * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117#include <contrib/dev/acpica/include/acpi.h>
118#include <contrib/dev/acpica/include/accommon.h>
119#include <contrib/dev/acpica/include/acnamesp.h>
120
121#define _COMPONENT          ACPI_HARDWARE
122        ACPI_MODULE_NAME    ("hwxface")
123
124
125/******************************************************************************
126 *
127 * FUNCTION:    AcpiReset
128 *
129 * PARAMETERS:  None
130 *
131 * RETURN:      Status
132 *
133 * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
134 *              support reset register in PCI config space, this must be
135 *              handled separately.
136 *
137 ******************************************************************************/
138
139ACPI_STATUS
140AcpiReset (
141    void)
142{
143    ACPI_GENERIC_ADDRESS    *ResetReg;
144    ACPI_STATUS             Status;
145
146
147    ACPI_FUNCTION_TRACE (AcpiReset);
148
149
150    ResetReg = &AcpiGbl_FADT.ResetRegister;
151
152    /* Check if the reset register is supported */
153
154    if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
155        !ResetReg->Address)
156    {
157        return_ACPI_STATUS (AE_NOT_EXIST);
158    }
159
160    if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
161    {
162        /*
163         * For I/O space, write directly to the OSL. This bypasses the port
164         * validation mechanism, which may block a valid write to the reset
165         * register.
166         */
167        Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
168                    AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
169    }
170    else
171    {
172        /* Write the reset value to the reset register */
173
174        Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
175    }
176
177    return_ACPI_STATUS (Status);
178}
179
180ACPI_EXPORT_SYMBOL (AcpiReset)
181
182
183/******************************************************************************
184 *
185 * FUNCTION:    AcpiRead
186 *
187 * PARAMETERS:  Value               - Where the value is returned
188 *              Reg                 - GAS register structure
189 *
190 * RETURN:      Status
191 *
192 * DESCRIPTION: Read from either memory or IO space.
193 *
194 * LIMITATIONS: <These limitations also apply to AcpiWrite>
195 *      BitWidth must be exactly 8, 16, 32, or 64.
196 *      SpaceID must be SystemMemory or SystemIO.
197 *      BitOffset and AccessWidth are currently ignored, as there has
198 *          not been a need to implement these.
199 *
200 ******************************************************************************/
201
202ACPI_STATUS
203AcpiRead (
204    UINT64                  *ReturnValue,
205    ACPI_GENERIC_ADDRESS    *Reg)
206{
207    UINT32                  Value;
208    UINT32                  Width;
209    UINT64                  Address;
210    ACPI_STATUS             Status;
211
212
213    ACPI_FUNCTION_NAME (AcpiRead);
214
215
216    if (!ReturnValue)
217    {
218        return (AE_BAD_PARAMETER);
219    }
220
221    /* Validate contents of the GAS register. Allow 64-bit transfers */
222
223    Status = AcpiHwValidateRegister (Reg, 64, &Address);
224    if (ACPI_FAILURE (Status))
225    {
226        return (Status);
227    }
228
229    Width = Reg->BitWidth;
230    if (Width == 64)
231    {
232        Width = 32; /* Break into two 32-bit transfers */
233    }
234
235    /* Initialize entire 64-bit return value to zero */
236
237    *ReturnValue = 0;
238    Value = 0;
239
240    /*
241     * Two address spaces supported: Memory or IO. PCI_Config is
242     * not supported here because the GAS structure is insufficient
243     */
244    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
245    {
246        Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
247                    Address, &Value, Width);
248        if (ACPI_FAILURE (Status))
249        {
250            return (Status);
251        }
252        *ReturnValue = Value;
253
254        if (Reg->BitWidth == 64)
255        {
256            /* Read the top 32 bits */
257
258            Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
259                        (Address + 4), &Value, 32);
260            if (ACPI_FAILURE (Status))
261            {
262                return (Status);
263            }
264            *ReturnValue |= ((UINT64) Value << 32);
265        }
266    }
267    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
268    {
269        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
270                    Address, &Value, Width);
271        if (ACPI_FAILURE (Status))
272        {
273            return (Status);
274        }
275        *ReturnValue = Value;
276
277        if (Reg->BitWidth == 64)
278        {
279            /* Read the top 32 bits */
280
281            Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
282                        (Address + 4), &Value, 32);
283            if (ACPI_FAILURE (Status))
284            {
285                return (Status);
286            }
287            *ReturnValue |= ((UINT64) Value << 32);
288        }
289    }
290
291    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
292        "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
293        ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
294        ACPI_FORMAT_UINT64 (Address),
295        AcpiUtGetRegionName (Reg->SpaceId)));
296
297    return (Status);
298}
299
300ACPI_EXPORT_SYMBOL (AcpiRead)
301
302
303/******************************************************************************
304 *
305 * FUNCTION:    AcpiWrite
306 *
307 * PARAMETERS:  Value               - Value to be written
308 *              Reg                 - GAS register structure
309 *
310 * RETURN:      Status
311 *
312 * DESCRIPTION: Write to either memory or IO space.
313 *
314 ******************************************************************************/
315
316ACPI_STATUS
317AcpiWrite (
318    UINT64                  Value,
319    ACPI_GENERIC_ADDRESS    *Reg)
320{
321    UINT32                  Width;
322    UINT64                  Address;
323    ACPI_STATUS             Status;
324
325
326    ACPI_FUNCTION_NAME (AcpiWrite);
327
328
329    /* Validate contents of the GAS register. Allow 64-bit transfers */
330
331    Status = AcpiHwValidateRegister (Reg, 64, &Address);
332    if (ACPI_FAILURE (Status))
333    {
334        return (Status);
335    }
336
337    Width = Reg->BitWidth;
338    if (Width == 64)
339    {
340        Width = 32; /* Break into two 32-bit transfers */
341    }
342
343    /*
344     * Two address spaces supported: Memory or IO. PCI_Config is
345     * not supported here because the GAS structure is insufficient
346     */
347    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
348    {
349        Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
350                    Address, ACPI_LODWORD (Value), Width);
351        if (ACPI_FAILURE (Status))
352        {
353            return (Status);
354        }
355
356        if (Reg->BitWidth == 64)
357        {
358            Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
359                        (Address + 4), ACPI_HIDWORD (Value), 32);
360            if (ACPI_FAILURE (Status))
361            {
362                return (Status);
363            }
364        }
365    }
366    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
367    {
368        Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
369                    Address, ACPI_LODWORD (Value), Width);
370        if (ACPI_FAILURE (Status))
371        {
372            return (Status);
373        }
374
375        if (Reg->BitWidth == 64)
376        {
377            Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
378                        (Address + 4), ACPI_HIDWORD (Value), 32);
379            if (ACPI_FAILURE (Status))
380            {
381                return (Status);
382            }
383        }
384    }
385
386    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
387        "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
388        ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
389        ACPI_FORMAT_UINT64 (Address),
390        AcpiUtGetRegionName (Reg->SpaceId)));
391
392    return (Status);
393}
394
395ACPI_EXPORT_SYMBOL (AcpiWrite)
396
397
398/*******************************************************************************
399 *
400 * FUNCTION:    AcpiReadBitRegister
401 *
402 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
403 *              ReturnValue     - Value that was read from the register,
404 *                                normalized to bit position zero.
405 *
406 * RETURN:      Status and the value read from the specified Register. Value
407 *              returned is normalized to bit0 (is shifted all the way right)
408 *
409 * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
410 *
411 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
412 *              PM2 Control.
413 *
414 * Note: The hardware lock is not required when reading the ACPI bit registers
415 *       since almost all of them are single bit and it does not matter that
416 *       the parent hardware register can be split across two physical
417 *       registers. The only multi-bit field is SLP_TYP in the PM1 control
418 *       register, but this field does not cross an 8-bit boundary (nor does
419 *       it make much sense to actually read this field.)
420 *
421 ******************************************************************************/
422
423ACPI_STATUS
424AcpiReadBitRegister (
425    UINT32                  RegisterId,
426    UINT32                  *ReturnValue)
427{
428    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
429    UINT32                  RegisterValue;
430    UINT32                  Value;
431    ACPI_STATUS             Status;
432
433
434    ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
435
436
437    /* Get the info structure corresponding to the requested ACPI Register */
438
439    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
440    if (!BitRegInfo)
441    {
442        return_ACPI_STATUS (AE_BAD_PARAMETER);
443    }
444
445    /* Read the entire parent register */
446
447    Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
448                &RegisterValue);
449    if (ACPI_FAILURE (Status))
450    {
451        return_ACPI_STATUS (Status);
452    }
453
454    /* Normalize the value that was read, mask off other bits */
455
456    Value = ((RegisterValue & BitRegInfo->AccessBitMask)
457                >> BitRegInfo->BitPosition);
458
459    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
460        "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
461        RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
462
463    *ReturnValue = Value;
464    return_ACPI_STATUS (AE_OK);
465}
466
467ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
468
469
470/*******************************************************************************
471 *
472 * FUNCTION:    AcpiWriteBitRegister
473 *
474 * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
475 *              Value           - Value to write to the register, in bit
476 *                                position zero. The bit is automaticallly
477 *                                shifted to the correct position.
478 *
479 * RETURN:      Status
480 *
481 * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
482 *              since most operations require a read/modify/write sequence.
483 *
484 * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
485 *              PM2 Control.
486 *
487 * Note that at this level, the fact that there may be actually two
488 * hardware registers (A and B - and B may not exist) is abstracted.
489 *
490 ******************************************************************************/
491
492ACPI_STATUS
493AcpiWriteBitRegister (
494    UINT32                  RegisterId,
495    UINT32                  Value)
496{
497    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
498    ACPI_CPU_FLAGS          LockFlags;
499    UINT32                  RegisterValue;
500    ACPI_STATUS             Status = AE_OK;
501
502
503    ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
504
505
506    /* Get the info structure corresponding to the requested ACPI Register */
507
508    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
509    if (!BitRegInfo)
510    {
511        return_ACPI_STATUS (AE_BAD_PARAMETER);
512    }
513
514    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
515
516    /*
517     * At this point, we know that the parent register is one of the
518     * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
519     */
520    if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
521    {
522        /*
523         * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
524         *
525         * Perform a register read to preserve the bits that we are not
526         * interested in
527         */
528        Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
529                    &RegisterValue);
530        if (ACPI_FAILURE (Status))
531        {
532            goto UnlockAndExit;
533        }
534
535        /*
536         * Insert the input bit into the value that was just read
537         * and write the register
538         */
539        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
540            BitRegInfo->AccessBitMask, Value);
541
542        Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
543                    RegisterValue);
544    }
545    else
546    {
547        /*
548         * 2) Case for PM1 Status
549         *
550         * The Status register is different from the rest. Clear an event
551         * by writing 1, writing 0 has no effect. So, the only relevant
552         * information is the single bit we're interested in, all others
553         * should be written as 0 so they will be left unchanged.
554         */
555        RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
556            BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
557
558        /* No need to write the register if value is all zeros */
559
560        if (RegisterValue)
561        {
562            Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
563                        RegisterValue);
564        }
565    }
566
567    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
568        "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
569        RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
570
571
572UnlockAndExit:
573
574    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
575    return_ACPI_STATUS (Status);
576}
577
578ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
579
580
581/*******************************************************************************
582 *
583 * FUNCTION:    AcpiGetSleepTypeData
584 *
585 * PARAMETERS:  SleepState          - Numeric sleep state
586 *              *SleepTypeA         - Where SLP_TYPa is returned
587 *              *SleepTypeB         - Where SLP_TYPb is returned
588 *
589 * RETURN:      Status - ACPI status
590 *
591 * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
592 *              state.
593 *
594 ******************************************************************************/
595
596ACPI_STATUS
597AcpiGetSleepTypeData (
598    UINT8                   SleepState,
599    UINT8                   *SleepTypeA,
600    UINT8                   *SleepTypeB)
601{
602    ACPI_STATUS             Status = AE_OK;
603    ACPI_EVALUATE_INFO      *Info;
604
605
606    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
607
608
609    /* Validate parameters */
610
611    if ((SleepState > ACPI_S_STATES_MAX) ||
612        !SleepTypeA ||
613        !SleepTypeB)
614    {
615        return_ACPI_STATUS (AE_BAD_PARAMETER);
616    }
617
618    /* Allocate the evaluation information block */
619
620    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
621    if (!Info)
622    {
623        return_ACPI_STATUS (AE_NO_MEMORY);
624    }
625
626    Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
627
628    /* Evaluate the namespace object containing the values for this state */
629
630    Status = AcpiNsEvaluate (Info);
631    if (ACPI_FAILURE (Status))
632    {
633        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
634            "%s while evaluating SleepState [%s]\n",
635            AcpiFormatException (Status), Info->Pathname));
636
637        goto Cleanup;
638    }
639
640    /* Must have a return object */
641
642    if (!Info->ReturnObject)
643    {
644        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
645            Info->Pathname));
646        Status = AE_NOT_EXIST;
647    }
648
649    /* It must be of type Package */
650
651    else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
652    {
653        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
654        Status = AE_AML_OPERAND_TYPE;
655    }
656
657    /*
658     * The package must have at least two elements. NOTE (March 2005): This
659     * goes against the current ACPI spec which defines this object as a
660     * package with one encoded DWORD element. However, existing practice
661     * by BIOS vendors seems to be to have 2 or more elements, at least
662     * one per sleep type (A/B).
663     */
664    else if (Info->ReturnObject->Package.Count < 2)
665    {
666        ACPI_ERROR ((AE_INFO,
667            "Sleep State return package does not have at least two elements"));
668        Status = AE_AML_NO_OPERAND;
669    }
670
671    /* The first two elements must both be of type Integer */
672
673    else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
674                != ACPI_TYPE_INTEGER) ||
675             ((Info->ReturnObject->Package.Elements[1])->Common.Type
676                != ACPI_TYPE_INTEGER))
677    {
678        ACPI_ERROR ((AE_INFO,
679            "Sleep State return package elements are not both Integers "
680            "(%s, %s)",
681            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
682            AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
683        Status = AE_AML_OPERAND_TYPE;
684    }
685    else
686    {
687        /* Valid _Sx_ package size, type, and value */
688
689        *SleepTypeA = (UINT8)
690            (Info->ReturnObject->Package.Elements[0])->Integer.Value;
691        *SleepTypeB = (UINT8)
692            (Info->ReturnObject->Package.Elements[1])->Integer.Value;
693    }
694
695    if (ACPI_FAILURE (Status))
696    {
697        ACPI_EXCEPTION ((AE_INFO, Status,
698            "While evaluating SleepState [%s], bad Sleep object %p type %s",
699            Info->Pathname, Info->ReturnObject,
700            AcpiUtGetObjectTypeName (Info->ReturnObject)));
701    }
702
703    AcpiUtRemoveReference (Info->ReturnObject);
704
705Cleanup:
706    ACPI_FREE (Info);
707    return_ACPI_STATUS (Status);
708}
709
710ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
711