ReactOS 0.4.15-dev-8408-g466a198
hwregs.c
Go to the documentation of this file.
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 - 2022, 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 MERCHANTABILITY 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#include "acpi.h"
46#include "accommon.h"
47#include "acevents.h"
48
49#define _COMPONENT ACPI_HARDWARE
50 ACPI_MODULE_NAME ("hwregs")
51
52
53#if (!ACPI_REDUCED_HARDWARE)
54
55/* Local Prototypes */
56
57static UINT8
61 UINT8 MaxBitWidth);
62
63static ACPI_STATUS
66 ACPI_GENERIC_ADDRESS *RegisterA,
67 ACPI_GENERIC_ADDRESS *RegisterB);
68
69static ACPI_STATUS
72 ACPI_GENERIC_ADDRESS *RegisterA,
73 ACPI_GENERIC_ADDRESS *RegisterB);
74
75#endif /* !ACPI_REDUCED_HARDWARE */
76
77
78/******************************************************************************
79 *
80 * FUNCTION: AcpiHwGetAccessBitWidth
81 *
82 * PARAMETERS: Address - GAS register address
83 * Reg - GAS register structure
84 * MaxBitWidth - Max BitWidth supported (32 or 64)
85 *
86 * RETURN: Status
87 *
88 * DESCRIPTION: Obtain optimal access bit width
89 *
90 ******************************************************************************/
91
92static UINT8
96 UINT8 MaxBitWidth)
97{
98 UINT8 AccessBitWidth;
99
100
101 /*
102 * GAS format "register", used by FADT:
103 * 1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64;
104 * 2. AccessSize field is ignored and BitWidth field is used for
105 * determining the boundary of the IO accesses.
106 * GAS format "region", used by APEI registers:
107 * 1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64;
108 * 2. AccessSize field is used for determining the boundary of the
109 * IO accesses;
110 * 3. BitOffset/BitWidth fields are used to describe the "region".
111 *
112 * Note: This algorithm assumes that the "Address" fields should always
113 * contain aligned values.
114 */
115 if (!Reg->BitOffset && Reg->BitWidth &&
117 ACPI_IS_ALIGNED (Reg->BitWidth, 8))
118 {
119 AccessBitWidth = Reg->BitWidth;
120 }
121 else if (Reg->AccessWidth)
122 {
123 AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth);
124 }
125 else
126 {
127 AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 (
128 Reg->BitOffset + Reg->BitWidth);
129 if (AccessBitWidth <= 8)
130 {
131 AccessBitWidth = 8;
132 }
133 else
134 {
135 while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3))
136 {
137 AccessBitWidth >>= 1;
138 }
139 }
140 }
141
142 /* Maximum IO port access bit width is 32 */
143
145 {
146 MaxBitWidth = 32;
147 }
148
149 /*
150 * Return access width according to the requested maximum access bit width,
151 * as the caller should know the format of the register and may enforce
152 * a 32-bit accesses.
153 */
154 if (AccessBitWidth < MaxBitWidth)
155 {
156 return (AccessBitWidth);
157 }
158 return (MaxBitWidth);
159}
160
161
162/******************************************************************************
163 *
164 * FUNCTION: AcpiHwValidateRegister
165 *
166 * PARAMETERS: Reg - GAS register structure
167 * MaxBitWidth - Max BitWidth supported (32 or 64)
168 * Address - Pointer to where the gas->address
169 * is returned
170 *
171 * RETURN: Status
172 *
173 * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
174 * pointer, Address, SpaceId, BitWidth, and BitOffset.
175 *
176 ******************************************************************************/
177
181 UINT8 MaxBitWidth,
183{
184 UINT8 BitWidth;
185 UINT8 AccessWidth;
186
187
188 /* Must have a valid pointer to a GAS structure */
189
190 if (!Reg)
191 {
192 return (AE_BAD_PARAMETER);
193 }
194
195 /*
196 * Copy the target address. This handles possible alignment issues.
197 * Address must not be null. A null address also indicates an optional
198 * ACPI register that is not supported, so no error message.
199 */
201 if (!(*Address))
202 {
203 return (AE_BAD_ADDRESS);
204 }
205
206 /* Validate the SpaceID */
207
210 {
212 "Unsupported address space: 0x%X", Reg->SpaceId));
213 return (AE_SUPPORT);
214 }
215
216 /* Validate the AccessWidth */
217
218 if (Reg->AccessWidth > 4)
219 {
221 "Unsupported register access width: 0x%X", Reg->AccessWidth));
222 return (AE_SUPPORT);
223 }
224
225 /* Validate the BitWidth, convert AccessWidth into number of bits */
226
227 AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth);
228 BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth);
229 if (MaxBitWidth < BitWidth)
230 {
232 "Requested bit width 0x%X is smaller than register bit width 0x%X",
233 MaxBitWidth, BitWidth));
234 return (AE_SUPPORT);
235 }
236
237 return (AE_OK);
238}
239
240
241/******************************************************************************
242 *
243 * FUNCTION: AcpiHwRead
244 *
245 * PARAMETERS: Value - Where the value is returned
246 * Reg - GAS register structure
247 *
248 * RETURN: Status
249 *
250 * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max
251 * version of AcpiRead.
252 *
253 * LIMITATIONS: <These limitations also apply to AcpiHwWrite>
254 * SpaceID must be SystemMemory or SystemIO.
255 *
256 ******************************************************************************/
257
260 UINT64 *Value,
262{
264 UINT8 AccessWidth;
265 UINT32 BitWidth;
266 UINT8 BitOffset;
267 UINT64 Value64;
268 UINT32 Value32;
269 UINT8 Index;
271
272
273 ACPI_FUNCTION_NAME (HwRead);
274
275
276 /* Validate contents of the GAS register */
277
279 if (ACPI_FAILURE (Status))
280 {
281 return (Status);
282 }
283
284 /*
285 * Initialize entire 64-bit return value to zero, convert AccessWidth
286 * into number of bits based
287 */
288 *Value = 0;
289 AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
290 BitWidth = Reg->BitOffset + Reg->BitWidth;
291 BitOffset = Reg->BitOffset;
292
293 /*
294 * Two address spaces supported: Memory or IO. PCI_Config is
295 * not supported here because the GAS structure is insufficient
296 */
297 Index = 0;
298 while (BitWidth)
299 {
300 if (BitOffset >= AccessWidth)
301 {
302 Value64 = 0;
303 BitOffset -= AccessWidth;
304 }
305 else
306 {
308 {
309 Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
310 Address + Index * ACPI_DIV_8 (AccessWidth),
311 &Value64, AccessWidth);
312 }
313 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
314 {
315 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
316 Address + Index * ACPI_DIV_8 (AccessWidth),
317 &Value32, AccessWidth);
318 Value64 = (UINT64) Value32;
319 }
320 }
321
322 /*
323 * Use offset style bit writes because "Index * AccessWidth" is
324 * ensured to be less than 64-bits by AcpiHwValidateRegister().
325 */
326 ACPI_SET_BITS (Value, Index * AccessWidth,
327 ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64);
328
329 BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
330 Index++;
331 }
332
334 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
335 ACPI_FORMAT_UINT64 (*Value), AccessWidth,
337
338 return (Status);
339}
340
341
342/******************************************************************************
343 *
344 * FUNCTION: AcpiHwWrite
345 *
346 * PARAMETERS: Value - Value to be written
347 * Reg - GAS register structure
348 *
349 * RETURN: Status
350 *
351 * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max
352 * version of AcpiWrite.
353 *
354 ******************************************************************************/
355
360{
362 UINT8 AccessWidth;
363 UINT32 BitWidth;
364 UINT8 BitOffset;
365 UINT64 Value64;
366 UINT8 Index;
368
369
370 ACPI_FUNCTION_NAME (HwWrite);
371
372
373 /* Validate contents of the GAS register */
374
376 if (ACPI_FAILURE (Status))
377 {
378 return (Status);
379 }
380
381 /* Convert AccessWidth into number of bits based */
382
383 AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64);
384 BitWidth = Reg->BitOffset + Reg->BitWidth;
385 BitOffset = Reg->BitOffset;
386
387 /*
388 * Two address spaces supported: Memory or IO. PCI_Config is
389 * not supported here because the GAS structure is insufficient
390 */
391 Index = 0;
392 while (BitWidth)
393 {
394 /*
395 * Use offset style bit reads because "Index * AccessWidth" is
396 * ensured to be less than 64-bits by AcpiHwValidateRegister().
397 */
398 Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth,
399 ACPI_MASK_BITS_ABOVE_64 (AccessWidth));
400
401 if (BitOffset >= AccessWidth)
402 {
403 BitOffset -= AccessWidth;
404 }
405 else
406 {
408 {
409 Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
410 Address + Index * ACPI_DIV_8 (AccessWidth),
411 Value64, AccessWidth);
412 }
413 else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
414 {
415 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
416 Address + Index * ACPI_DIV_8 (AccessWidth),
417 (UINT32) Value64, AccessWidth);
418 }
419 }
420
421 /*
422 * Index * AccessWidth is ensured to be less than 32-bits by
423 * AcpiHwValidateRegister().
424 */
425 BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth;
426 Index++;
427 }
428
430 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
431 ACPI_FORMAT_UINT64 (Value), AccessWidth,
433
434 return (Status);
435}
436
437
438#if (!ACPI_REDUCED_HARDWARE)
439/*******************************************************************************
440 *
441 * FUNCTION: AcpiHwClearAcpiStatus
442 *
443 * PARAMETERS: None
444 *
445 * RETURN: Status
446 *
447 * DESCRIPTION: Clears all fixed and general purpose status bits
448 *
449 ******************************************************************************/
450
453 void)
454{
456 ACPI_CPU_FLAGS LockFlags = 0;
457
458
459 ACPI_FUNCTION_TRACE (HwClearAcpiStatus);
460
461
462 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
464 ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address)));
465
466 LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
467
468 /* Clear the fixed events in PM1 A/B */
469
472
473 AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
474
475 if (ACPI_FAILURE (Status))
476 {
477 goto Exit;
478 }
479
480 /* Clear the GPE Bits in all GPE registers in all GPE blocks */
481
483
484Exit:
486}
487
488
489/*******************************************************************************
490 *
491 * FUNCTION: AcpiHwGetBitRegisterInfo
492 *
493 * PARAMETERS: RegisterId - Index of ACPI Register to access
494 *
495 * RETURN: The bitmask to be used when accessing the register
496 *
497 * DESCRIPTION: Map RegisterId into a register bitmask.
498 *
499 ******************************************************************************/
500
503 UINT32 RegisterId)
504{
506
507
508 if (RegisterId > ACPI_BITREG_MAX)
509 {
510 ACPI_ERROR ((AE_INFO, "Invalid BitRegister ID: 0x%X", RegisterId));
511 return (NULL);
512 }
513
514 return (&AcpiGbl_BitRegisterInfo[RegisterId]);
515}
516
517
518/******************************************************************************
519 *
520 * FUNCTION: AcpiHwWritePm1Control
521 *
522 * PARAMETERS: Pm1aControl - Value to be written to PM1A control
523 * Pm1bControl - Value to be written to PM1B control
524 *
525 * RETURN: Status
526 *
527 * DESCRIPTION: Write the PM1 A/B control registers. These registers are
528 * different than the PM1 A/B status and enable registers
529 * in that different values can be written to the A/B registers.
530 * Most notably, the SLP_TYP bits can be different, as per the
531 * values returned from the _Sx predefined methods.
532 *
533 ******************************************************************************/
534
537 UINT32 Pm1aControl,
538 UINT32 Pm1bControl)
539{
541
542
543 ACPI_FUNCTION_TRACE (HwWritePm1Control);
544
545
546 Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock);
547 if (ACPI_FAILURE (Status))
548 {
550 }
551
552 if (AcpiGbl_FADT.XPm1bControlBlock.Address)
553 {
554 Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock);
555 }
557}
558
559
560/******************************************************************************
561 *
562 * FUNCTION: AcpiHwRegisterRead
563 *
564 * PARAMETERS: RegisterId - ACPI Register ID
565 * ReturnValue - Where the register value is returned
566 *
567 * RETURN: Status and the value read.
568 *
569 * DESCRIPTION: Read from the specified ACPI register
570 *
571 ******************************************************************************/
572
575 UINT32 RegisterId,
577{
578 UINT32 Value = 0;
579 UINT64 Value64;
581
582
583 ACPI_FUNCTION_TRACE (HwRegisterRead);
584
585
586 switch (RegisterId)
587 {
588 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
589
591 &AcpiGbl_XPm1aStatus,
592 &AcpiGbl_XPm1bStatus);
593 break;
594
595 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
596
598 &AcpiGbl_XPm1aEnable,
599 &AcpiGbl_XPm1bEnable);
600 break;
601
602 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
603
605 &AcpiGbl_FADT.XPm1aControlBlock,
606 &AcpiGbl_FADT.XPm1bControlBlock);
607
608 /*
609 * Zero the write-only bits. From the ACPI specification, "Hardware
610 * Write-Only Bits": "Upon reads to registers with write-only bits,
611 * software masks out all write-only bits."
612 */
613 Value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
614 break;
615
616 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
617
618 Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPm2ControlBlock);
619 if (ACPI_SUCCESS (Status))
620 {
621 Value = (UINT32) Value64;
622 }
623 break;
624
625 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
626
627 Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock);
628 if (ACPI_SUCCESS (Status))
629 {
630 Value = (UINT32) Value64;
631 }
632
633 break;
634
635 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
636
637 Status = AcpiHwReadPort (AcpiGbl_FADT.SmiCommand, &Value, 8);
638 break;
639
640 default:
641
642 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
643 RegisterId));
645 break;
646 }
647
648 if (ACPI_SUCCESS (Status))
649 {
651 }
652
654}
655
656
657/******************************************************************************
658 *
659 * FUNCTION: AcpiHwRegisterWrite
660 *
661 * PARAMETERS: RegisterId - ACPI Register ID
662 * Value - The value to write
663 *
664 * RETURN: Status
665 *
666 * DESCRIPTION: Write to the specified ACPI register
667 *
668 * NOTE: In accordance with the ACPI specification, this function automatically
669 * preserves the value of the following bits, meaning that these bits cannot be
670 * changed via this interface:
671 *
672 * PM1_CONTROL[0] = SCI_EN
673 * PM1_CONTROL[9]
674 * PM1_STATUS[11]
675 *
676 * ACPI References:
677 * 1) Hardware Ignored Bits: When software writes to a register with ignored
678 * bit fields, it preserves the ignored bit fields
679 * 2) SCI_EN: OSPM always preserves this bit position
680 *
681 ******************************************************************************/
682
685 UINT32 RegisterId,
687{
689 UINT32 ReadValue;
690 UINT64 ReadValue64;
691
692
693 ACPI_FUNCTION_TRACE (HwRegisterWrite);
694
695
696 switch (RegisterId)
697 {
698 case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */
699 /*
700 * Handle the "ignored" bit in PM1 Status. According to the ACPI
701 * specification, ignored bits are to be preserved when writing.
702 * Normally, this would mean a read/modify/write sequence. However,
703 * preserving a bit in the status register is different. Writing a
704 * one clears the status, and writing a zero preserves the status.
705 * Therefore, we must always write zero to the ignored bit.
706 *
707 * This behavior is clarified in the ACPI 4.0 specification.
708 */
709 Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
710
712 &AcpiGbl_XPm1aStatus,
713 &AcpiGbl_XPm1bStatus);
714 break;
715
716 case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */
717
719 &AcpiGbl_XPm1aEnable,
720 &AcpiGbl_XPm1bEnable);
721 break;
722
723 case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */
724 /*
725 * Perform a read first to preserve certain bits (per ACPI spec)
726 * Note: This includes SCI_EN, we never want to change this bit
727 */
728 Status = AcpiHwReadMultiple (&ReadValue,
729 &AcpiGbl_FADT.XPm1aControlBlock,
730 &AcpiGbl_FADT.XPm1bControlBlock);
731 if (ACPI_FAILURE (Status))
732 {
733 goto Exit;
734 }
735
736 /* Insert the bits to be preserved */
737
739
740 /* Now we can write the data */
741
743 &AcpiGbl_FADT.XPm1aControlBlock,
744 &AcpiGbl_FADT.XPm1bControlBlock);
745 break;
746
747 case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
748 /*
749 * For control registers, all reserved bits must be preserved,
750 * as per the ACPI spec.
751 */
752 Status = AcpiHwRead (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock);
753 if (ACPI_FAILURE (Status))
754 {
755 goto Exit;
756 }
757 ReadValue = (UINT32) ReadValue64;
758
759 /* Insert the bits to be preserved */
760
762
763 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock);
764 break;
765
766 case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
767
768 Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock);
769 break;
770
771 case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
772
773 /* SMI_CMD is currently always in IO space */
774
775 Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8);
776 break;
777
778 default:
779
780 ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X",
781 RegisterId));
783 break;
784 }
785
786Exit:
788}
789
790
791/******************************************************************************
792 *
793 * FUNCTION: AcpiHwReadMultiple
794 *
795 * PARAMETERS: Value - Where the register value is returned
796 * RegisterA - First ACPI register (required)
797 * RegisterB - Second ACPI register (optional)
798 *
799 * RETURN: Status
800 *
801 * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B)
802 *
803 ******************************************************************************/
804
805static ACPI_STATUS
807 UINT32 *Value,
808 ACPI_GENERIC_ADDRESS *RegisterA,
809 ACPI_GENERIC_ADDRESS *RegisterB)
810{
811 UINT32 ValueA = 0;
812 UINT32 ValueB = 0;
813 UINT64 Value64;
815
816
817 /* The first register is always required */
818
819 Status = AcpiHwRead (&Value64, RegisterA);
820 if (ACPI_FAILURE (Status))
821 {
822 return (Status);
823 }
824 ValueA = (UINT32) Value64;
825
826 /* Second register is optional */
827
828 if (RegisterB->Address)
829 {
830 Status = AcpiHwRead (&Value64, RegisterB);
831 if (ACPI_FAILURE (Status))
832 {
833 return (Status);
834 }
835 ValueB = (UINT32) Value64;
836 }
837
838 /*
839 * OR the two return values together. No shifting or masking is necessary,
840 * because of how the PM1 registers are defined in the ACPI specification:
841 *
842 * "Although the bits can be split between the two register blocks (each
843 * register block has a unique pointer within the FADT), the bit positions
844 * are maintained. The register block with unimplemented bits (that is,
845 * those implemented in the other register block) always returns zeros,
846 * and writes have no side effects"
847 */
848 *Value = (ValueA | ValueB);
849 return (AE_OK);
850}
851
852
853/******************************************************************************
854 *
855 * FUNCTION: AcpiHwWriteMultiple
856 *
857 * PARAMETERS: Value - The value to write
858 * RegisterA - First ACPI register (required)
859 * RegisterB - Second ACPI register (optional)
860 *
861 * RETURN: Status
862 *
863 * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B)
864 *
865 ******************************************************************************/
866
867static ACPI_STATUS
870 ACPI_GENERIC_ADDRESS *RegisterA,
871 ACPI_GENERIC_ADDRESS *RegisterB)
872{
874
875
876 /* The first register is always required */
877
878 Status = AcpiHwWrite (Value, RegisterA);
879 if (ACPI_FAILURE (Status))
880 {
881 return (Status);
882 }
883
884 /*
885 * Second register is optional
886 *
887 * No bit shifting or clearing is necessary, because of how the PM1
888 * registers are defined in the ACPI specification:
889 *
890 * "Although the bits can be split between the two register blocks (each
891 * register block has a unique pointer within the FADT), the bit positions
892 * are maintained. The register block with unimplemented bits (that is,
893 * those implemented in the other register block) always returns zeros,
894 * and writes have no side effects"
895 */
896 if (RegisterB->Address)
897 {
898 Status = AcpiHwWrite (Value, RegisterB);
899 }
900
901 return (Status);
902}
903
904#endif /* !ACPI_REDUCED_HARDWARE */
unsigned long long UINT64
unsigned char UINT8
unsigned int UINT32
UINT32 void void ** ReturnValue
Definition: acevents.h:216
#define AE_SUPPORT
Definition: acexcep.h:123
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_BAD_PARAMETER
Definition: acexcep.h:151
#define AE_BAD_ADDRESS
Definition: acexcep.h:159
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define AE_OK
Definition: acexcep.h:97
ACPI_BIT_REGISTER_INFO AcpiGbl_BitRegisterInfo[ACPI_NUM_BITREG]
Definition: utglobal.c:145
#define ACPI_PM1_CONTROL_PRESERVED_BITS
Definition: aclocal.h:1175
#define ACPI_REGISTER_PM2_CONTROL
Definition: aclocal.h:1187
#define ACPI_REGISTER_PM1_ENABLE
Definition: aclocal.h:1185
#define ACPI_PM2_CONTROL_PRESERVED_BITS
Definition: aclocal.h:1178
#define ACPI_REGISTER_PM_TIMER
Definition: aclocal.h:1188
#define ACPI_REGISTER_SMI_COMMAND_BLOCK
Definition: aclocal.h:1190
#define ACPI_BITMASK_ALL_FIXED_STATUS
Definition: aclocal.h:1204
#define ACPI_REGISTER_PM1_CONTROL
Definition: aclocal.h:1186
#define ACPI_REGISTER_PM1_STATUS
Definition: aclocal.h:1184
#define ACPI_SET_BITS(TargetPtr, Position, Mask, Value)
Definition: acmacros.h:371
#define ACPI_IS_ALIGNED(a, s)
Definition: acmacros.h:331
#define ACPI_GET_BITS(SourcePtr, Position, Mask)
Definition: acmacros.h:368
#define ACPI_FORMAT_UINT64(i)
Definition: acmacros.h:71
#define ACPI_DIV_8(a)
Definition: acmacros.h:214
#define ACPI_MASK_BITS_ABOVE_64(width)
Definition: acmacros.h:348
#define ACPI_MOVE_64_TO_64(d, s)
Definition: acmacros.h:155
#define ACPI_ROUND_UP(value, boundary)
Definition: acmacros.h:242
#define ACPI_INSERT_BITS(Target, Mask, Source)
Definition: acmacros.h:363
#define ACPI_ROUND_UP_POWER_OF_TWO_8(a)
Definition: acmacros.h:319
#define ACPI_IS_POWER_OF_TWO(a)
Definition: acmacros.h:332
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
#define ACPI_WARNING(plist)
Definition: acoutput.h:238
#define ACPI_FUNCTION_ENTRY()
Definition: acoutput.h:484
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
#define AE_INFO
Definition: acoutput.h:230
#define ACPI_FUNCTION_NAME(a)
Definition: acoutput.h:479
#define ACPI_DB_IO
Definition: acoutput.h:177
ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
Definition: osl.c:634
ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
Definition: osl.c:667
void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
Definition: osl.c:516
ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
Definition: osl.c:498
#define ACPI_BITREG_MAX
Definition: actypes.h:933
#define ACPI_ADR_SPACE_SYSTEM_IO
Definition: actypes.h:862
#define ACPI_CPU_FLAGS
Definition: actypes.h:252
#define ACPI_ADR_SPACE_SYSTEM_MEMORY
Definition: actypes.h:861
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define ACPI_ACCESS_BIT_WIDTH(size)
Definition: actypes.h:591
const char * AcpiUtGetRegionName(UINT8 SpaceId)
Definition: utdecode.c:125
#define NULL
Definition: types.h:112
ACPI_STATUS AcpiEvWalkGpeList(ACPI_GPE_CALLBACK GpeWalkCallback, void *Context)
Definition: evgpeutil.c:67
Status
Definition: gdiplustypes.h:25
ACPI_STATUS AcpiHwClearGpeBlock(ACPI_GPE_XRUPT_INFO *GpeXruptInfo, ACPI_GPE_BLOCK_INFO *GpeBlock, void *Context)
Definition: hwgpe.c:404
ACPI_STATUS AcpiHwWritePm1Control(UINT32 Pm1aControl, UINT32 Pm1bControl)
Definition: hwregs.c:536
ACPI_STATUS AcpiHwValidateRegister(ACPI_GENERIC_ADDRESS *Reg, UINT8 MaxBitWidth, UINT64 *Address)
Definition: hwregs.c:179
static ACPI_STATUS AcpiHwReadMultiple(UINT32 *Value, ACPI_GENERIC_ADDRESS *RegisterA, ACPI_GENERIC_ADDRESS *RegisterB)
Definition: hwregs.c:806
ACPI_STATUS AcpiHwWrite(UINT64 Value, ACPI_GENERIC_ADDRESS *Reg)
Definition: hwregs.c:357
ACPI_STATUS AcpiHwClearAcpiStatus(void)
Definition: hwregs.c:452
ACPI_STATUS AcpiHwRead(UINT64 *Value, ACPI_GENERIC_ADDRESS *Reg)
Definition: hwregs.c:259
ACPI_STATUS AcpiHwRegisterRead(UINT32 RegisterId, UINT32 *ReturnValue)
Definition: hwregs.c:574
static UINT8 AcpiHwGetAccessBitWidth(UINT64 Address, ACPI_GENERIC_ADDRESS *Reg, UINT8 MaxBitWidth)
Definition: hwregs.c:93
static ACPI_STATUS AcpiHwWriteMultiple(UINT32 Value, ACPI_GENERIC_ADDRESS *RegisterA, ACPI_GENERIC_ADDRESS *RegisterB)
Definition: hwregs.c:868
ACPI_STATUS AcpiHwRegisterWrite(UINT32 RegisterId, UINT32 Value)
Definition: hwregs.c:684
ACPI_BIT_REGISTER_INFO * AcpiHwGetBitRegisterInfo(UINT32 RegisterId)
Definition: hwregs.c:502
ACPI_STATUS AcpiHwWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
Definition: hwvalid.c:312
ACPI_STATUS AcpiHwReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
Definition: hwvalid.c:237
static WCHAR Address[46]
Definition: ping.c:68
static void Exit(void)
Definition: sock.c:1330
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413