Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
4.6 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. acpienbl.c
  5. Abstract:
  6. This module contains functions to put an ACPI machine in ACPI mode.
  7. Author:
  8. Jason Clark (jasoncl)
  9. Environment:
  10. NT Kernel Model Driver only
  11. --*/
  12. #include "pch.h"
  13. VOID
  14. ACPIEnableEnterACPIMode (
  15. VOID
  16. )
  17. /*++
  18. Routine Description:
  19. This routine is called to enter ACPI mode
  20. Arguments:
  21. None
  22. Return Value:
  23. None
  24. --*/
  25. {
  26. ULONG i;
  27. ASSERTMSG(
  28. "ACPIEnableEnterACPIMode: System already in ACPI mode!\n",
  29. !(READ_PM1_CONTROL() & PM1_SCI_EN)
  30. );
  31. //
  32. // Let the world know about this
  33. //
  34. ACPIPrint( (
  35. ACPI_PRINT_LOADING,
  36. "ACPIEnableEnterACPIMode: Enabling ACPI\n"
  37. ) );
  38. //
  39. // Write the magic value to the port
  40. //
  41. WRITE_ACPI_REGISTER(SMI_CMD, 0,
  42. AcpiInformation->FixedACPIDescTable->acpi_on_value);
  43. //
  44. // Make sure that we see that PM1 is in fact enabled
  45. //
  46. for (i = 0; ; i++) {
  47. if ( (READ_PM1_CONTROL() & PM1_SCI_EN) ) {
  48. break;
  49. }
  50. if (i > 0xFFFFFF) {
  51. KeBugCheckEx(
  52. ACPI_BIOS_ERROR,
  53. ACPI_SYSTEM_CANNOT_START_ACPI,
  54. 6,
  55. 0,
  56. 0
  57. );
  58. }
  59. }
  60. }
  61. VOID
  62. ACPIEnableInitializeACPI(
  63. IN BOOLEAN ReEnable
  64. )
  65. /*++
  66. Routine Description:
  67. A function to put an ACPI machine into ACPI mode. This function should be
  68. called with the SCI IRQ masked since we cannot set the interrupt enable
  69. mask until after enabling ACPI. The SCI should be unmasked by the caller
  70. when the call returns.
  71. General Sequence:
  72. Enable ACPI through the SMI command port
  73. Clear the PM1_STS register to put it in a known state
  74. Set the PM1_EN register mask
  75. Build the GP mask
  76. Clear the GP status register bits which belong to the GP mask
  77. Set the GP enable register bits according to the GP mask built above
  78. Set the PM1_CTRL register bits.
  79. Arguments:
  80. NONE
  81. Return Value:
  82. NONE
  83. --*/
  84. {
  85. USHORT contents;
  86. USHORT clearbits;
  87. //
  88. // Read PM1_CTRL, if SCI_EN is already set then this is an ACPI only machine
  89. // and we do not need to Enable ACPI
  90. //
  91. if ( !(READ_PM1_CONTROL() & PM1_SCI_EN) ) {
  92. AcpiInformation->ACPIOnly = FALSE;
  93. ACPIEnableEnterACPIMode();
  94. }
  95. //
  96. // Put the pm1 status registers into a known state. We will allow the Bus
  97. // Master bit to be enabled (if we have no choice) across this reset. I do
  98. // not pretend to understand this code
  99. //
  100. CLEAR_PM1_STATUS_REGISTER();
  101. contents = (USHORT)(READ_PM1_STATUS() & ~(PM1_BM_STS | PM1_RTC_STS));
  102. if (contents) {
  103. CLEAR_PM1_STATUS_REGISTER();
  104. contents = (USHORT)(READ_PM1_STATUS() & ~(PM1_BM_STS | PM1_RTC_STS));
  105. }
  106. ASSERTMSG(
  107. "ACPIEnableInitializeACPI: Cannot clear PM1 Status Register\n",
  108. (contents == 0)
  109. );
  110. //
  111. // We determined what the PM1 enable bits are when we processed the FADT.
  112. // We should now enable those bits
  113. //
  114. WRITE_PM1_ENABLE( AcpiInformation->pm1_en_bits );
  115. ASSERTMSG(
  116. "ACPIEnableInitializeACPI: Cannot write all PM1 Enable Bits\n",
  117. (READ_PM1_ENABLE() == AcpiInformation->pm1_en_bits)
  118. );
  119. //
  120. // This is called when we renable ACPI after having woken up from sleep
  121. // or hibernate
  122. //
  123. if (ReEnable) {
  124. //
  125. // Re-enable all possible GPE events
  126. //
  127. ACPIGpeClearRegisters();
  128. ACPIGpeEnableDisableEvents( TRUE );
  129. }
  130. //
  131. // Calculate the bits that we should clear. These are the
  132. // sleep enable bit and the bus master bit.
  133. //
  134. // [vincentg] - the original implementation cleared SLP_TYP as well -
  135. // this breaks C2/C3 on Intel PIIX4 chipsets. Updated to only clear
  136. // SLP_EN and BM_RLD.
  137. //
  138. clearbits = ((0x8 << SLP_TYP_POS) | PM1_BM_RLD);
  139. //
  140. // Read the PM1 control registery, clear the unwanted bits and then
  141. // write it back
  142. //
  143. contents = (READ_PM1_CONTROL() & ~clearbits);
  144. WRITE_PM1_CONTROL ( contents, TRUE, WRITE_REGISTER_A_AND_B );
  145. }
  146. VOID
  147. ACPIEnablePMInterruptOnly(
  148. VOID
  149. )
  150. /*++
  151. Routine Descrition:
  152. Enable interrupts in the ACPI controller
  153. Arguments:
  154. None
  155. Return Value:
  156. None
  157. --*/
  158. {
  159. WRITE_PM1_ENABLE(AcpiInformation->pm1_en_bits);
  160. }
  161. ULONG
  162. ACPIEnableQueryFixedEnables (
  163. VOID
  164. )
  165. /*++
  166. Routine Descrition:
  167. Returns the enable mask
  168. Arguments:
  169. None
  170. Return Value:
  171. None
  172. --*/
  173. {
  174. return AcpiInformation->pm1_en_bits;
  175. }