xref: /freebsd/sys/contrib/dev/acpica/components/hardware/hwregs.c (revision a159c266a93c3c4f229864954c5f963acd8f60f2)
1*a159c266SJung-uk Kim 
2*a159c266SJung-uk Kim /*******************************************************************************
3*a159c266SJung-uk Kim  *
4*a159c266SJung-uk Kim  * Module Name: hwregs - Read/write access functions for the various ACPI
5*a159c266SJung-uk Kim  *                       control and status registers.
6*a159c266SJung-uk Kim  *
7*a159c266SJung-uk Kim  ******************************************************************************/
8*a159c266SJung-uk Kim 
9*a159c266SJung-uk Kim /*
10*a159c266SJung-uk Kim  * Copyright (C) 2000 - 2012, Intel Corp.
11*a159c266SJung-uk Kim  * All rights reserved.
12*a159c266SJung-uk Kim  *
13*a159c266SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
14*a159c266SJung-uk Kim  * modification, are permitted provided that the following conditions
15*a159c266SJung-uk Kim  * are met:
16*a159c266SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
17*a159c266SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
18*a159c266SJung-uk Kim  *    without modification.
19*a159c266SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
20*a159c266SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
21*a159c266SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
22*a159c266SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
23*a159c266SJung-uk Kim  *    binary redistribution.
24*a159c266SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
25*a159c266SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
26*a159c266SJung-uk Kim  *    from this software without specific prior written permission.
27*a159c266SJung-uk Kim  *
28*a159c266SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
29*a159c266SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
30*a159c266SJung-uk Kim  * Software Foundation.
31*a159c266SJung-uk Kim  *
32*a159c266SJung-uk Kim  * NO WARRANTY
33*a159c266SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
34*a159c266SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
35*a159c266SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
36*a159c266SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
37*a159c266SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38*a159c266SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39*a159c266SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40*a159c266SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41*a159c266SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42*a159c266SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43*a159c266SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
44*a159c266SJung-uk Kim  */
45*a159c266SJung-uk Kim 
46*a159c266SJung-uk Kim #define __HWREGS_C__
47*a159c266SJung-uk Kim 
48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
50*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acevents.h>
51*a159c266SJung-uk Kim 
52*a159c266SJung-uk Kim #define _COMPONENT          ACPI_HARDWARE
53*a159c266SJung-uk Kim         ACPI_MODULE_NAME    ("hwregs")
54*a159c266SJung-uk Kim 
55*a159c266SJung-uk Kim 
56*a159c266SJung-uk Kim #if (!ACPI_REDUCED_HARDWARE)
57*a159c266SJung-uk Kim 
58*a159c266SJung-uk Kim /* Local Prototypes */
59*a159c266SJung-uk Kim 
60*a159c266SJung-uk Kim static ACPI_STATUS
61*a159c266SJung-uk Kim AcpiHwReadMultiple (
62*a159c266SJung-uk Kim     UINT32                  *Value,
63*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterA,
64*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterB);
65*a159c266SJung-uk Kim 
66*a159c266SJung-uk Kim static ACPI_STATUS
67*a159c266SJung-uk Kim AcpiHwWriteMultiple (
68*a159c266SJung-uk Kim     UINT32                  Value,
69*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterA,
70*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterB);
71*a159c266SJung-uk Kim 
72*a159c266SJung-uk Kim #endif /* !ACPI_REDUCED_HARDWARE */
73*a159c266SJung-uk Kim 
74*a159c266SJung-uk Kim /******************************************************************************
75*a159c266SJung-uk Kim  *
76*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwValidateRegister
77*a159c266SJung-uk Kim  *
78*a159c266SJung-uk Kim  * PARAMETERS:  Reg                 - GAS register structure
79*a159c266SJung-uk Kim  *              MaxBitWidth         - Max BitWidth supported (32 or 64)
80*a159c266SJung-uk Kim  *              Address             - Pointer to where the gas->address
81*a159c266SJung-uk Kim  *                                    is returned
82*a159c266SJung-uk Kim  *
83*a159c266SJung-uk Kim  * RETURN:      Status
84*a159c266SJung-uk Kim  *
85*a159c266SJung-uk Kim  * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
86*a159c266SJung-uk Kim  *              pointer, Address, SpaceId, BitWidth, and BitOffset.
87*a159c266SJung-uk Kim  *
88*a159c266SJung-uk Kim  ******************************************************************************/
89*a159c266SJung-uk Kim 
90*a159c266SJung-uk Kim ACPI_STATUS
91*a159c266SJung-uk Kim AcpiHwValidateRegister (
92*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *Reg,
93*a159c266SJung-uk Kim     UINT8                   MaxBitWidth,
94*a159c266SJung-uk Kim     UINT64                  *Address)
95*a159c266SJung-uk Kim {
96*a159c266SJung-uk Kim 
97*a159c266SJung-uk Kim     /* Must have a valid pointer to a GAS structure */
98*a159c266SJung-uk Kim 
99*a159c266SJung-uk Kim     if (!Reg)
100*a159c266SJung-uk Kim     {
101*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
102*a159c266SJung-uk Kim     }
103*a159c266SJung-uk Kim 
104*a159c266SJung-uk Kim     /*
105*a159c266SJung-uk Kim      * Copy the target address. This handles possible alignment issues.
106*a159c266SJung-uk Kim      * Address must not be null. A null address also indicates an optional
107*a159c266SJung-uk Kim      * ACPI register that is not supported, so no error message.
108*a159c266SJung-uk Kim      */
109*a159c266SJung-uk Kim     ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
110*a159c266SJung-uk Kim     if (!(*Address))
111*a159c266SJung-uk Kim     {
112*a159c266SJung-uk Kim         return (AE_BAD_ADDRESS);
113*a159c266SJung-uk Kim     }
114*a159c266SJung-uk Kim 
115*a159c266SJung-uk Kim     /* Validate the SpaceID */
116*a159c266SJung-uk Kim 
117*a159c266SJung-uk Kim     if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
118*a159c266SJung-uk Kim         (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
119*a159c266SJung-uk Kim     {
120*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO,
121*a159c266SJung-uk Kim             "Unsupported address space: 0x%X", Reg->SpaceId));
122*a159c266SJung-uk Kim         return (AE_SUPPORT);
123*a159c266SJung-uk Kim     }
124*a159c266SJung-uk Kim 
125*a159c266SJung-uk Kim     /* Validate the BitWidth */
126*a159c266SJung-uk Kim 
127*a159c266SJung-uk Kim     if ((Reg->BitWidth != 8) &&
128*a159c266SJung-uk Kim         (Reg->BitWidth != 16) &&
129*a159c266SJung-uk Kim         (Reg->BitWidth != 32) &&
130*a159c266SJung-uk Kim         (Reg->BitWidth != MaxBitWidth))
131*a159c266SJung-uk Kim     {
132*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO,
133*a159c266SJung-uk Kim             "Unsupported register bit width: 0x%X", Reg->BitWidth));
134*a159c266SJung-uk Kim         return (AE_SUPPORT);
135*a159c266SJung-uk Kim     }
136*a159c266SJung-uk Kim 
137*a159c266SJung-uk Kim     /* Validate the BitOffset. Just a warning for now. */
138*a159c266SJung-uk Kim 
139*a159c266SJung-uk Kim     if (Reg->BitOffset != 0)
140*a159c266SJung-uk Kim     {
141*a159c266SJung-uk Kim         ACPI_WARNING ((AE_INFO,
142*a159c266SJung-uk Kim             "Unsupported register bit offset: 0x%X", Reg->BitOffset));
143*a159c266SJung-uk Kim     }
144*a159c266SJung-uk Kim 
145*a159c266SJung-uk Kim     return (AE_OK);
146*a159c266SJung-uk Kim }
147*a159c266SJung-uk Kim 
148*a159c266SJung-uk Kim 
149*a159c266SJung-uk Kim /******************************************************************************
150*a159c266SJung-uk Kim  *
151*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwRead
152*a159c266SJung-uk Kim  *
153*a159c266SJung-uk Kim  * PARAMETERS:  Value               - Where the value is returned
154*a159c266SJung-uk Kim  *              Reg                 - GAS register structure
155*a159c266SJung-uk Kim  *
156*a159c266SJung-uk Kim  * RETURN:      Status
157*a159c266SJung-uk Kim  *
158*a159c266SJung-uk Kim  * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
159*a159c266SJung-uk Kim  *              version of AcpiRead, used internally since the overhead of
160*a159c266SJung-uk Kim  *              64-bit values is not needed.
161*a159c266SJung-uk Kim  *
162*a159c266SJung-uk Kim  * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
163*a159c266SJung-uk Kim  *      BitWidth must be exactly 8, 16, or 32.
164*a159c266SJung-uk Kim  *      SpaceID must be SystemMemory or SystemIO.
165*a159c266SJung-uk Kim  *      BitOffset and AccessWidth are currently ignored, as there has
166*a159c266SJung-uk Kim  *          not been a need to implement these.
167*a159c266SJung-uk Kim  *
168*a159c266SJung-uk Kim  ******************************************************************************/
169*a159c266SJung-uk Kim 
170*a159c266SJung-uk Kim ACPI_STATUS
171*a159c266SJung-uk Kim AcpiHwRead (
172*a159c266SJung-uk Kim     UINT32                  *Value,
173*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *Reg)
174*a159c266SJung-uk Kim {
175*a159c266SJung-uk Kim     UINT64                  Address;
176*a159c266SJung-uk Kim     UINT64                  Value64;
177*a159c266SJung-uk Kim     ACPI_STATUS             Status;
178*a159c266SJung-uk Kim 
179*a159c266SJung-uk Kim 
180*a159c266SJung-uk Kim     ACPI_FUNCTION_NAME (HwRead);
181*a159c266SJung-uk Kim 
182*a159c266SJung-uk Kim 
183*a159c266SJung-uk Kim     /* Validate contents of the GAS register */
184*a159c266SJung-uk Kim 
185*a159c266SJung-uk Kim     Status = AcpiHwValidateRegister (Reg, 32, &Address);
186*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
187*a159c266SJung-uk Kim     {
188*a159c266SJung-uk Kim         return (Status);
189*a159c266SJung-uk Kim     }
190*a159c266SJung-uk Kim 
191*a159c266SJung-uk Kim     /* Initialize entire 32-bit return value to zero */
192*a159c266SJung-uk Kim 
193*a159c266SJung-uk Kim     *Value = 0;
194*a159c266SJung-uk Kim 
195*a159c266SJung-uk Kim     /*
196*a159c266SJung-uk Kim      * Two address spaces supported: Memory or IO. PCI_Config is
197*a159c266SJung-uk Kim      * not supported here because the GAS structure is insufficient
198*a159c266SJung-uk Kim      */
199*a159c266SJung-uk Kim     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
200*a159c266SJung-uk Kim     {
201*a159c266SJung-uk Kim         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
202*a159c266SJung-uk Kim                     Address, &Value64, Reg->BitWidth);
203*a159c266SJung-uk Kim 
204*a159c266SJung-uk Kim         *Value = (UINT32) Value64;
205*a159c266SJung-uk Kim     }
206*a159c266SJung-uk Kim     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
207*a159c266SJung-uk Kim     {
208*a159c266SJung-uk Kim         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
209*a159c266SJung-uk Kim                     Address, Value, Reg->BitWidth);
210*a159c266SJung-uk Kim     }
211*a159c266SJung-uk Kim 
212*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
213*a159c266SJung-uk Kim         "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
214*a159c266SJung-uk Kim         *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
215*a159c266SJung-uk Kim         AcpiUtGetRegionName (Reg->SpaceId)));
216*a159c266SJung-uk Kim 
217*a159c266SJung-uk Kim     return (Status);
218*a159c266SJung-uk Kim }
219*a159c266SJung-uk Kim 
220*a159c266SJung-uk Kim 
221*a159c266SJung-uk Kim /******************************************************************************
222*a159c266SJung-uk Kim  *
223*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwWrite
224*a159c266SJung-uk Kim  *
225*a159c266SJung-uk Kim  * PARAMETERS:  Value               - Value to be written
226*a159c266SJung-uk Kim  *              Reg                 - GAS register structure
227*a159c266SJung-uk Kim  *
228*a159c266SJung-uk Kim  * RETURN:      Status
229*a159c266SJung-uk Kim  *
230*a159c266SJung-uk Kim  * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
231*a159c266SJung-uk Kim  *              version of AcpiWrite, used internally since the overhead of
232*a159c266SJung-uk Kim  *              64-bit values is not needed.
233*a159c266SJung-uk Kim  *
234*a159c266SJung-uk Kim  ******************************************************************************/
235*a159c266SJung-uk Kim 
236*a159c266SJung-uk Kim ACPI_STATUS
237*a159c266SJung-uk Kim AcpiHwWrite (
238*a159c266SJung-uk Kim     UINT32                  Value,
239*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *Reg)
240*a159c266SJung-uk Kim {
241*a159c266SJung-uk Kim     UINT64                  Address;
242*a159c266SJung-uk Kim     ACPI_STATUS             Status;
243*a159c266SJung-uk Kim 
244*a159c266SJung-uk Kim 
245*a159c266SJung-uk Kim     ACPI_FUNCTION_NAME (HwWrite);
246*a159c266SJung-uk Kim 
247*a159c266SJung-uk Kim 
248*a159c266SJung-uk Kim     /* Validate contents of the GAS register */
249*a159c266SJung-uk Kim 
250*a159c266SJung-uk Kim     Status = AcpiHwValidateRegister (Reg, 32, &Address);
251*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
252*a159c266SJung-uk Kim     {
253*a159c266SJung-uk Kim         return (Status);
254*a159c266SJung-uk Kim     }
255*a159c266SJung-uk Kim 
256*a159c266SJung-uk Kim     /*
257*a159c266SJung-uk Kim      * Two address spaces supported: Memory or IO. PCI_Config is
258*a159c266SJung-uk Kim      * not supported here because the GAS structure is insufficient
259*a159c266SJung-uk Kim      */
260*a159c266SJung-uk Kim     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
261*a159c266SJung-uk Kim     {
262*a159c266SJung-uk Kim         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
263*a159c266SJung-uk Kim                     Address, (UINT64) Value, Reg->BitWidth);
264*a159c266SJung-uk Kim     }
265*a159c266SJung-uk Kim     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
266*a159c266SJung-uk Kim     {
267*a159c266SJung-uk Kim         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
268*a159c266SJung-uk Kim                     Address, Value, Reg->BitWidth);
269*a159c266SJung-uk Kim     }
270*a159c266SJung-uk Kim 
271*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
272*a159c266SJung-uk Kim         "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
273*a159c266SJung-uk Kim         Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
274*a159c266SJung-uk Kim         AcpiUtGetRegionName (Reg->SpaceId)));
275*a159c266SJung-uk Kim 
276*a159c266SJung-uk Kim     return (Status);
277*a159c266SJung-uk Kim }
278*a159c266SJung-uk Kim 
279*a159c266SJung-uk Kim 
280*a159c266SJung-uk Kim #if (!ACPI_REDUCED_HARDWARE)
281*a159c266SJung-uk Kim /*******************************************************************************
282*a159c266SJung-uk Kim  *
283*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwClearAcpiStatus
284*a159c266SJung-uk Kim  *
285*a159c266SJung-uk Kim  * PARAMETERS:  None
286*a159c266SJung-uk Kim  *
287*a159c266SJung-uk Kim  * RETURN:      Status
288*a159c266SJung-uk Kim  *
289*a159c266SJung-uk Kim  * DESCRIPTION: Clears all fixed and general purpose status bits
290*a159c266SJung-uk Kim  *
291*a159c266SJung-uk Kim  ******************************************************************************/
292*a159c266SJung-uk Kim 
293*a159c266SJung-uk Kim ACPI_STATUS
294*a159c266SJung-uk Kim AcpiHwClearAcpiStatus (
295*a159c266SJung-uk Kim     void)
296*a159c266SJung-uk Kim {
297*a159c266SJung-uk Kim     ACPI_STATUS             Status;
298*a159c266SJung-uk Kim     ACPI_CPU_FLAGS          LockFlags = 0;
299*a159c266SJung-uk Kim 
300*a159c266SJung-uk Kim 
301*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
302*a159c266SJung-uk Kim 
303*a159c266SJung-uk Kim 
304*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
305*a159c266SJung-uk Kim         ACPI_BITMASK_ALL_FIXED_STATUS,
306*a159c266SJung-uk Kim         ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
307*a159c266SJung-uk Kim 
308*a159c266SJung-uk Kim     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
309*a159c266SJung-uk Kim 
310*a159c266SJung-uk Kim     /* Clear the fixed events in PM1 A/B */
311*a159c266SJung-uk Kim 
312*a159c266SJung-uk Kim     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
313*a159c266SJung-uk Kim                 ACPI_BITMASK_ALL_FIXED_STATUS);
314*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
315*a159c266SJung-uk Kim     {
316*a159c266SJung-uk Kim         goto UnlockAndExit;
317*a159c266SJung-uk Kim     }
318*a159c266SJung-uk Kim 
319*a159c266SJung-uk Kim     /* Clear the GPE Bits in all GPE registers in all GPE blocks */
320*a159c266SJung-uk Kim 
321*a159c266SJung-uk Kim     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
322*a159c266SJung-uk Kim 
323*a159c266SJung-uk Kim UnlockAndExit:
324*a159c266SJung-uk Kim     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
325*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
326*a159c266SJung-uk Kim }
327*a159c266SJung-uk Kim 
328*a159c266SJung-uk Kim 
329*a159c266SJung-uk Kim /*******************************************************************************
330*a159c266SJung-uk Kim  *
331*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwGetBitRegisterInfo
332*a159c266SJung-uk Kim  *
333*a159c266SJung-uk Kim  * PARAMETERS:  RegisterId          - Index of ACPI Register to access
334*a159c266SJung-uk Kim  *
335*a159c266SJung-uk Kim  * RETURN:      The bitmask to be used when accessing the register
336*a159c266SJung-uk Kim  *
337*a159c266SJung-uk Kim  * DESCRIPTION: Map RegisterId into a register bitmask.
338*a159c266SJung-uk Kim  *
339*a159c266SJung-uk Kim  ******************************************************************************/
340*a159c266SJung-uk Kim 
341*a159c266SJung-uk Kim ACPI_BIT_REGISTER_INFO *
342*a159c266SJung-uk Kim AcpiHwGetBitRegisterInfo (
343*a159c266SJung-uk Kim     UINT32                  RegisterId)
344*a159c266SJung-uk Kim {
345*a159c266SJung-uk Kim     ACPI_FUNCTION_ENTRY ();
346*a159c266SJung-uk Kim 
347*a159c266SJung-uk Kim 
348*a159c266SJung-uk Kim     if (RegisterId > ACPI_BITREG_MAX)
349*a159c266SJung-uk Kim     {
350*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
351*a159c266SJung-uk Kim         return (NULL);
352*a159c266SJung-uk Kim     }
353*a159c266SJung-uk Kim 
354*a159c266SJung-uk Kim     return (&AcpiGbl_BitRegisterInfo[RegisterId]);
355*a159c266SJung-uk Kim }
356*a159c266SJung-uk Kim 
357*a159c266SJung-uk Kim 
358*a159c266SJung-uk Kim /******************************************************************************
359*a159c266SJung-uk Kim  *
360*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwWritePm1Control
361*a159c266SJung-uk Kim  *
362*a159c266SJung-uk Kim  * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
363*a159c266SJung-uk Kim  *              Pm1bControl         - Value to be written to PM1B control
364*a159c266SJung-uk Kim  *
365*a159c266SJung-uk Kim  * RETURN:      Status
366*a159c266SJung-uk Kim  *
367*a159c266SJung-uk Kim  * DESCRIPTION: Write the PM1 A/B control registers. These registers are
368*a159c266SJung-uk Kim  *              different than than the PM1 A/B status and enable registers
369*a159c266SJung-uk Kim  *              in that different values can be written to the A/B registers.
370*a159c266SJung-uk Kim  *              Most notably, the SLP_TYP bits can be different, as per the
371*a159c266SJung-uk Kim  *              values returned from the _Sx predefined methods.
372*a159c266SJung-uk Kim  *
373*a159c266SJung-uk Kim  ******************************************************************************/
374*a159c266SJung-uk Kim 
375*a159c266SJung-uk Kim ACPI_STATUS
376*a159c266SJung-uk Kim AcpiHwWritePm1Control (
377*a159c266SJung-uk Kim     UINT32                  Pm1aControl,
378*a159c266SJung-uk Kim     UINT32                  Pm1bControl)
379*a159c266SJung-uk Kim {
380*a159c266SJung-uk Kim     ACPI_STATUS             Status;
381*a159c266SJung-uk Kim 
382*a159c266SJung-uk Kim 
383*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (HwWritePm1Control);
384*a159c266SJung-uk Kim 
385*a159c266SJung-uk Kim 
386*a159c266SJung-uk Kim     Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
387*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
388*a159c266SJung-uk Kim     {
389*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
390*a159c266SJung-uk Kim     }
391*a159c266SJung-uk Kim 
392*a159c266SJung-uk Kim     if (AcpiGbl_FADT.XPm1bControlBlock.Address)
393*a159c266SJung-uk Kim     {
394*a159c266SJung-uk Kim         Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
395*a159c266SJung-uk Kim     }
396*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
397*a159c266SJung-uk Kim }
398*a159c266SJung-uk Kim 
399*a159c266SJung-uk Kim 
400*a159c266SJung-uk Kim /******************************************************************************
401*a159c266SJung-uk Kim  *
402*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwRegisterRead
403*a159c266SJung-uk Kim  *
404*a159c266SJung-uk Kim  * PARAMETERS:  RegisterId          - ACPI Register ID
405*a159c266SJung-uk Kim  *              ReturnValue         - Where the register value is returned
406*a159c266SJung-uk Kim  *
407*a159c266SJung-uk Kim  * RETURN:      Status and the value read.
408*a159c266SJung-uk Kim  *
409*a159c266SJung-uk Kim  * DESCRIPTION: Read from the specified ACPI register
410*a159c266SJung-uk Kim  *
411*a159c266SJung-uk Kim  ******************************************************************************/
412*a159c266SJung-uk Kim 
413*a159c266SJung-uk Kim ACPI_STATUS
414*a159c266SJung-uk Kim AcpiHwRegisterRead (
415*a159c266SJung-uk Kim     UINT32                  RegisterId,
416*a159c266SJung-uk Kim     UINT32                  *ReturnValue)
417*a159c266SJung-uk Kim {
418*a159c266SJung-uk Kim     UINT32                  Value = 0;
419*a159c266SJung-uk Kim     ACPI_STATUS             Status;
420*a159c266SJung-uk Kim 
421*a159c266SJung-uk Kim 
422*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (HwRegisterRead);
423*a159c266SJung-uk Kim 
424*a159c266SJung-uk Kim 
425*a159c266SJung-uk Kim     switch (RegisterId)
426*a159c266SJung-uk Kim     {
427*a159c266SJung-uk Kim     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
428*a159c266SJung-uk Kim 
429*a159c266SJung-uk Kim         Status = AcpiHwReadMultiple (&Value,
430*a159c266SJung-uk Kim                     &AcpiGbl_XPm1aStatus,
431*a159c266SJung-uk Kim                     &AcpiGbl_XPm1bStatus);
432*a159c266SJung-uk Kim         break;
433*a159c266SJung-uk Kim 
434*a159c266SJung-uk Kim 
435*a159c266SJung-uk Kim     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
436*a159c266SJung-uk Kim 
437*a159c266SJung-uk Kim         Status = AcpiHwReadMultiple (&Value,
438*a159c266SJung-uk Kim                     &AcpiGbl_XPm1aEnable,
439*a159c266SJung-uk Kim                     &AcpiGbl_XPm1bEnable);
440*a159c266SJung-uk Kim         break;
441*a159c266SJung-uk Kim 
442*a159c266SJung-uk Kim 
443*a159c266SJung-uk Kim     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
444*a159c266SJung-uk Kim 
445*a159c266SJung-uk Kim         Status = AcpiHwReadMultiple (&Value,
446*a159c266SJung-uk Kim                     &AcpiGbl_FADT.XPm1aControlBlock,
447*a159c266SJung-uk Kim                     &AcpiGbl_FADT.XPm1bControlBlock);
448*a159c266SJung-uk Kim 
449*a159c266SJung-uk Kim         /*
450*a159c266SJung-uk Kim          * Zero the write-only bits. From the ACPI specification, "Hardware
451*a159c266SJung-uk Kim          * Write-Only Bits": "Upon reads to registers with write-only bits,
452*a159c266SJung-uk Kim          * software masks out all write-only bits."
453*a159c266SJung-uk Kim          */
454*a159c266SJung-uk Kim         Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
455*a159c266SJung-uk Kim         break;
456*a159c266SJung-uk Kim 
457*a159c266SJung-uk Kim 
458*a159c266SJung-uk Kim     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
459*a159c266SJung-uk Kim 
460*a159c266SJung-uk Kim         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPm2ControlBlock);
461*a159c266SJung-uk Kim         break;
462*a159c266SJung-uk Kim 
463*a159c266SJung-uk Kim 
464*a159c266SJung-uk Kim     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
465*a159c266SJung-uk Kim 
466*a159c266SJung-uk Kim         Status = AcpiHwRead (&Value, &AcpiGbl_FADT.XPmTimerBlock);
467*a159c266SJung-uk Kim         break;
468*a159c266SJung-uk Kim 
469*a159c266SJung-uk Kim 
470*a159c266SJung-uk Kim     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
471*a159c266SJung-uk Kim 
472*a159c266SJung-uk Kim         Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
473*a159c266SJung-uk Kim         break;
474*a159c266SJung-uk Kim 
475*a159c266SJung-uk Kim 
476*a159c266SJung-uk Kim     default:
477*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
478*a159c266SJung-uk Kim             RegisterId));
479*a159c266SJung-uk Kim         Status = AE_BAD_PARAMETER;
480*a159c266SJung-uk Kim         break;
481*a159c266SJung-uk Kim     }
482*a159c266SJung-uk Kim 
483*a159c266SJung-uk Kim     if (ACPI_SUCCESS (Status))
484*a159c266SJung-uk Kim     {
485*a159c266SJung-uk Kim         *ReturnValue = Value;
486*a159c266SJung-uk Kim     }
487*a159c266SJung-uk Kim 
488*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
489*a159c266SJung-uk Kim }
490*a159c266SJung-uk Kim 
491*a159c266SJung-uk Kim 
492*a159c266SJung-uk Kim /******************************************************************************
493*a159c266SJung-uk Kim  *
494*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwRegisterWrite
495*a159c266SJung-uk Kim  *
496*a159c266SJung-uk Kim  * PARAMETERS:  RegisterId          - ACPI Register ID
497*a159c266SJung-uk Kim  *              Value               - The value to write
498*a159c266SJung-uk Kim  *
499*a159c266SJung-uk Kim  * RETURN:      Status
500*a159c266SJung-uk Kim  *
501*a159c266SJung-uk Kim  * DESCRIPTION: Write to the specified ACPI register
502*a159c266SJung-uk Kim  *
503*a159c266SJung-uk Kim  * NOTE: In accordance with the ACPI specification, this function automatically
504*a159c266SJung-uk Kim  * preserves the value of the following bits, meaning that these bits cannot be
505*a159c266SJung-uk Kim  * changed via this interface:
506*a159c266SJung-uk Kim  *
507*a159c266SJung-uk Kim  * PM1_CONTROL[0] = SCI_EN
508*a159c266SJung-uk Kim  * PM1_CONTROL[9]
509*a159c266SJung-uk Kim  * PM1_STATUS[11]
510*a159c266SJung-uk Kim  *
511*a159c266SJung-uk Kim  * ACPI References:
512*a159c266SJung-uk Kim  * 1) Hardware Ignored Bits: When software writes to a register with ignored
513*a159c266SJung-uk Kim  *      bit fields, it preserves the ignored bit fields
514*a159c266SJung-uk Kim  * 2) SCI_EN: OSPM always preserves this bit position
515*a159c266SJung-uk Kim  *
516*a159c266SJung-uk Kim  ******************************************************************************/
517*a159c266SJung-uk Kim 
518*a159c266SJung-uk Kim ACPI_STATUS
519*a159c266SJung-uk Kim AcpiHwRegisterWrite (
520*a159c266SJung-uk Kim     UINT32                  RegisterId,
521*a159c266SJung-uk Kim     UINT32                  Value)
522*a159c266SJung-uk Kim {
523*a159c266SJung-uk Kim     ACPI_STATUS             Status;
524*a159c266SJung-uk Kim     UINT32                  ReadValue;
525*a159c266SJung-uk Kim 
526*a159c266SJung-uk Kim 
527*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (HwRegisterWrite);
528*a159c266SJung-uk Kim 
529*a159c266SJung-uk Kim 
530*a159c266SJung-uk Kim     switch (RegisterId)
531*a159c266SJung-uk Kim     {
532*a159c266SJung-uk Kim     case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
533*a159c266SJung-uk Kim         /*
534*a159c266SJung-uk Kim          * Handle the "ignored" bit in PM1 Status. According to the ACPI
535*a159c266SJung-uk Kim          * specification, ignored bits are to be preserved when writing.
536*a159c266SJung-uk Kim          * Normally, this would mean a read/modify/write sequence. However,
537*a159c266SJung-uk Kim          * preserving a bit in the status register is different. Writing a
538*a159c266SJung-uk Kim          * one clears the status, and writing a zero preserves the status.
539*a159c266SJung-uk Kim          * Therefore, we must always write zero to the ignored bit.
540*a159c266SJung-uk Kim          *
541*a159c266SJung-uk Kim          * This behavior is clarified in the ACPI 4.0 specification.
542*a159c266SJung-uk Kim          */
543*a159c266SJung-uk Kim         Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
544*a159c266SJung-uk Kim 
545*a159c266SJung-uk Kim         Status = AcpiHwWriteMultiple (Value,
546*a159c266SJung-uk Kim                     &AcpiGbl_XPm1aStatus,
547*a159c266SJung-uk Kim                     &AcpiGbl_XPm1bStatus);
548*a159c266SJung-uk Kim         break;
549*a159c266SJung-uk Kim 
550*a159c266SJung-uk Kim 
551*a159c266SJung-uk Kim     case ACPI_REGISTER_PM1_ENABLE:           /* PM1 A/B: 16-bit access each */
552*a159c266SJung-uk Kim 
553*a159c266SJung-uk Kim         Status = AcpiHwWriteMultiple (Value,
554*a159c266SJung-uk Kim                     &AcpiGbl_XPm1aEnable,
555*a159c266SJung-uk Kim                     &AcpiGbl_XPm1bEnable);
556*a159c266SJung-uk Kim         break;
557*a159c266SJung-uk Kim 
558*a159c266SJung-uk Kim 
559*a159c266SJung-uk Kim     case ACPI_REGISTER_PM1_CONTROL:          /* PM1 A/B: 16-bit access each */
560*a159c266SJung-uk Kim 
561*a159c266SJung-uk Kim         /*
562*a159c266SJung-uk Kim          * Perform a read first to preserve certain bits (per ACPI spec)
563*a159c266SJung-uk Kim          * Note: This includes SCI_EN, we never want to change this bit
564*a159c266SJung-uk Kim          */
565*a159c266SJung-uk Kim         Status = AcpiHwReadMultiple (&ReadValue,
566*a159c266SJung-uk Kim                     &AcpiGbl_FADT.XPm1aControlBlock,
567*a159c266SJung-uk Kim                     &AcpiGbl_FADT.XPm1bControlBlock);
568*a159c266SJung-uk Kim         if (ACPI_FAILURE (Status))
569*a159c266SJung-uk Kim         {
570*a159c266SJung-uk Kim             goto Exit;
571*a159c266SJung-uk Kim         }
572*a159c266SJung-uk Kim 
573*a159c266SJung-uk Kim         /* Insert the bits to be preserved */
574*a159c266SJung-uk Kim 
575*a159c266SJung-uk Kim         ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue);
576*a159c266SJung-uk Kim 
577*a159c266SJung-uk Kim         /* Now we can write the data */
578*a159c266SJung-uk Kim 
579*a159c266SJung-uk Kim         Status = AcpiHwWriteMultiple (Value,
580*a159c266SJung-uk Kim                     &AcpiGbl_FADT.XPm1aControlBlock,
581*a159c266SJung-uk Kim                     &AcpiGbl_FADT.XPm1bControlBlock);
582*a159c266SJung-uk Kim         break;
583*a159c266SJung-uk Kim 
584*a159c266SJung-uk Kim 
585*a159c266SJung-uk Kim     case ACPI_REGISTER_PM2_CONTROL:          /* 8-bit access */
586*a159c266SJung-uk Kim 
587*a159c266SJung-uk Kim         /*
588*a159c266SJung-uk Kim          * For control registers, all reserved bits must be preserved,
589*a159c266SJung-uk Kim          * as per the ACPI spec.
590*a159c266SJung-uk Kim          */
591*a159c266SJung-uk Kim         Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
592*a159c266SJung-uk Kim         if (ACPI_FAILURE (Status))
593*a159c266SJung-uk Kim         {
594*a159c266SJung-uk Kim             goto Exit;
595*a159c266SJung-uk Kim         }
596*a159c266SJung-uk Kim 
597*a159c266SJung-uk Kim         /* Insert the bits to be preserved */
598*a159c266SJung-uk Kim 
599*a159c266SJung-uk Kim         ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue);
600*a159c266SJung-uk Kim 
601*a159c266SJung-uk Kim         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
602*a159c266SJung-uk Kim         break;
603*a159c266SJung-uk Kim 
604*a159c266SJung-uk Kim 
605*a159c266SJung-uk Kim     case ACPI_REGISTER_PM_TIMER:             /* 32-bit access */
606*a159c266SJung-uk Kim 
607*a159c266SJung-uk Kim         Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
608*a159c266SJung-uk Kim         break;
609*a159c266SJung-uk Kim 
610*a159c266SJung-uk Kim 
611*a159c266SJung-uk Kim     case ACPI_REGISTER_SMI_COMMAND_BLOCK:    /* 8-bit access */
612*a159c266SJung-uk Kim 
613*a159c266SJung-uk Kim         /* SMI_CMD is currently always in IO space */
614*a159c266SJung-uk Kim 
615*a159c266SJung-uk Kim         Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
616*a159c266SJung-uk Kim         break;
617*a159c266SJung-uk Kim 
618*a159c266SJung-uk Kim 
619*a159c266SJung-uk Kim     default:
620*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
621*a159c266SJung-uk Kim             RegisterId));
622*a159c266SJung-uk Kim         Status = AE_BAD_PARAMETER;
623*a159c266SJung-uk Kim         break;
624*a159c266SJung-uk Kim     }
625*a159c266SJung-uk Kim 
626*a159c266SJung-uk Kim Exit:
627*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
628*a159c266SJung-uk Kim }
629*a159c266SJung-uk Kim 
630*a159c266SJung-uk Kim 
631*a159c266SJung-uk Kim /******************************************************************************
632*a159c266SJung-uk Kim  *
633*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwReadMultiple
634*a159c266SJung-uk Kim  *
635*a159c266SJung-uk Kim  * PARAMETERS:  Value               - Where the register value is returned
636*a159c266SJung-uk Kim  *              RegisterA           - First ACPI register (required)
637*a159c266SJung-uk Kim  *              RegisterB           - Second ACPI register (optional)
638*a159c266SJung-uk Kim  *
639*a159c266SJung-uk Kim  * RETURN:      Status
640*a159c266SJung-uk Kim  *
641*a159c266SJung-uk Kim  * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
642*a159c266SJung-uk Kim  *
643*a159c266SJung-uk Kim  ******************************************************************************/
644*a159c266SJung-uk Kim 
645*a159c266SJung-uk Kim static ACPI_STATUS
646*a159c266SJung-uk Kim AcpiHwReadMultiple (
647*a159c266SJung-uk Kim     UINT32                  *Value,
648*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterA,
649*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterB)
650*a159c266SJung-uk Kim {
651*a159c266SJung-uk Kim     UINT32                  ValueA = 0;
652*a159c266SJung-uk Kim     UINT32                  ValueB = 0;
653*a159c266SJung-uk Kim     ACPI_STATUS             Status;
654*a159c266SJung-uk Kim 
655*a159c266SJung-uk Kim 
656*a159c266SJung-uk Kim     /* The first register is always required */
657*a159c266SJung-uk Kim 
658*a159c266SJung-uk Kim     Status = AcpiHwRead (&ValueA, RegisterA);
659*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
660*a159c266SJung-uk Kim     {
661*a159c266SJung-uk Kim         return (Status);
662*a159c266SJung-uk Kim     }
663*a159c266SJung-uk Kim 
664*a159c266SJung-uk Kim     /* Second register is optional */
665*a159c266SJung-uk Kim 
666*a159c266SJung-uk Kim     if (RegisterB->Address)
667*a159c266SJung-uk Kim     {
668*a159c266SJung-uk Kim         Status = AcpiHwRead (&ValueB, RegisterB);
669*a159c266SJung-uk Kim         if (ACPI_FAILURE (Status))
670*a159c266SJung-uk Kim         {
671*a159c266SJung-uk Kim             return (Status);
672*a159c266SJung-uk Kim         }
673*a159c266SJung-uk Kim     }
674*a159c266SJung-uk Kim 
675*a159c266SJung-uk Kim     /*
676*a159c266SJung-uk Kim      * OR the two return values together. No shifting or masking is necessary,
677*a159c266SJung-uk Kim      * because of how the PM1 registers are defined in the ACPI specification:
678*a159c266SJung-uk Kim      *
679*a159c266SJung-uk Kim      * "Although the bits can be split between the two register blocks (each
680*a159c266SJung-uk Kim      * register block has a unique pointer within the FADT), the bit positions
681*a159c266SJung-uk Kim      * are maintained. The register block with unimplemented bits (that is,
682*a159c266SJung-uk Kim      * those implemented in the other register block) always returns zeros,
683*a159c266SJung-uk Kim      * and writes have no side effects"
684*a159c266SJung-uk Kim      */
685*a159c266SJung-uk Kim     *Value = (ValueA | ValueB);
686*a159c266SJung-uk Kim     return (AE_OK);
687*a159c266SJung-uk Kim }
688*a159c266SJung-uk Kim 
689*a159c266SJung-uk Kim 
690*a159c266SJung-uk Kim /******************************************************************************
691*a159c266SJung-uk Kim  *
692*a159c266SJung-uk Kim  * FUNCTION:    AcpiHwWriteMultiple
693*a159c266SJung-uk Kim  *
694*a159c266SJung-uk Kim  * PARAMETERS:  Value               - The value to write
695*a159c266SJung-uk Kim  *              RegisterA           - First ACPI register (required)
696*a159c266SJung-uk Kim  *              RegisterB           - Second ACPI register (optional)
697*a159c266SJung-uk Kim  *
698*a159c266SJung-uk Kim  * RETURN:      Status
699*a159c266SJung-uk Kim  *
700*a159c266SJung-uk Kim  * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
701*a159c266SJung-uk Kim  *
702*a159c266SJung-uk Kim  ******************************************************************************/
703*a159c266SJung-uk Kim 
704*a159c266SJung-uk Kim static ACPI_STATUS
705*a159c266SJung-uk Kim AcpiHwWriteMultiple (
706*a159c266SJung-uk Kim     UINT32                  Value,
707*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterA,
708*a159c266SJung-uk Kim     ACPI_GENERIC_ADDRESS    *RegisterB)
709*a159c266SJung-uk Kim {
710*a159c266SJung-uk Kim     ACPI_STATUS             Status;
711*a159c266SJung-uk Kim 
712*a159c266SJung-uk Kim 
713*a159c266SJung-uk Kim     /* The first register is always required */
714*a159c266SJung-uk Kim 
715*a159c266SJung-uk Kim     Status = AcpiHwWrite (Value, RegisterA);
716*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
717*a159c266SJung-uk Kim     {
718*a159c266SJung-uk Kim         return (Status);
719*a159c266SJung-uk Kim     }
720*a159c266SJung-uk Kim 
721*a159c266SJung-uk Kim     /*
722*a159c266SJung-uk Kim      * Second register is optional
723*a159c266SJung-uk Kim      *
724*a159c266SJung-uk Kim      * No bit shifting or clearing is necessary, because of how the PM1
725*a159c266SJung-uk Kim      * registers are defined in the ACPI specification:
726*a159c266SJung-uk Kim      *
727*a159c266SJung-uk Kim      * "Although the bits can be split between the two register blocks (each
728*a159c266SJung-uk Kim      * register block has a unique pointer within the FADT), the bit positions
729*a159c266SJung-uk Kim      * are maintained. The register block with unimplemented bits (that is,
730*a159c266SJung-uk Kim      * those implemented in the other register block) always returns zeros,
731*a159c266SJung-uk Kim      * and writes have no side effects"
732*a159c266SJung-uk Kim      */
733*a159c266SJung-uk Kim     if (RegisterB->Address)
734*a159c266SJung-uk Kim     {
735*a159c266SJung-uk Kim         Status = AcpiHwWrite (Value, RegisterB);
736*a159c266SJung-uk Kim     }
737*a159c266SJung-uk Kim 
738*a159c266SJung-uk Kim     return (Status);
739*a159c266SJung-uk Kim }
740*a159c266SJung-uk Kim 
741*a159c266SJung-uk Kim #endif /* !ACPI_REDUCED_HARDWARE */
742