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