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