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.

312 lines
6.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. amdk6msr.c
  5. Abstract:
  6. This module implements code specific to the AMDK6-2 processor
  7. Author:
  8. Todd Carpenter (7/20/00) - create file
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include <ntddk.h>
  14. #include <ntacpi.h>
  15. #include "amdk6.h"
  16. extern LEGACY_GEMINI_SMI LegacyInterface;
  17. extern HalpFixedAcpiDescTable;
  18. PUCHAR ProcessorToBusClockRatioStr[] = {
  19. "4.5x", // 0
  20. "5.0x", // 1
  21. "4.0x", // 2
  22. "5.5x", // 3
  23. "2.0x", // 4
  24. "3.0x", // 5
  25. "6.0x", // 6
  26. "3.5x", // 7
  27. };
  28. NTSTATUS
  29. GetCurrentCpuSpeedMSR (
  30. OUT PULONG CpuSpeed
  31. )
  32. /*++
  33. Routine Description:
  34. Arguments:
  35. Return Value:
  36. --*/
  37. {
  38. NTSTATUS status;
  39. UCHAR vidANDbf;
  40. ULONG state;
  41. LARGE_INTEGER msrInfo;
  42. DebugAssert(LegacyInterface.GBDT);
  43. DebugAssert(CpuSpeed);
  44. msrInfo.QuadPart = ReadMSR(AMDK6_GEMINI_PSOR_MSR);
  45. //
  46. // VID [20:16 ] and BF [ 2:0 ] --> VID [4:0 ] and BF [7:5 ]
  47. //
  48. vidANDbf = (UCHAR)(((msrInfo.LowPart >> 16) & 0x1f) | ((msrInfo.LowPart & 0x7) << 5));
  49. status = ConvertVidBfValueToGeminiState(vidANDbf, &state);
  50. if (NT_SUCCESS(status)) {
  51. *CpuSpeed = LegacyInterface.GBDT->State[state].CpuFrequency;
  52. }
  53. return status;
  54. }
  55. NTSTATUS
  56. SetCurrentStateMSR (
  57. ULONG State
  58. )
  59. /*++
  60. Description:
  61. Arguments:
  62. Return Value:
  63. NTSTATUS
  64. --*/
  65. {
  66. #define STOP_GRANT_TIME_OUT 3 // ISSUE: need to check bus clock to gen this number
  67. LARGE_INTEGER msrInfo;
  68. NTSTATUS status = STATUS_NOT_SUPPORTED;
  69. ULONG esiReturned, geminiState;
  70. UCHAR vidANDbf = 0;
  71. ULONG bvcValue = 0;
  72. DebugAssert(LegacyInterface.EpmIoAddress);
  73. //
  74. // Convert to Gemini State
  75. //
  76. geminiState = CONVERT_PERF_STATE_INDEX(State);
  77. //
  78. // Lookup VID and BF values for geminiState
  79. //
  80. vidANDbf = (LegacyInterface.GBDT->State[geminiState].Vid) |
  81. ((LegacyInterface.GBDT->State[geminiState].Bf) << 5);
  82. //
  83. // Build BVC value to write to I/O space to initiate transition
  84. //
  85. bvcValue |= (STOP_GRANT_TIME_OUT << 12); // Stop Grant Time-out Counter
  86. bvcValue |= (0x6 << 8); // BVF[11:8] == 0110
  87. bvcValue |= vidANDbf; //
  88. _asm {
  89. //
  90. // Disable bus masters
  91. //
  92. mov edx, [HalpFixedAcpiDescTable + 72]
  93. in al, dx // read PM2_CNT_BLK
  94. mov cl, al // save current PM2_CNT_BLK
  95. or al, 0x1 // set ARB_DIS bit
  96. out dx, al // write PM2_CNT_BLK
  97. //
  98. // initiate processor transition
  99. //
  100. mov edx, LegacyInterface.EpmIoAddress
  101. mov eax, bvcValue
  102. out dx, eax
  103. //
  104. // Restore bus master access
  105. //
  106. mov edx, [HalpFixedAcpiDescTable + 72]
  107. mov al, cl
  108. out dx, al
  109. }
  110. //
  111. // BUGBUG: Need to figure out error checking. Should probably go read
  112. // see if PSOR reflects our new vid and bf values.
  113. //
  114. return STATUS_SUCCESS;
  115. }
  116. NTSTATUS
  117. ReadEpmInfo (
  118. OUT PULONG EpmInfo
  119. )
  120. /*++
  121. Routine Description:
  122. Arguments:
  123. Return Value:
  124. --*/
  125. {
  126. ULONG emp;
  127. _asm {
  128. mov eax, AMDK6_GEMINI_CPUID_EPM
  129. xor ebx, ebx
  130. xor ecx, ecx
  131. xor edx, edx // will be destroyed by the cpuid
  132. cpuid
  133. mov emp, edx
  134. }
  135. if (ARGUMENT_PRESENT(EpmInfo)) {
  136. *EpmInfo = emp;
  137. }
  138. return STATUS_SUCCESS;
  139. }
  140. NTSTATUS
  141. EnableGeminiTransitionsMSR (
  142. PULONG BaseAddress
  143. )
  144. /*++
  145. Routine Description:
  146. Arguments:
  147. Return Value:
  148. --*/
  149. {
  150. ULARGE_INTEGER msrInfo;
  151. DebugAssert(BaseAddress);
  152. //
  153. // EPMR contains I/O block address for perf transitions
  154. //
  155. msrInfo.QuadPart = ReadMSR(AMDK6_GEMINI_EPMR_MSR);
  156. *BaseAddress = (msrInfo.LowPart & ~0xf) + 8;
  157. DebugPrint((INFO, "EnableGeminiTransitionsMSR: Base Address = 0x%x\n", *BaseAddress));
  158. //
  159. // Enable mobile feature base address
  160. //
  161. msrInfo.LowPart |= 0x1;
  162. WriteMSR(AMDK6_GEMINI_EPMR_MSR, msrInfo.QuadPart);
  163. return STATUS_SUCCESS;
  164. }
  165. VOID
  166. DisplayEPM (
  167. IN ULONG Epm
  168. )
  169. {
  170. DebugPrint((MAXTRACE, "Enhanced Power Management Information (0x%x):\n", Epm));
  171. DebugPrint((MAXTRACE, " Temperature Sensor: %sSupported\n", (Epm & 0x1) ? "" : "NOT "));
  172. DebugPrint((MAXTRACE, " Bus Divisor Control: %sSupported\n", (Epm & 0x2) ? "" : "NOT "));
  173. DebugPrint((MAXTRACE, " Voltage Id control: %sSupported\n", (Epm & 0x4) ? "" : "NOT "));
  174. DebugPrint((MAXTRACE, "\n"));
  175. }
  176. VOID
  177. DisplayEPMR (
  178. IN ULONG Epmr
  179. )
  180. {
  181. DebugPrint((MAXTRACE, "Enhanced Power Management Register (0x%x):\n", Epmr));
  182. DebugPrint((MAXTRACE, " Mobile Feature Base Address = %sEnabled\n", (Epmr & 0x1) ? "" : "NOT "));
  183. DebugPrint((MAXTRACE, " Generate Special Bus Cycle = %sEnabled\n", (Epmr & 0x2) ? "" : "NOT "));
  184. DebugPrint((MAXTRACE, " I/O Base Address = 0x%x\n", ((Epmr >> 4) & 0xffff)));
  185. DebugPrint((MAXTRACE, "\n"));
  186. }
  187. VOID
  188. DisplayPSOR (
  189. IN ULONG Psor
  190. )
  191. {
  192. DebugPrint((MAXTRACE, "Processor State Observability (0x%x):\n", Psor));
  193. DebugPrint((MAXTRACE, " Bus Frequency Divisor (Internal) = 0x%x (%s)\n", (Psor & 0x3),
  194. ProcessorToBusClockRatioStr[(Psor & 0x3)]));
  195. DebugPrint((MAXTRACE, " Processor Stepping Id = 0x%x\n", ((Psor >> 4) & 0xf)));
  196. DebugPrint((MAXTRACE, " L2 Cache Present = %s\n", (Psor & 0x256) ? "No" : "Yes"));
  197. DebugPrint((MAXTRACE, " Voltage Id = 0x%x\n", ((Psor >> 16) & 0x1f)));
  198. DebugPrint((MAXTRACE, " Bus Frequency Divisor (External) = 0x%x (%s)\n", ((Psor >> 21) & 0x3),
  199. ProcessorToBusClockRatioStr[((Psor >> 21) & 0x3)]));
  200. DebugPrint((MAXTRACE, "\n"));
  201. }