1193267Sjkim/******************************************************************************
2193267Sjkim *
3193267Sjkim * Module Name: hwxface - Public ACPICA hardware interfaces
4193267Sjkim *
5193267Sjkim *****************************************************************************/
6193267Sjkim
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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
44281075Sdim#define EXPORT_ACPI_INTERFACES
45281075Sdim
46193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
47193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
48193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
49193267Sjkim
50193267Sjkim#define _COMPONENT          ACPI_HARDWARE
51193267Sjkim        ACPI_MODULE_NAME    ("hwxface")
52193267Sjkim
53193267Sjkim
54193267Sjkim/******************************************************************************
55193267Sjkim *
56193267Sjkim * FUNCTION:    AcpiReset
57193267Sjkim *
58193267Sjkim * PARAMETERS:  None
59193267Sjkim *
60193267Sjkim * RETURN:      Status
61193267Sjkim *
62193267Sjkim * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
63193267Sjkim *              support reset register in PCI config space, this must be
64193267Sjkim *              handled separately.
65193267Sjkim *
66193267Sjkim ******************************************************************************/
67193267Sjkim
68193267SjkimACPI_STATUS
69193267SjkimAcpiReset (
70193267Sjkim    void)
71193267Sjkim{
72193267Sjkim    ACPI_GENERIC_ADDRESS    *ResetReg;
73193267Sjkim    ACPI_STATUS             Status;
74193267Sjkim
75193267Sjkim
76193267Sjkim    ACPI_FUNCTION_TRACE (AcpiReset);
77193267Sjkim
78193267Sjkim
79193267Sjkim    ResetReg = &AcpiGbl_FADT.ResetRegister;
80193267Sjkim
81193267Sjkim    /* Check if the reset register is supported */
82193267Sjkim
83193267Sjkim    if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
84193267Sjkim        !ResetReg->Address)
85193267Sjkim    {
86193267Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
87193267Sjkim    }
88193267Sjkim
89197104Sjkim    if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
90197104Sjkim    {
91197104Sjkim        /*
92197104Sjkim         * For I/O space, write directly to the OSL. This bypasses the port
93197104Sjkim         * validation mechanism, which may block a valid write to the reset
94197104Sjkim         * register.
95281075Sdim         *
96281075Sdim         * NOTE:
97281075Sdim         * The ACPI spec requires the reset register width to be 8, so we
98281075Sdim         * hardcode it here and ignore the FADT value. This maintains
99281075Sdim         * compatibility with other ACPI implementations that have allowed
100281075Sdim         * BIOS code with bad register width values to go unnoticed.
101197104Sjkim         */
102197104Sjkim        Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
103281075Sdim            AcpiGbl_FADT.ResetValue, ACPI_RESET_REGISTER_WIDTH);
104197104Sjkim    }
105197104Sjkim    else
106197104Sjkim    {
107197104Sjkim        /* Write the reset value to the reset register */
108193267Sjkim
109197104Sjkim        Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
110197104Sjkim    }
111197104Sjkim
112193267Sjkim    return_ACPI_STATUS (Status);
113193267Sjkim}
114193267Sjkim
115193267SjkimACPI_EXPORT_SYMBOL (AcpiReset)
116193267Sjkim
117193267Sjkim
118193267Sjkim/******************************************************************************
119193267Sjkim *
120193267Sjkim * FUNCTION:    AcpiRead
121193267Sjkim *
122193267Sjkim * PARAMETERS:  Value               - Where the value is returned
123193267Sjkim *              Reg                 - GAS register structure
124193267Sjkim *
125193267Sjkim * RETURN:      Status
126193267Sjkim *
127193267Sjkim * DESCRIPTION: Read from either memory or IO space.
128193267Sjkim *
129197104Sjkim * LIMITATIONS: <These limitations also apply to AcpiWrite>
130197104Sjkim *      BitWidth must be exactly 8, 16, 32, or 64.
131197104Sjkim *      SpaceID must be SystemMemory or SystemIO.
132197104Sjkim *      BitOffset and AccessWidth are currently ignored, as there has
133197104Sjkim *          not been a need to implement these.
134197104Sjkim *
135193267Sjkim ******************************************************************************/
136193267Sjkim
137193267SjkimACPI_STATUS
138193267SjkimAcpiRead (
139197104Sjkim    UINT64                  *ReturnValue,
140193267Sjkim    ACPI_GENERIC_ADDRESS    *Reg)
141193267Sjkim{
142254745Sjkim    UINT32                  ValueLo;
143254745Sjkim    UINT32                  ValueHi;
144193267Sjkim    UINT32                  Width;
145193267Sjkim    UINT64                  Address;
146193267Sjkim    ACPI_STATUS             Status;
147193267Sjkim
148193267Sjkim
149193267Sjkim    ACPI_FUNCTION_NAME (AcpiRead);
150193267Sjkim
151193267Sjkim
152197104Sjkim    if (!ReturnValue)
153193267Sjkim    {
154193267Sjkim        return (AE_BAD_PARAMETER);
155193267Sjkim    }
156193267Sjkim
157197104Sjkim    /* Validate contents of the GAS register. Allow 64-bit transfers */
158193267Sjkim
159197104Sjkim    Status = AcpiHwValidateRegister (Reg, 64, &Address);
160197104Sjkim    if (ACPI_FAILURE (Status))
161193267Sjkim    {
162197104Sjkim        return (Status);
163193267Sjkim    }
164193267Sjkim
165193267Sjkim    /*
166254745Sjkim     * Two address spaces supported: Memory or I/O. PCI_Config is
167193267Sjkim     * not supported here because the GAS structure is insufficient
168193267Sjkim     */
169197104Sjkim    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
170193267Sjkim    {
171197104Sjkim        Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
172306536Sjkim            Address, ReturnValue, Reg->BitWidth);
173197104Sjkim        if (ACPI_FAILURE (Status))
174197104Sjkim        {
175197104Sjkim            return (Status);
176197104Sjkim        }
177197104Sjkim    }
178197104Sjkim    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
179197104Sjkim    {
180254745Sjkim        ValueLo = 0;
181254745Sjkim        ValueHi = 0;
182254745Sjkim
183231844Sjkim        Width = Reg->BitWidth;
184231844Sjkim        if (Width == 64)
185231844Sjkim        {
186231844Sjkim            Width = 32; /* Break into two 32-bit transfers */
187231844Sjkim        }
188231844Sjkim
189197104Sjkim        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
190306536Sjkim            Address, &ValueLo, Width);
191197104Sjkim        if (ACPI_FAILURE (Status))
192197104Sjkim        {
193197104Sjkim            return (Status);
194197104Sjkim        }
195193267Sjkim
196197104Sjkim        if (Reg->BitWidth == 64)
197197104Sjkim        {
198197104Sjkim            /* Read the top 32 bits */
199193267Sjkim
200197104Sjkim            Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
201306536Sjkim                (Address + 4), &ValueHi, 32);
202197104Sjkim            if (ACPI_FAILURE (Status))
203197104Sjkim            {
204197104Sjkim                return (Status);
205197104Sjkim            }
206197104Sjkim        }
207254745Sjkim
208254745Sjkim        /* Set the return value only if status is AE_OK */
209254745Sjkim
210254745Sjkim        *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32));
211193267Sjkim    }
212193267Sjkim
213193267Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
214197104Sjkim        "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
215197104Sjkim        ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
216197104Sjkim        ACPI_FORMAT_UINT64 (Address),
217193267Sjkim        AcpiUtGetRegionName (Reg->SpaceId)));
218193267Sjkim
219254745Sjkim    return (AE_OK);
220193267Sjkim}
221193267Sjkim
222193267SjkimACPI_EXPORT_SYMBOL (AcpiRead)
223193267Sjkim
224193267Sjkim
225193267Sjkim/******************************************************************************
226193267Sjkim *
227193267Sjkim * FUNCTION:    AcpiWrite
228193267Sjkim *
229197104Sjkim * PARAMETERS:  Value               - Value to be written
230193267Sjkim *              Reg                 - GAS register structure
231193267Sjkim *
232193267Sjkim * RETURN:      Status
233193267Sjkim *
234193267Sjkim * DESCRIPTION: Write to either memory or IO space.
235193267Sjkim *
236193267Sjkim ******************************************************************************/
237193267Sjkim
238193267SjkimACPI_STATUS
239193267SjkimAcpiWrite (
240197104Sjkim    UINT64                  Value,
241193267Sjkim    ACPI_GENERIC_ADDRESS    *Reg)
242193267Sjkim{
243193267Sjkim    UINT32                  Width;
244193267Sjkim    UINT64                  Address;
245193267Sjkim    ACPI_STATUS             Status;
246193267Sjkim
247193267Sjkim
248193267Sjkim    ACPI_FUNCTION_NAME (AcpiWrite);
249193267Sjkim
250193267Sjkim
251197104Sjkim    /* Validate contents of the GAS register. Allow 64-bit transfers */
252193267Sjkim
253197104Sjkim    Status = AcpiHwValidateRegister (Reg, 64, &Address);
254197104Sjkim    if (ACPI_FAILURE (Status))
255193267Sjkim    {
256197104Sjkim        return (Status);
257193267Sjkim    }
258193267Sjkim
259193267Sjkim    /*
260197104Sjkim     * Two address spaces supported: Memory or IO. PCI_Config is
261197104Sjkim     * not supported here because the GAS structure is insufficient
262193267Sjkim     */
263197104Sjkim    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
264193267Sjkim    {
265197104Sjkim        Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
266306536Sjkim            Address, Value, Reg->BitWidth);
267197104Sjkim        if (ACPI_FAILURE (Status))
268197104Sjkim        {
269197104Sjkim            return (Status);
270197104Sjkim        }
271197104Sjkim    }
272197104Sjkim    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
273197104Sjkim    {
274231844Sjkim        Width = Reg->BitWidth;
275231844Sjkim        if (Width == 64)
276231844Sjkim        {
277231844Sjkim            Width = 32; /* Break into two 32-bit transfers */
278231844Sjkim        }
279231844Sjkim
280197104Sjkim        Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
281306536Sjkim            Address, ACPI_LODWORD (Value), Width);
282197104Sjkim        if (ACPI_FAILURE (Status))
283197104Sjkim        {
284197104Sjkim            return (Status);
285197104Sjkim        }
286193267Sjkim
287197104Sjkim        if (Reg->BitWidth == 64)
288197104Sjkim        {
289197104Sjkim            Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
290306536Sjkim                (Address + 4), ACPI_HIDWORD (Value), 32);
291197104Sjkim            if (ACPI_FAILURE (Status))
292197104Sjkim            {
293197104Sjkim                return (Status);
294197104Sjkim            }
295197104Sjkim        }
296193267Sjkim    }
297193267Sjkim
298193267Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
299197104Sjkim        "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
300197104Sjkim        ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
301197104Sjkim        ACPI_FORMAT_UINT64 (Address),
302193267Sjkim        AcpiUtGetRegionName (Reg->SpaceId)));
303193267Sjkim
304193267Sjkim    return (Status);
305193267Sjkim}
306193267Sjkim
307193267SjkimACPI_EXPORT_SYMBOL (AcpiWrite)
308193267Sjkim
309193267Sjkim
310231844Sjkim#if (!ACPI_REDUCED_HARDWARE)
311193267Sjkim/*******************************************************************************
312193267Sjkim *
313193267Sjkim * FUNCTION:    AcpiReadBitRegister
314193267Sjkim *
315193267Sjkim * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
316193267Sjkim *              ReturnValue     - Value that was read from the register,
317193267Sjkim *                                normalized to bit position zero.
318193267Sjkim *
319193267Sjkim * RETURN:      Status and the value read from the specified Register. Value
320193267Sjkim *              returned is normalized to bit0 (is shifted all the way right)
321193267Sjkim *
322193267Sjkim * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
323193267Sjkim *
324193267Sjkim * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
325193267Sjkim *              PM2 Control.
326193267Sjkim *
327193267Sjkim * Note: The hardware lock is not required when reading the ACPI bit registers
328193267Sjkim *       since almost all of them are single bit and it does not matter that
329193267Sjkim *       the parent hardware register can be split across two physical
330193267Sjkim *       registers. The only multi-bit field is SLP_TYP in the PM1 control
331193267Sjkim *       register, but this field does not cross an 8-bit boundary (nor does
332193267Sjkim *       it make much sense to actually read this field.)
333193267Sjkim *
334193267Sjkim ******************************************************************************/
335193267Sjkim
336193267SjkimACPI_STATUS
337193267SjkimAcpiReadBitRegister (
338193267Sjkim    UINT32                  RegisterId,
339193267Sjkim    UINT32                  *ReturnValue)
340193267Sjkim{
341193267Sjkim    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
342193267Sjkim    UINT32                  RegisterValue;
343193267Sjkim    UINT32                  Value;
344193267Sjkim    ACPI_STATUS             Status;
345193267Sjkim
346193267Sjkim
347193267Sjkim    ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
348193267Sjkim
349193267Sjkim
350193267Sjkim    /* Get the info structure corresponding to the requested ACPI Register */
351193267Sjkim
352193267Sjkim    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
353193267Sjkim    if (!BitRegInfo)
354193267Sjkim    {
355193267Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
356193267Sjkim    }
357193267Sjkim
358193267Sjkim    /* Read the entire parent register */
359193267Sjkim
360193267Sjkim    Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
361306536Sjkim        &RegisterValue);
362193267Sjkim    if (ACPI_FAILURE (Status))
363193267Sjkim    {
364193267Sjkim        return_ACPI_STATUS (Status);
365193267Sjkim    }
366193267Sjkim
367193267Sjkim    /* Normalize the value that was read, mask off other bits */
368193267Sjkim
369193267Sjkim    Value = ((RegisterValue & BitRegInfo->AccessBitMask)
370306536Sjkim        >> BitRegInfo->BitPosition);
371193267Sjkim
372193267Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
373193267Sjkim        "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
374193267Sjkim        RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
375193267Sjkim
376193267Sjkim    *ReturnValue = Value;
377193267Sjkim    return_ACPI_STATUS (AE_OK);
378193267Sjkim}
379193267Sjkim
380193267SjkimACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
381193267Sjkim
382193267Sjkim
383193267Sjkim/*******************************************************************************
384193267Sjkim *
385193267Sjkim * FUNCTION:    AcpiWriteBitRegister
386193267Sjkim *
387193267Sjkim * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
388193267Sjkim *              Value           - Value to write to the register, in bit
389245582Sjkim *                                position zero. The bit is automatically
390193267Sjkim *                                shifted to the correct position.
391193267Sjkim *
392193267Sjkim * RETURN:      Status
393193267Sjkim *
394193267Sjkim * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
395193267Sjkim *              since most operations require a read/modify/write sequence.
396193267Sjkim *
397193267Sjkim * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
398193267Sjkim *              PM2 Control.
399193267Sjkim *
400193267Sjkim * Note that at this level, the fact that there may be actually two
401193267Sjkim * hardware registers (A and B - and B may not exist) is abstracted.
402193267Sjkim *
403193267Sjkim ******************************************************************************/
404193267Sjkim
405193267SjkimACPI_STATUS
406193267SjkimAcpiWriteBitRegister (
407193267Sjkim    UINT32                  RegisterId,
408193267Sjkim    UINT32                  Value)
409193267Sjkim{
410193267Sjkim    ACPI_BIT_REGISTER_INFO  *BitRegInfo;
411193267Sjkim    ACPI_CPU_FLAGS          LockFlags;
412193267Sjkim    UINT32                  RegisterValue;
413193267Sjkim    ACPI_STATUS             Status = AE_OK;
414193267Sjkim
415193267Sjkim
416193267Sjkim    ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
417193267Sjkim
418193267Sjkim
419193267Sjkim    /* Get the info structure corresponding to the requested ACPI Register */
420193267Sjkim
421193267Sjkim    BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
422193267Sjkim    if (!BitRegInfo)
423193267Sjkim    {
424193267Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
425193267Sjkim    }
426193267Sjkim
427193267Sjkim    LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
428193267Sjkim
429193267Sjkim    /*
430193267Sjkim     * At this point, we know that the parent register is one of the
431193267Sjkim     * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
432193267Sjkim     */
433193267Sjkim    if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
434193267Sjkim    {
435193267Sjkim        /*
436193267Sjkim         * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
437193267Sjkim         *
438193267Sjkim         * Perform a register read to preserve the bits that we are not
439193267Sjkim         * interested in
440193267Sjkim         */
441193267Sjkim        Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
442306536Sjkim            &RegisterValue);
443193267Sjkim        if (ACPI_FAILURE (Status))
444193267Sjkim        {
445193267Sjkim            goto UnlockAndExit;
446193267Sjkim        }
447193267Sjkim
448193267Sjkim        /*
449193267Sjkim         * Insert the input bit into the value that was just read
450193267Sjkim         * and write the register
451193267Sjkim         */
452193267Sjkim        ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
453193267Sjkim            BitRegInfo->AccessBitMask, Value);
454193267Sjkim
455193267Sjkim        Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
456306536Sjkim            RegisterValue);
457193267Sjkim    }
458193267Sjkim    else
459193267Sjkim    {
460193267Sjkim        /*
461193267Sjkim         * 2) Case for PM1 Status
462193267Sjkim         *
463193267Sjkim         * The Status register is different from the rest. Clear an event
464193267Sjkim         * by writing 1, writing 0 has no effect. So, the only relevant
465193267Sjkim         * information is the single bit we're interested in, all others
466193267Sjkim         * should be written as 0 so they will be left unchanged.
467193267Sjkim         */
468193267Sjkim        RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
469193267Sjkim            BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
470193267Sjkim
471193267Sjkim        /* No need to write the register if value is all zeros */
472193267Sjkim
473193267Sjkim        if (RegisterValue)
474193267Sjkim        {
475193267Sjkim            Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
476306536Sjkim                RegisterValue);
477193267Sjkim        }
478193267Sjkim    }
479193267Sjkim
480193267Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_IO,
481193267Sjkim        "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
482193267Sjkim        RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
483193267Sjkim
484193267Sjkim
485193267SjkimUnlockAndExit:
486193267Sjkim
487193267Sjkim    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
488193267Sjkim    return_ACPI_STATUS (Status);
489193267Sjkim}
490193267Sjkim
491193267SjkimACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
492193267Sjkim
493231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
494193267Sjkim
495231844Sjkim
496193267Sjkim/*******************************************************************************
497193267Sjkim *
498193267Sjkim * FUNCTION:    AcpiGetSleepTypeData
499193267Sjkim *
500193267Sjkim * PARAMETERS:  SleepState          - Numeric sleep state
501193267Sjkim *              *SleepTypeA         - Where SLP_TYPa is returned
502193267Sjkim *              *SleepTypeB         - Where SLP_TYPb is returned
503193267Sjkim *
504245582Sjkim * RETURN:      Status
505193267Sjkim *
506245582Sjkim * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
507245582Sjkim *              sleep state via the appropriate \_Sx object.
508193267Sjkim *
509245582Sjkim *  The sleep state package returned from the corresponding \_Sx_ object
510245582Sjkim *  must contain at least one integer.
511245582Sjkim *
512245582Sjkim *  March 2005:
513245582Sjkim *  Added support for a package that contains two integers. This
514245582Sjkim *  goes against the ACPI specification which defines this object as a
515245582Sjkim *  package with one encoded DWORD integer. However, existing practice
516245582Sjkim *  by many BIOS vendors is to return a package with 2 or more integer
517245582Sjkim *  elements, at least one per sleep type (A/B).
518245582Sjkim *
519245582Sjkim *  January 2013:
520245582Sjkim *  Therefore, we must be prepared to accept a package with either a
521245582Sjkim *  single integer or multiple integers.
522245582Sjkim *
523245582Sjkim *  The single integer DWORD format is as follows:
524245582Sjkim *      BYTE 0 - Value for the PM1A SLP_TYP register
525245582Sjkim *      BYTE 1 - Value for the PM1B SLP_TYP register
526245582Sjkim *      BYTE 2-3 - Reserved
527245582Sjkim *
528245582Sjkim *  The dual integer format is as follows:
529245582Sjkim *      Integer 0 - Value for the PM1A SLP_TYP register
530245582Sjkim *      Integer 1 - Value for the PM1A SLP_TYP register
531245582Sjkim *
532193267Sjkim ******************************************************************************/
533193267Sjkim
534193267SjkimACPI_STATUS
535193267SjkimAcpiGetSleepTypeData (
536193267Sjkim    UINT8                   SleepState,
537193267Sjkim    UINT8                   *SleepTypeA,
538193267Sjkim    UINT8                   *SleepTypeB)
539193267Sjkim{
540245582Sjkim    ACPI_STATUS             Status;
541193267Sjkim    ACPI_EVALUATE_INFO      *Info;
542245582Sjkim    ACPI_OPERAND_OBJECT     **Elements;
543193267Sjkim
544193267Sjkim
545193267Sjkim    ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
546193267Sjkim
547193267Sjkim
548193267Sjkim    /* Validate parameters */
549193267Sjkim
550193267Sjkim    if ((SleepState > ACPI_S_STATES_MAX) ||
551245582Sjkim        !SleepTypeA || !SleepTypeB)
552193267Sjkim    {
553193267Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
554193267Sjkim    }
555193267Sjkim
556193267Sjkim    /* Allocate the evaluation information block */
557193267Sjkim
558193267Sjkim    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
559193267Sjkim    if (!Info)
560193267Sjkim    {
561193267Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
562193267Sjkim    }
563193267Sjkim
564245582Sjkim    /*
565245582Sjkim     * Evaluate the \_Sx namespace object containing the register values
566245582Sjkim     * for this state
567245582Sjkim     */
568306536Sjkim    Info->RelativePathname = AcpiGbl_SleepStateNames[SleepState];
569306536Sjkim
570193267Sjkim    Status = AcpiNsEvaluate (Info);
571193267Sjkim    if (ACPI_FAILURE (Status))
572193267Sjkim    {
573306536Sjkim        if (Status == AE_NOT_FOUND)
574306536Sjkim        {
575306536Sjkim            /* The _Sx states are optional, ignore NOT_FOUND */
576306536Sjkim
577306536Sjkim            goto FinalCleanup;
578306536Sjkim        }
579306536Sjkim
580306536Sjkim        goto WarningCleanup;
581193267Sjkim    }
582193267Sjkim
583193267Sjkim    /* Must have a return object */
584193267Sjkim
585193267Sjkim    if (!Info->ReturnObject)
586193267Sjkim    {
587193267Sjkim        ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
588249663Sjkim            Info->RelativePathname));
589245582Sjkim        Status = AE_AML_NO_RETURN_VALUE;
590306536Sjkim        goto WarningCleanup;
591193267Sjkim    }
592193267Sjkim
593245582Sjkim    /* Return object must be of type Package */
594193267Sjkim
595245582Sjkim    if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
596193267Sjkim    {
597193267Sjkim        ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
598193267Sjkim        Status = AE_AML_OPERAND_TYPE;
599306536Sjkim        goto ReturnValueCleanup;
600193267Sjkim    }
601193267Sjkim
602193267Sjkim    /*
603245582Sjkim     * Any warnings about the package length or the object types have
604245582Sjkim     * already been issued by the predefined name module -- there is no
605245582Sjkim     * need to repeat them here.
606193267Sjkim     */
607245582Sjkim    Elements = Info->ReturnObject->Package.Elements;
608245582Sjkim    switch (Info->ReturnObject->Package.Count)
609193267Sjkim    {
610245582Sjkim    case 0:
611250838Sjkim
612245582Sjkim        Status = AE_AML_PACKAGE_LIMIT;
613245582Sjkim        break;
614193267Sjkim
615245582Sjkim    case 1:
616250838Sjkim
617245582Sjkim        if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
618245582Sjkim        {
619245582Sjkim            Status = AE_AML_OPERAND_TYPE;
620245582Sjkim            break;
621245582Sjkim        }
622193267Sjkim
623245582Sjkim        /* A valid _Sx_ package with one integer */
624193267Sjkim
625245582Sjkim        *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
626245582Sjkim        *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
627245582Sjkim        break;
628245582Sjkim
629245582Sjkim    case 2:
630245582Sjkim    default:
631250838Sjkim
632245582Sjkim        if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
633245582Sjkim            (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
634245582Sjkim        {
635245582Sjkim            Status = AE_AML_OPERAND_TYPE;
636245582Sjkim            break;
637245582Sjkim        }
638245582Sjkim
639245582Sjkim        /* A valid _Sx_ package with two integers */
640245582Sjkim
641245582Sjkim        *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
642245582Sjkim        *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
643245582Sjkim        break;
644193267Sjkim    }
645193267Sjkim
646306536SjkimReturnValueCleanup:
647245582Sjkim    AcpiUtRemoveReference (Info->ReturnObject);
648245582Sjkim
649306536SjkimWarningCleanup:
650193267Sjkim    if (ACPI_FAILURE (Status))
651193267Sjkim    {
652193267Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
653306536Sjkim            "While evaluating Sleep State [%s]",
654306536Sjkim            Info->RelativePathname));
655193267Sjkim    }
656193267Sjkim
657306536SjkimFinalCleanup:
658193267Sjkim    ACPI_FREE (Info);
659193267Sjkim    return_ACPI_STATUS (Status);
660193267Sjkim}
661193267Sjkim
662193267SjkimACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)
663