ReactOS  0.4.14-dev-293-g2b39b42
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 - 2019, 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 #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 
57 static UINT8
61  UINT8 MaxBitWidth);
62 
63 static ACPI_STATUS
65  UINT32 *Value,
66  ACPI_GENERIC_ADDRESS *RegisterA,
67  ACPI_GENERIC_ADDRESS *RegisterB);
68 
69 static ACPI_STATUS
71  UINT32 Value,
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 
92 static 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 
144  if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
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,
182  UINT64 *Address)
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 
208  if ((Reg->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
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 {
263  UINT64 Address;
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 
278  Status = AcpiHwValidateRegister (Reg, 64, &Address);
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 
358  UINT64 Value,
360 {
361  UINT64 Address;
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 
375  Status = AcpiHwValidateRegister (Reg, 64, &Address);
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 
484 Exit:
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 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  */
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  {
650  *ReturnValue = (UINT32) Value;
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,
686  UINT32 Value)
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  */
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 
786 Exit:
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 
805 static 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 
867 static ACPI_STATUS
869  UINT32 Value,
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 */
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
ACPI_STATUS AcpiHwClearAcpiStatus(void)
Definition: hwregs.c:452
ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
Definition: osl.c:498
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define ACPI_REGISTER_PM2_CONTROL
Definition: aclocal.h:1187
#define AE_BAD_PARAMETER
Definition: acexcep.h:151
ACPI_STATUS AcpiHwClearGpeBlock(ACPI_GPE_XRUPT_INFO *GpeXruptInfo, ACPI_GPE_BLOCK_INFO *GpeBlock, void *Context)
Definition: hwgpe.c:404
#define ACPI_WARNING(plist)
Definition: acoutput.h:238
ACPI_STATUS AcpiHwValidateRegister(ACPI_GENERIC_ADDRESS *Reg, UINT8 MaxBitWidth, UINT64 *Address)
Definition: hwregs.c:179
#define ACPI_DB_IO
Definition: acoutput.h:177
#define ACPI_REGISTER_PM1_CONTROL
Definition: aclocal.h:1186
#define ACPI_CPU_FLAGS
Definition: actypes.h:252
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define ACPI_MASK_BITS_ABOVE_64(width)
Definition: acmacros.h:348
ACPI_STATUS AcpiHwReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
Definition: hwvalid.c:237
ACPI_STATUS AcpiHwRegisterRead(UINT32 RegisterId, UINT32 *ReturnValue)
Definition: hwregs.c:574
ACPI_BIT_REGISTER_INFO * AcpiHwGetBitRegisterInfo(UINT32 RegisterId)
Definition: hwregs.c:502
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define ACPI_PM1_STATUS_PRESERVED_BITS
Definition: aclocal.h:1157
UINT32 void void ** ReturnValue
Definition: acevents.h:214
#define ACPI_ADR_SPACE_SYSTEM_IO
Definition: actypes.h:852
const char * AcpiUtGetRegionName(UINT8 SpaceId)
Definition: utdecode.c:124
unsigned int UINT32
#define ACPI_BITMASK_ALL_FIXED_STATUS
Definition: aclocal.h:1204
#define ACPI_SET_BITS(TargetPtr, Position, Mask, Value)
Definition: acmacros.h:371
#define ACPI_INSERT_BITS(Target, Mask, Source)
Definition: acmacros.h:363
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
ACPI_STATUS AcpiHwWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
Definition: hwvalid.c:312
static ACPI_STATUS AcpiHwWriteMultiple(UINT32 Value, ACPI_GENERIC_ADDRESS *RegisterA, ACPI_GENERIC_ADDRESS *RegisterB)
Definition: hwregs.c:868
smooth NULL
Definition: ftsmooth.c:416
#define AE_INFO
Definition: acoutput.h:230
#define ACPI_REGISTER_PM_TIMER
Definition: aclocal.h:1188
static WCHAR Address[46]
Definition: ping.c:68
#define AE_BAD_ADDRESS
Definition: acexcep.h:159
ACPI_BIT_REGISTER_INFO AcpiGbl_BitRegisterInfo[ACPI_NUM_BITREG]
Definition: utglobal.c:145
#define ACPI_REGISTER_PM1_STATUS
Definition: aclocal.h:1184
#define ACPI_FUNCTION_ENTRY()
Definition: acoutput.h:484
#define ACPI_IS_ALIGNED(a, s)
Definition: acmacros.h:331
ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
Definition: osl.c:667
static void Exit(void)
Definition: sock.c:1331
#define ACPI_ROUND_UP(value, boundary)
Definition: acmacros.h:242
#define ACPI_IS_POWER_OF_TWO(a)
Definition: acmacros.h:332
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
static const UCHAR Index[8]
Definition: usbohci.c:18
#define AE_SUPPORT
Definition: acexcep.h:123
#define ACPI_PM1_CONTROL_WRITEONLY_BITS
Definition: aclocal.h:1161
ACPI_STATUS AcpiHwRead(UINT64 *Value, ACPI_GENERIC_ADDRESS *Reg)
Definition: hwregs.c:259
static ACPI_STATUS AcpiHwReadMultiple(UINT32 *Value, ACPI_GENERIC_ADDRESS *RegisterA, ACPI_GENERIC_ADDRESS *RegisterB)
Definition: hwregs.c:806
static UINT8 AcpiHwGetAccessBitWidth(UINT64 Address, ACPI_GENERIC_ADDRESS *Reg, UINT8 MaxBitWidth)
Definition: hwregs.c:93
#define ACPI_BITREG_MAX
Definition: actypes.h:922
#define ACPI_DIV_8(a)
Definition: acmacros.h:214
Status
Definition: gdiplustypes.h:24
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_FORMAT_UINT64(i)
Definition: acmacros.h:71
ACPI_STATUS AcpiHwRegisterWrite(UINT32 RegisterId, UINT32 Value)
Definition: hwregs.c:684
#define ACPI_REGISTER_SMI_COMMAND_BLOCK
Definition: aclocal.h:1190
ACPI_STATUS AcpiEvWalkGpeList(ACPI_GPE_CALLBACK GpeWalkCallback, void *Context)
Definition: evgpeutil.c:67
ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
Definition: osl.c:634
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
Definition: osl.c:516
ACPI_STATUS AcpiHwWritePm1Control(UINT32 Pm1aControl, UINT32 Pm1bControl)
Definition: hwregs.c:536
#define ACPI_MOVE_64_TO_64(d, s)
Definition: acmacros.h:155
#define ACPI_FUNCTION_NAME(a)
Definition: acoutput.h:479
#define ACPI_ACCESS_BIT_WIDTH(size)
Definition: actypes.h:582
#define ACPI_ADR_SPACE_SYSTEM_MEMORY
Definition: actypes.h:851
unsigned long long UINT64
#define ACPI_PM1_CONTROL_PRESERVED_BITS
Definition: aclocal.h:1175
#define ACPI_PM2_CONTROL_PRESERVED_BITS
Definition: aclocal.h:1178
#define ACPI_GET_BITS(SourcePtr, Position, Mask)
Definition: acmacros.h:368
unsigned char UINT8
#define ACPI_ROUND_UP_POWER_OF_TWO_8(a)
Definition: acmacros.h:319
#define ACPI_REGISTER_PM1_ENABLE
Definition: aclocal.h:1185
ACPI_STATUS AcpiHwWrite(UINT64 Value, ACPI_GENERIC_ADDRESS *Reg)
Definition: hwregs.c:357
#define AE_OK
Definition: acexcep.h:97