Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
 
2
 *
3
 * Module Name: hwregs - Read/write access functions for the various ACPI
4
 *                       control and status registers.
5
 *
6
 ******************************************************************************/
7
8
 
9
 *
10
 * 1. Copyright Notice
11
 *
12
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
2216 Serge 13
 * All rights reserved.
1498 serge 14
 *
15
 * 2. License
16
 *
17
 * 2.1. This is your license from Intel Corp. under its intellectual property
18
 * rights.  You may have additional license terms from the party that provided
19
 * you this software, covering your right to use that party's intellectual
20
 * property rights.
21
 *
22
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23
 * copy of the source code appearing in this file ("Covered Code") an
24
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25
 * base code distributed originally by Intel ("Original Intel Code") to copy,
26
 * make derivatives, distribute, use and display any portion of the Covered
27
 * Code in any form, with the right to sublicense such rights; and
28
 *
29
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30
 * license (with the right to sublicense), under only those claims of Intel
31
 * patents that are infringed by the Original Intel Code, to make, use, sell,
32
 * offer to sell, and import the Covered Code and derivative works thereof
33
 * solely to the minimum extent necessary to exercise the above copyright
34
 * license, and in no event shall the patent license extend to any additions
35
 * to or modifications of the Original Intel Code.  No other license or right
36
 * is granted directly or by implication, estoppel or otherwise;
37
 *
38
 * The above copyright and patent license is granted only if the following
39
 * conditions are met:
40
 *
41
 * 3. Conditions
42
 *
43
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44
 * Redistribution of source code of any substantial portion of the Covered
45
 * Code or modification with rights to further distribute source must include
46
 * the above Copyright Notice, the above License, this list of Conditions,
47
 * and the following Disclaimer and Export Compliance provision.  In addition,
48
 * Licensee must cause all Covered Code to which Licensee contributes to
49
 * contain a file documenting the changes Licensee made to create that Covered
50
 * Code and the date of any change.  Licensee must include in that file the
51
 * documentation of any changes made by any predecessor Licensee.  Licensee
52
 * must include a prominent statement that the modification is derived,
53
 * directly or indirectly, from Original Intel Code.
54
 *
55
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56
 * Redistribution of source code of any substantial portion of the Covered
57
 * Code or modification without rights to further distribute source must
58
 * include the following Disclaimer and Export Compliance provision in the
59
 * documentation and/or other materials provided with distribution.  In
60
 * addition, Licensee may not authorize further sublicense of source of any
61
 * portion of the Covered Code, and must include terms to the effect that the
62
 * license from Licensee to its licensee is limited to the intellectual
63
 * property embodied in the software Licensee provides to its licensee, and
64
 * not to intellectual property embodied in modifications its licensee may
65
 * make.
66
 *
67
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68
 * substantial portion of the Covered Code or modification must reproduce the
69
 * above Copyright Notice, and the following Disclaimer and Export Compliance
70
 * provision in the documentation and/or other materials provided with the
71
 * distribution.
72
 *
73
 * 3.4. Intel retains all right, title, and interest in and to the Original
74
 * Intel Code.
75
 *
76
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77
 * Intel shall be used in advertising or otherwise to promote the sale, use or
78
 * other dealings in products derived from or relating to the Covered Code
79
 * without prior written authorization from Intel.
80
 *
81
 * 4. Disclaimer and Export Compliance
82
 *
83
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89
 * PARTICULAR PURPOSE.
90
 *
91
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98
 * LIMITED REMEDY.
99
 *
100
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101
 * software or system incorporating such software without first obtaining any
102
 * required license or other approval from the U. S. Department of Commerce or
103
 * any other agency or department of the United States Government.  In the
104
 * event Licensee exports any such software from the United States or
105
 * re-exports any such software from a foreign destination, Licensee shall
106
 * ensure that the distribution and export/re-export of the software is in
107
 * compliance with all laws, regulations, orders, or other restrictions of the
108
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109
 * any of its subsidiaries will export/re-export any technical data, process,
110
 * software, or service, directly or indirectly, to any country for which the
111
 * United States government or any agency thereof requires an export license,
112
 * other governmental approval, or letter of assurance, without first obtaining
113
 * such license, approval or letter.
114
 *
115
 *****************************************************************************/
116
117
 
118
119
 
120
#include "accommon.h"
121
#include "acevents.h"
122
123
 
124
        ACPI_MODULE_NAME    ("hwregs")
125
126
 
127
 
128
129
 
130
AcpiHwReadMultiple (
131
    UINT32                  *Value,
132
    ACPI_GENERIC_ADDRESS    *RegisterA,
133
    ACPI_GENERIC_ADDRESS    *RegisterB);
134
135
 
136
AcpiHwWriteMultiple (
137
    UINT32                  Value,
138
    ACPI_GENERIC_ADDRESS    *RegisterA,
139
    ACPI_GENERIC_ADDRESS    *RegisterB);
140
141
 
142
 
143
 *
144
 * FUNCTION:    AcpiHwValidateRegister
145
 *
146
 * PARAMETERS:  Reg                 - GAS register structure
147
 *              MaxBitWidth         - Max BitWidth supported (32 or 64)
148
 *              Address             - Pointer to where the gas->address
149
 *                                    is returned
150
 *
151
 * RETURN:      Status
152
 *
153
 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
154
 *              pointer, Address, SpaceId, BitWidth, and BitOffset.
155
 *
156
 ******************************************************************************/
157
158
 
159
AcpiHwValidateRegister (
160
    ACPI_GENERIC_ADDRESS    *Reg,
161
    UINT8                   MaxBitWidth,
162
    UINT64                  *Address)
163
{
164
165
 
166
167
 
168
    {
169
        return (AE_BAD_PARAMETER);
170
    }
171
172
 
173
     * Copy the target address. This handles possible alignment issues.
174
     * Address must not be null. A null address also indicates an optional
175
     * ACPI register that is not supported, so no error message.
176
     */
177
    ACPI_MOVE_64_TO_64 (Address, &Reg->Address);
178
    if (!(*Address))
179
    {
180
        return (AE_BAD_ADDRESS);
181
    }
182
183
 
184
185
 
186
        (Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
187
    {
188
        ACPI_ERROR ((AE_INFO,
189
            "Unsupported address space: 0x%X", Reg->SpaceId));
190
        return (AE_SUPPORT);
191
    }
192
193
 
194
195
 
196
        (Reg->BitWidth != 16) &&
197
        (Reg->BitWidth != 32) &&
198
        (Reg->BitWidth != MaxBitWidth))
199
    {
200
        ACPI_ERROR ((AE_INFO,
201
            "Unsupported register bit width: 0x%X", Reg->BitWidth));
202
        return (AE_SUPPORT);
203
    }
204
205
 
206
207
 
208
    {
209
        ACPI_WARNING ((AE_INFO,
210
            "Unsupported register bit offset: 0x%X", Reg->BitOffset));
211
    }
212
213
 
214
}
215
216
 
217
 
218
 *
219
 * FUNCTION:    AcpiHwRead
220
 *
221
 * PARAMETERS:  Value               - Where the value is returned
222
 *              Reg                 - GAS register structure
223
 *
224
 * RETURN:      Status
225
 *
226
 * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
227
 *              version of AcpiRead, used internally since the overhead of
228
 *              64-bit values is not needed.
229
 *
230
 * LIMITATIONS: 
231
 *      BitWidth must be exactly 8, 16, or 32.
232
 *      SpaceID must be SystemMemory or SystemIO.
233
 *      BitOffset and AccessWidth are currently ignored, as there has
234
 *          not been a need to implement these.
235
 *
236
 ******************************************************************************/
237
238
 
239
AcpiHwRead (
240
    UINT32                  *Value,
241
    ACPI_GENERIC_ADDRESS    *Reg)
242
{
243
    UINT64                  Address;
244
    ACPI_STATUS             Status;
245
246
 
247
 
248
249
 
250
 
251
252
 
253
    if (ACPI_FAILURE (Status))
254
    {
255
        return (Status);
256
    }
257
258
 
259
260
 
261
262
 
263
     * Two address spaces supported: Memory or IO. PCI_Config is
264
     * not supported here because the GAS structure is insufficient
265
     */
266
    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
267
    {
268
        Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
269
                    Address, Value, Reg->BitWidth);
270
    }
271
    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
272
    {
273
        Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
274
                    Address, Value, Reg->BitWidth);
275
    }
276
277
 
278
        "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
279
        *Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
280
        AcpiUtGetRegionName (Reg->SpaceId)));
281
282
 
283
}
284
285
 
286
 
287
 *
288
 * FUNCTION:    AcpiHwWrite
289
 *
290
 * PARAMETERS:  Value               - Value to be written
291
 *              Reg                 - GAS register structure
292
 *
293
 * RETURN:      Status
294
 *
295
 * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
296
 *              version of AcpiWrite, used internally since the overhead of
297
 *              64-bit values is not needed.
298
 *
299
 ******************************************************************************/
300
301
 
302
AcpiHwWrite (
303
    UINT32                  Value,
304
    ACPI_GENERIC_ADDRESS    *Reg)
305
{
306
    UINT64                  Address;
307
    ACPI_STATUS             Status;
308
309
 
310
 
311
312
 
313
 
314
315
 
316
    if (ACPI_FAILURE (Status))
317
    {
318
        return (Status);
319
    }
320
321
 
322
     * Two address spaces supported: Memory or IO. PCI_Config is
323
     * not supported here because the GAS structure is insufficient
324
     */
325
    if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
326
    {
327
        Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
328
                    Address, Value, Reg->BitWidth);
329
    }
330
    else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
331
    {
332
        Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
333
                    Address, Value, Reg->BitWidth);
334
    }
335
336
 
337
        "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
338
        Value, Reg->BitWidth, ACPI_FORMAT_UINT64 (Address),
339
        AcpiUtGetRegionName (Reg->SpaceId)));
340
341
 
342
}
343
344
 
345
 
346
 *
347
 * FUNCTION:    AcpiHwClearAcpiStatus
348
 *
349
 * PARAMETERS:  None
350
 *
351
 * RETURN:      Status
352
 *
353
 * DESCRIPTION: Clears all fixed and general purpose status bits
354
 *
355
 ******************************************************************************/
356
357
 
358
AcpiHwClearAcpiStatus (
359
    void)
360
{
361
    ACPI_STATUS             Status;
362
    ACPI_CPU_FLAGS          LockFlags = 0;
363
364
 
365
 
366
367
 
368
 
369
        ACPI_BITMASK_ALL_FIXED_STATUS,
370
        ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
371
372
 
373
374
 
375
376
 
377
                ACPI_BITMASK_ALL_FIXED_STATUS);
378
    if (ACPI_FAILURE (Status))
379
    {
380
        goto UnlockAndExit;
381
    }
382
383
 
384
385
 
386
387
 
388
    AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
389
    return_ACPI_STATUS (Status);
390
}
391
392
 
393
 
394
 *
395
 * FUNCTION:    AcpiHwGetRegisterBitMask
396
 *
397
 * PARAMETERS:  RegisterId          - Index of ACPI Register to access
398
 *
399
 * RETURN:      The bitmask to be used when accessing the register
400
 *
401
 * DESCRIPTION: Map RegisterId into a register bitmask.
402
 *
403
 ******************************************************************************/
404
405
 
406
AcpiHwGetBitRegisterInfo (
407
    UINT32                  RegisterId)
408
{
409
    ACPI_FUNCTION_ENTRY ();
410
411
 
412
 
413
    {
414
        ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
415
        return (NULL);
416
    }
417
418
 
419
}
420
421
 
422
 
423
 *
424
 * FUNCTION:    AcpiHwWritePm1Control
425
 *
426
 * PARAMETERS:  Pm1aControl         - Value to be written to PM1A control
427
 *              Pm1bControl         - Value to be written to PM1B control
428
 *
429
 * RETURN:      Status
430
 *
431
 * DESCRIPTION: Write the PM1 A/B control registers. These registers are
432
 *              different than than the PM1 A/B status and enable registers
433
 *              in that different values can be written to the A/B registers.
434
 *              Most notably, the SLP_TYP bits can be different, as per the
435
 *              values returned from the _Sx predefined methods.
436
 *
437
 ******************************************************************************/
438
439
 
440
AcpiHwWritePm1Control (
441
    UINT32                  Pm1aControl,
442
    UINT32                  Pm1bControl)
443
{
444
    ACPI_STATUS             Status;
445
446
 
447
 
448
449
 
450
 
451
    if (ACPI_FAILURE (Status))
452
    {
453
        return_ACPI_STATUS (Status);
454
    }
455
456
 
457
    {
458
        Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
459
    }
460
    return_ACPI_STATUS (Status);
461
}
462
463
 
464
 
465
 *
466
 * FUNCTION:    AcpiHwRegisterRead
467
 *
468
 * PARAMETERS:  RegisterId          - ACPI Register ID
469
 *              ReturnValue         - Where the register value is returned
470
 *
471
 * RETURN:      Status and the value read.
472
 *
473
 * DESCRIPTION: Read from the specified ACPI register
474
 *
475
 ******************************************************************************/
476
477
 
478
AcpiHwRegisterRead (
479
    UINT32                  RegisterId,
480
    UINT32                  *ReturnValue)
481
{
482
    UINT32                  Value = 0;
483
    ACPI_STATUS             Status;
484
485
 
486
 
487
488
 
489
 
490
    {
491
    case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
492
493
 
494
                    &AcpiGbl_XPm1aStatus,
495
                    &AcpiGbl_XPm1bStatus);
496
        break;
497
498
 
499
 
500
501
 
502
                    &AcpiGbl_XPm1aEnable,
503
                    &AcpiGbl_XPm1bEnable);
504
        break;
505
506
 
507
 
508
509
 
510
                    &AcpiGbl_FADT.XPm1aControlBlock,
511
                    &AcpiGbl_FADT.XPm1bControlBlock);
512
513
 
514
         * Zero the write-only bits. From the ACPI specification, "Hardware
515
         * Write-Only Bits": "Upon reads to registers with write-only bits,
516
         * software masks out all write-only bits."
517
         */
518
        Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
519
        break;
520
521
 
522
 
523
524
 
525
        break;
526
527
 
528
 
529
530
 
531
        break;
532
533
 
534
 
535
536
 
537
        break;
538
539
 
540
 
541
        ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
542
            RegisterId));
543
        Status = AE_BAD_PARAMETER;
544
        break;
545
    }
546
547
 
548
    {
549
        *ReturnValue = Value;
550
    }
551
552
 
553
}
554
555
 
556
 
557
 *
558
 * FUNCTION:    AcpiHwRegisterWrite
559
 *
560
 * PARAMETERS:  RegisterId          - ACPI Register ID
561
 *              Value               - The value to write
562
 *
563
 * RETURN:      Status
564
 *
565
 * DESCRIPTION: Write to the specified ACPI register
566
 *
567
 * NOTE: In accordance with the ACPI specification, this function automatically
568
 * preserves the value of the following bits, meaning that these bits cannot be
569
 * changed via this interface:
570
 *
571
 * PM1_CONTROL[0] = SCI_EN
572
 * PM1_CONTROL[9]
573
 * PM1_STATUS[11]
574
 *
575
 * ACPI References:
576
 * 1) Hardware Ignored Bits: When software writes to a register with ignored
577
 *      bit fields, it preserves the ignored bit fields
578
 * 2) SCI_EN: OSPM always preserves this bit position
579
 *
580
 ******************************************************************************/
581
582
 
583
AcpiHwRegisterWrite (
584
    UINT32                  RegisterId,
585
    UINT32                  Value)
586
{
587
    ACPI_STATUS             Status;
588
    UINT32                  ReadValue;
589
590
 
591
 
592
593
 
594
 
595
    {
596
    case ACPI_REGISTER_PM1_STATUS:           /* PM1 A/B: 16-bit access each */
597
        /*
598
         * Handle the "ignored" bit in PM1 Status. According to the ACPI
599
         * specification, ignored bits are to be preserved when writing.
600
         * Normally, this would mean a read/modify/write sequence. However,
601
         * preserving a bit in the status register is different. Writing a
602
         * one clears the status, and writing a zero preserves the status.
603
         * Therefore, we must always write zero to the ignored bit.
604
         *
605
         * This behavior is clarified in the ACPI 4.0 specification.
606
         */
607
        Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
608
609
 
610
                    &AcpiGbl_XPm1aStatus,
611
                    &AcpiGbl_XPm1bStatus);
612
        break;
613
614
 
615
 
616
617
 
618
                    &AcpiGbl_XPm1aEnable,
619
                    &AcpiGbl_XPm1bEnable);
620
        break;
621
622
 
623
 
624
625
 
626
         * Perform a read first to preserve certain bits (per ACPI spec)
627
         * Note: This includes SCI_EN, we never want to change this bit
628
         */
629
        Status = AcpiHwReadMultiple (&ReadValue,
630
                    &AcpiGbl_FADT.XPm1aControlBlock,
631
                    &AcpiGbl_FADT.XPm1bControlBlock);
632
        if (ACPI_FAILURE (Status))
633
        {
634
            goto Exit;
635
        }
636
637
 
638
639
 
640
641
 
642
643
 
644
                    &AcpiGbl_FADT.XPm1aControlBlock,
645
                    &AcpiGbl_FADT.XPm1bControlBlock);
646
        break;
647
648
 
649
 
650
651
 
652
         * For control registers, all reserved bits must be preserved,
653
         * as per the ACPI spec.
654
         */
655
        Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock);
656
        if (ACPI_FAILURE (Status))
657
        {
658
            goto Exit;
659
        }
660
661
 
662
663
 
664
665
 
666
        break;
667
668
 
669
 
670
671
 
672
        break;
673
674
 
675
 
676
677
 
678
679
 
680
        break;
681
682
 
683
 
684
        ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
685
            RegisterId));
686
        Status = AE_BAD_PARAMETER;
687
        break;
688
    }
689
690
 
691
    return_ACPI_STATUS (Status);
692
}
693
694
 
695
 
696
 *
697
 * FUNCTION:    AcpiHwReadMultiple
698
 *
699
 * PARAMETERS:  Value               - Where the register value is returned
700
 *              RegisterA           - First ACPI register (required)
701
 *              RegisterB           - Second ACPI register (optional)
702
 *
703
 * RETURN:      Status
704
 *
705
 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
706
 *
707
 ******************************************************************************/
708
709
 
710
AcpiHwReadMultiple (
711
    UINT32                  *Value,
712
    ACPI_GENERIC_ADDRESS    *RegisterA,
713
    ACPI_GENERIC_ADDRESS    *RegisterB)
714
{
715
    UINT32                  ValueA = 0;
716
    UINT32                  ValueB = 0;
717
    ACPI_STATUS             Status;
718
719
 
720
 
721
722
 
723
    if (ACPI_FAILURE (Status))
724
    {
725
        return (Status);
726
    }
727
728
 
729
730
 
731
    {
732
        Status = AcpiHwRead (&ValueB, RegisterB);
733
        if (ACPI_FAILURE (Status))
734
        {
735
            return (Status);
736
        }
737
    }
738
739
 
740
     * OR the two return values together. No shifting or masking is necessary,
741
     * because of how the PM1 registers are defined in the ACPI specification:
742
     *
743
     * "Although the bits can be split between the two register blocks (each
744
     * register block has a unique pointer within the FADT), the bit positions
745
     * are maintained. The register block with unimplemented bits (that is,
746
     * those implemented in the other register block) always returns zeros,
747
     * and writes have no side effects"
748
     */
749
    *Value = (ValueA | ValueB);
750
    return (AE_OK);
751
}
752
753
 
754
 
755
 *
756
 * FUNCTION:    AcpiHwWriteMultiple
757
 *
758
 * PARAMETERS:  Value               - The value to write
759
 *              RegisterA           - First ACPI register (required)
760
 *              RegisterB           - Second ACPI register (optional)
761
 *
762
 * RETURN:      Status
763
 *
764
 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
765
 *
766
 ******************************************************************************/
767
768
 
769
AcpiHwWriteMultiple (
770
    UINT32                  Value,
771
    ACPI_GENERIC_ADDRESS    *RegisterA,
772
    ACPI_GENERIC_ADDRESS    *RegisterB)
773
{
774
    ACPI_STATUS             Status;
775
776
 
777
 
778
779
 
780
    if (ACPI_FAILURE (Status))
781
    {
782
        return (Status);
783
    }
784
785
 
786
     * Second register is optional
787
     *
788
     * No bit shifting or clearing is necessary, because of how the PM1
789
     * registers are defined in the ACPI specification:
790
     *
791
     * "Although the bits can be split between the two register blocks (each
792
     * register block has a unique pointer within the FADT), the bit positions
793
     * are maintained. The register block with unimplemented bits (that is,
794
     * those implemented in the other register block) always returns zeros,
795
     * and writes have no side effects"
796
     */
797
    if (RegisterB->Address)
798
    {
799
        Status = AcpiHwWrite (Value, RegisterB);
800
    }
801
802
 
803
}
804