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