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.

819 lines
15 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. longrun.c
  5. Abstract:
  6. This module implements the Crusoe LongRun Adaptive Power Control interface
  7. Author:
  8. Todd Carpenter (10/31/00) - create file
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include <ntddk.h>
  15. #include <ntacpi.h>
  16. #include "crusoe.h"
  17. LONGRUN_STATES LongRunStates;
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text (PAGE, InitializeLegacyInterface)
  20. #pragma alloc_text (PAGE, GetCurrentCpuSpeed)
  21. #pragma alloc_text (PAGE, GetMaxCpuSpeed)
  22. #endif
  23. NTSTATUS
  24. InitializeLegacyInterface(
  25. IN PFDO_DATA DeviceExtension
  26. )
  27. /*++
  28. Routine Description:
  29. Arguments:
  30. Return Value:
  31. --*/
  32. {
  33. NTSTATUS status = STATUS_SUCCESS;
  34. ULONG flags;
  35. DebugEnter();
  36. PAGED_CODE();
  37. //
  38. // Check Processor Feature Flags
  39. //
  40. GetProcessorFeatureFlags(&flags);
  41. if (flags & FEATURE_LONGRUN_ENALBED) {
  42. //
  43. // If the CMS4.2 Interface is present use it, else use CMS4.1
  44. //
  45. if (flags & FEATURE_LRTI_ENABLED) {
  46. DebugPrint((ERROR, "Using LongRun CMS 4.2 Interface\n"));
  47. BuildLongRunPerfStatesCMS42(&DeviceExtension->PssPackage);
  48. } else {
  49. DebugPrint((ERROR, "Using LongRun CMS 4.1 Interface\n"));
  50. BuildLongRunPerfStatesCMS41(&DeviceExtension->PssPackage);
  51. }
  52. DeviceExtension->PctPackage.Control.AddressSpaceID = AcpiGenericSpaceFixedFunction;
  53. DeviceExtension->PctPackage.Status.AddressSpaceID = AcpiGenericSpaceFixedFunction;
  54. //
  55. // Walk through _PSS states to calculate latency values
  56. //
  57. ValidatePssLatencyValues(DeviceExtension);
  58. } else {
  59. //
  60. // LongRun Interface is not present
  61. //
  62. DebugAssert(!"LongRun Interface is NOT enabled!\n");
  63. status = STATUS_UNSUCCESSFUL;
  64. }
  65. DebugExitStatus(status)
  66. return status;
  67. }
  68. NTSTATUS
  69. SetCurrentStateMSR(
  70. IN ULONG State,
  71. IN BOOLEAN InitPhase
  72. )
  73. /*++
  74. Routine Description:
  75. Arguments:
  76. Return Value:
  77. --*/
  78. {
  79. ULONG index, longRunMax, longRunMin = 0;
  80. NTSTATUS status = STATUS_SUCCESS;
  81. ULARGE_INTEGER longRunStatus;
  82. //
  83. // Convert our Perf State Value to LongRun value.
  84. // NOTE: LongRun states are stored in Ascending order.
  85. //
  86. index = (LongRunStates.MaxState - 1) - State;
  87. longRunMax = LongRunStates.States[index].LongRunValue;
  88. if (InitPhase) {
  89. longRunMin = longRunMax;
  90. }
  91. DebugPrint((ERROR, "Setting Long Run Range: l=0x%x, u=0x%x\n", longRunMin, longRunMax));
  92. SetCurrentPerformanceRange(longRunMin, longRunMax);
  93. longRunStatus.QuadPart = GetCurrentPerformanceRange();
  94. if ((longRunStatus.HighPart != longRunMax) ||
  95. (longRunStatus.LowPart != longRunMin)) {
  96. DebugPrint((ERROR, "ERROR! Expected: l=0x%x, h=0x%x Recieved: l=0x%x, h=0x%x\n",
  97. longRunMin,
  98. longRunMax,
  99. longRunStatus.LowPart,
  100. longRunStatus.HighPart));
  101. status = STATUS_UNSUCCESSFUL;
  102. }
  103. return status;
  104. }
  105. ULONG
  106. ConvertLongRunValueToPerfState(
  107. IN PLONGRUN_STATES PerfStates,
  108. IN ULONG LongRunValue
  109. )
  110. /*++
  111. Routine Description:
  112. Arguments:
  113. Return Value:
  114. --*/
  115. {
  116. ULONG x;
  117. //
  118. // Convert Transemta state values in Perf state values.
  119. //
  120. for (x = 0; x < PerfStates->MaxState; x++) {
  121. if (PerfStates->States[x].LongRunValue == LongRunValue) {
  122. return x;
  123. }
  124. }
  125. return INVALID_LONGRUN_STATE;
  126. }
  127. NTSTATUS
  128. GetCurrentCpuSpeed(
  129. OUT PULONG CpuSpeed
  130. )
  131. /*++
  132. Routine Description:
  133. Arguments:
  134. Return Value:
  135. --*/
  136. {
  137. NTSTATUS status;
  138. STATE_INFO stateInfo;
  139. DebugAssert(CpuSpeed);
  140. status = GetCurrentStateInfo(&stateInfo);
  141. if (NT_SUCCESS(status)) {
  142. *CpuSpeed = stateInfo.CpuSpeed;
  143. }
  144. return status;
  145. }
  146. NTSTATUS
  147. GetMaxCpuSpeed(
  148. OUT PULONG CpuSpeed
  149. )
  150. /*++
  151. Routine Description:
  152. Arguments:
  153. Return Value:
  154. --*/
  155. {
  156. ULONG junk;
  157. DebugAssert(CpuSpeed);
  158. PAGED_CODE();
  159. CPUID(LONGRUN_CPUID_PROCESSOR_INFO,
  160. &junk,
  161. &junk,
  162. CpuSpeed,
  163. &junk);
  164. return STATUS_SUCCESS;
  165. }
  166. VOID
  167. GetProcessorFeatureFlags(
  168. OUT PULONG Flags
  169. )
  170. /*++
  171. Routine Description:
  172. Arguments:
  173. Return Value:
  174. --*/
  175. {
  176. ULONG junk;
  177. DebugAssert(Flags);
  178. PAGED_CODE();
  179. CPUID(LONGRUN_CPUID_PROCESSOR_INFO,
  180. &junk,
  181. &junk,
  182. &junk,
  183. Flags);
  184. }
  185. NTSTATUS
  186. GetCurrentStateInfo(
  187. OUT PSTATE_INFO StateInfo
  188. )
  189. /*++
  190. Routine Description:
  191. Arguments:
  192. Return Value:
  193. --*/
  194. {
  195. ULONG junk;
  196. DebugAssert(StateInfo);
  197. CPUID(LONGRUN_CPUID_GETSTATE,
  198. &StateInfo->CpuSpeed,
  199. &StateInfo->Voltage,
  200. &StateInfo->LongRunValue,
  201. &junk);
  202. return STATUS_SUCCESS;
  203. }
  204. ULONGLONG
  205. GetCurrentPerformanceRange(
  206. VOID
  207. )
  208. /*++
  209. Routine Description:
  210. Arguments:
  211. Return Value:
  212. --*/
  213. {
  214. return ReadMSR(LONGRUN_CONTROL_STATUS_MSR);
  215. }
  216. VOID
  217. SetCurrentPerformanceRange(
  218. IN ULONG Min,
  219. IN ULONG Max
  220. )
  221. /*++
  222. Routine Description:
  223. Arguments:
  224. Return Value:
  225. --*/
  226. {
  227. ULARGE_INTEGER msrInfo;
  228. msrInfo.LowPart = Min;
  229. msrInfo.HighPart = Max;
  230. WriteMSR(LONGRUN_CONTROL_STATUS_MSR, msrInfo.QuadPart);
  231. }
  232. NTSTATUS
  233. CalculateLongRunPerfStates(
  234. IN PLONGRUN_STATES PerfStates
  235. )
  236. /*++
  237. Routine Description:
  238. Arguments:
  239. Return Value:
  240. --*/
  241. {
  242. STATE_INFO stateInfo;
  243. ULONG x, currentPerfState = 0;
  244. ULONG currentLongRunValue = INVALID_LONGRUN_STATE;
  245. DebugAssert(PerfStates);
  246. PerfStates->MaxState = MAX_LONGRUN_STATES;
  247. //
  248. // step through each state from 0 - 100, recording
  249. // unique performance states
  250. //
  251. for (x = 0; x <= MAX_LONGRUN_VALUE; x++) {
  252. //DebugPrint((ERROR, "Transition to state %u\n", x));
  253. SetCurrentPerformanceRange(x, x);
  254. GetCurrentStateInfo(&stateInfo);
  255. //DisplayStateInfo(&stateInfo);
  256. //
  257. // If this is a new state, record it.
  258. //
  259. // NOTE: we are ASSUMING that all states with identical LongRun
  260. // state values are contigous AND that the LongRun values
  261. // are increasing in value. Here is an example of what we
  262. // expect to find.
  263. //
  264. // LongRun States (0-100) unique LongRun value
  265. //
  266. // 0-25 0
  267. // 26-50 40
  268. // 51-75 71
  269. // 76-100 100
  270. //
  271. if (stateInfo.LongRunValue != currentLongRunValue) {
  272. DebugAssert(currentPerfState < PerfStates->MaxState);
  273. DebugAssert(stateInfo.LongRunValue <= MAX_LONGRUN_VALUE);
  274. currentLongRunValue = stateInfo.LongRunValue;
  275. RtlCopyMemory(&PerfStates->States[currentPerfState++],
  276. &stateInfo,
  277. sizeof(STATE_INFO));
  278. }
  279. }
  280. return STATUS_SUCCESS;
  281. }
  282. NTSTATUS
  283. BuildAcpi2PerformanceStates(
  284. IN PACPI_PSS_PACKAGE PerfStates
  285. )
  286. /*++
  287. Routine Description:
  288. Arguments:
  289. Return Value:
  290. --*/
  291. {
  292. return STATUS_SUCCESS;
  293. }
  294. NTSTATUS
  295. BuildLongRunPerfStatesCMS41(
  296. OUT PACPI_PSS_PACKAGE *PssPackage
  297. )
  298. /*++
  299. Routine Description:
  300. Arguments:
  301. Return Value:
  302. --*/
  303. {
  304. ULONG x;
  305. ULONG pssSize;
  306. ULONG currentPerfState = 0;
  307. ULONG currentLongRunValue = INVALID_LONGRUN_STATE;
  308. NTSTATUS status = STATUS_SUCCESS;
  309. STATE_INFO stateInfo;
  310. PACPI_PSS_PACKAGE tmpPss;
  311. DebugEnter();
  312. DebugAssert(PssPackage);
  313. pssSize = sizeof(ACPI_PSS_PACKAGE) +
  314. ((MAX_LONGRUN_STATES-1) * sizeof(ACPI_PSS_DESCRIPTOR));
  315. tmpPss = ExAllocatePoolWithTag(NonPagedPool,
  316. pssSize,
  317. PROCESSOR_POOL_TAG);
  318. if (!tmpPss) {
  319. status = STATUS_INSUFFICIENT_RESOURCES;
  320. goto BuildLongRunPerfStatesCMS41Exit;
  321. }
  322. //
  323. // Iterate through each level collecting data.
  324. //
  325. tmpPss->NumPStates = MAX_LONGRUN_STATES;
  326. for (x = 0; x <= MAX_LONGRUN_VALUE; x += 5) {
  327. SetCurrentPerformanceRange(x, x);
  328. GetCurrentStateInfo(&stateInfo);
  329. //
  330. // If this is a new state, record it.
  331. //
  332. // NOTE: we are ASSUMING that all states with identical LongRun
  333. // state values are contigous AND that the LongRun values
  334. // are increasing in value. Here is an example of what we
  335. // expect to find.
  336. //
  337. // LongRun States (0-100) unique LongRun value
  338. //
  339. // 0-25 0
  340. // 26-50 40
  341. // 51-75 71
  342. // 76-100 100
  343. //
  344. if (stateInfo.LongRunValue != currentLongRunValue) {
  345. PACPI_PSS_DESCRIPTOR state;
  346. CRUSOE_PSS_VALUE longRunState = {0};
  347. DebugAssert(currentPerfState < MAX_LONGRUN_STATES);
  348. DebugAssert(stateInfo.LongRunValue <= MAX_LONGRUN_VALUE);
  349. state = &tmpPss->State[(MAX_LONGRUN_STATES-1) - currentPerfState];
  350. state->CoreFrequency = stateInfo.CpuSpeed;
  351. DebugAssert(stateInfo.Voltage < MAXUSHORT);
  352. state->Power = stateInfo.Voltage;
  353. state->Latency = CRUSOE_TRANSITION_LATENCY;
  354. longRunState.Max = stateInfo.LongRunValue;
  355. state->Control = longRunState.AsDWord;
  356. state->Status = longRunState.AsDWord;
  357. state->BmLatency = 0;
  358. //
  359. // If we have found all of the states, bail
  360. //
  361. if (currentPerfState == (MAX_LONGRUN_STATES-1)) {
  362. break;
  363. } else {
  364. currentLongRunValue = stateInfo.LongRunValue;
  365. currentPerfState++;
  366. }
  367. }
  368. }
  369. *PssPackage = tmpPss;
  370. BuildLongRunPerfStatesCMS41Exit:
  371. DebugExitStatus(status);
  372. return status;
  373. }
  374. NTSTATUS
  375. BuildLongRunPerfStatesCMS42(
  376. OUT PACPI_PSS_PACKAGE *PssPackage
  377. )
  378. /*++
  379. Routine Description:
  380. Arguments:
  381. Return Value:
  382. --*/
  383. {
  384. ULONG maxLevel;
  385. ULONG pssSize;
  386. ULONG x;
  387. NTSTATUS status = STATUS_SUCCESS;
  388. PACPI_PSS_PACKAGE tmpPss;
  389. DebugEnter();
  390. DebugAssert(PssPackage);
  391. //
  392. // Get max LongRun Level
  393. //
  394. maxLevel = LRTI_GetMaxSupportedLevel();
  395. pssSize = sizeof(ACPI_PSS_PACKAGE) + (maxLevel * sizeof(ACPI_PSS_DESCRIPTOR));
  396. tmpPss = ExAllocatePoolWithTag(NonPagedPool,
  397. pssSize,
  398. PROCESSOR_POOL_TAG);
  399. if (!tmpPss) {
  400. status = STATUS_INSUFFICIENT_RESOURCES;
  401. goto BuildLongRunPerfStatesCMS42Exit;
  402. }
  403. //
  404. // Iterate through each level collecting data.
  405. //
  406. DebugAssert(maxLevel < MAXUCHAR);
  407. tmpPss->NumPStates = (UCHAR) maxLevel+1;
  408. for (x=0; x <= maxLevel; x++) {
  409. PACPI_PSS_DESCRIPTOR state = &tmpPss->State[x];
  410. CRUSOE_PSS_VALUE longRunState;
  411. ULONG voltage;
  412. LRTI_SetCurrentLevel(x);
  413. state->CoreFrequency = LRTI_GetFrequency();
  414. voltage = LRTI_GetVoltage();
  415. DebugAssert(voltage < MAXUSHORT);
  416. state->Power = voltage;
  417. state->Latency = CRUSOE_TRANSITION_LATENCY;
  418. longRunState.Max = LRTI_GetPerformanceIndex();
  419. longRunState.Min = 0;
  420. state->Control = longRunState.AsDWord;
  421. state->Status = longRunState.AsDWord;
  422. state->BmLatency = 0;
  423. }
  424. *PssPackage = tmpPss;
  425. BuildLongRunPerfStatesCMS42Exit:
  426. DebugExitStatus(status);
  427. return status;
  428. }
  429. ULONG
  430. LRTI_GetMaxSupportedLevel(
  431. VOID
  432. )
  433. /*++
  434. Routine Description:
  435. Arguments:
  436. Return Value:
  437. --*/
  438. {
  439. ULARGE_INTEGER results;
  440. results.QuadPart = ReadMSR(LONGRUN_TI_READOUT_MSR);
  441. return results.HighPart;
  442. }
  443. VOID
  444. LRTI_SetCurrentLevel (
  445. ULONG LongRunLevel
  446. )
  447. /*++
  448. Routine Description:
  449. Arguments:
  450. Return Value:
  451. --*/
  452. {
  453. ULARGE_INTEGER msr;
  454. msr.LowPart = LongRunLevel;
  455. msr.HighPart = 0;
  456. WriteMSR(LONGRUN_TI_READOUT_MSR, msr.QuadPart);
  457. }
  458. ULONG
  459. LRTI_GetPerformanceIndex (
  460. VOID
  461. )
  462. /*++
  463. Routine Description:
  464. Arguments:
  465. Return Value:
  466. --*/
  467. {
  468. ULARGE_INTEGER msr;
  469. msr.QuadPart = ReadMSR(LONGRUN_TI_PERFORMANCE_INDEX_MSR);
  470. return msr.LowPart;
  471. }
  472. ULONG
  473. LRTI_GetVoltage (
  474. VOID
  475. )
  476. /*++
  477. Routine Description:
  478. Arguments:
  479. Return Value:
  480. --*/
  481. {
  482. ULARGE_INTEGER msr;
  483. msr.QuadPart = ReadMSR(LONGRUN_TI_VOLTAGE_FREQUENCY_MSR);
  484. return msr.HighPart;
  485. }
  486. ULONG
  487. LRTI_GetFrequency (
  488. VOID
  489. )
  490. /*++
  491. Routine Description:
  492. Arguments:
  493. Return Value:
  494. --*/
  495. {
  496. ULARGE_INTEGER msr;
  497. msr.QuadPart = ReadMSR(LONGRUN_TI_VOLTAGE_FREQUENCY_MSR);
  498. return msr.LowPart;
  499. }
  500. ULONG
  501. GetLongRunFlagsRegister (
  502. VOID
  503. )
  504. /*++
  505. Routine Description:
  506. Arguments:
  507. Return Value:
  508. --*/
  509. {
  510. ULARGE_INTEGER msr;
  511. msr.QuadPart = ReadMSR(LONGRUN_FLAGS_REGISTER_MSR);
  512. return msr.LowPart;
  513. }
  514. VOID
  515. SetLongRunEconomyMode (
  516. VOID
  517. )
  518. /*++
  519. Routine Description:
  520. Arguments:
  521. Return Value:
  522. --*/
  523. {
  524. ULARGE_INTEGER msr = {0};
  525. WriteMSR(LONGRUN_FLAGS_REGISTER_MSR, msr.QuadPart);
  526. }
  527. VOID
  528. SetLongRunPerformanceMode (
  529. VOID
  530. )
  531. /*++
  532. Routine Description:
  533. Arguments:
  534. Return Value:
  535. --*/
  536. {
  537. ULARGE_INTEGER msr = {0};
  538. msr.LowPart |= 0x1;
  539. WriteMSR(LONGRUN_FLAGS_REGISTER_MSR, msr.QuadPart);
  540. }
  541. #if DBG
  542. VOID
  543. DisplayStateInfo(
  544. IN PSTATE_INFO State
  545. )
  546. {
  547. DebugPrint((MAXTRACE, "State Info:\n"));
  548. DebugPrint((MAXTRACE, " Processor Clock Frequency: %u Mhz\n", State->CpuSpeed));
  549. DebugPrint((MAXTRACE, " Processor Core Voltage: %u millivolts\n", State->Voltage));
  550. DebugPrint((MAXTRACE, " LongRun Value [0-100]: %u\n", State->LongRunValue));
  551. DebugPrint((MAXTRACE, " Performance State: %u\n", ConvertLongRunValueToPerfState(
  552. &LongRunStates,
  553. State->LongRunValue)));
  554. DebugPrint((MAXTRACE, "\n"));
  555. }
  556. VOID
  557. DisplayLongRunStates(
  558. IN PLONGRUN_STATES States
  559. )
  560. {
  561. ULONG x;
  562. DebugPrint((MAXTRACE, "LongRun Performance Levels:\n"));
  563. for (x = 0; x < States->MaxState; x++) {
  564. DebugPrint((ERROR, "State %u:\n", x));
  565. DisplayStateInfo(&States->States[x]);
  566. }
  567. }
  568. #endif