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.

741 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. amdk6.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. Notes:
  12. DeviceInst = "ACPI\AuthenticAMD_-_x86_Family_5_Model_13"
  13. ServiceName = "amdk6"
  14. Revision History:
  15. --*/
  16. #include "amdk6.h"
  17. #include "..\lib\processor.h"
  18. #if DBG
  19. PUCHAR DebugName = "AmdK6.sys";
  20. #endif
  21. PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS];
  22. UCHAR DevExtIndex;
  23. extern GLOBALS Globals;
  24. extern LEGACY_GEMINI_SMI LegacyInterface;
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
  27. #pragma alloc_text (PAGE, InitializeAcpi2PStates)
  28. #pragma alloc_text (PAGE, InitializeAcpi2Cstates)
  29. #pragma alloc_text (PAGE, MergePerformanceStates)
  30. #endif
  31. NTSTATUS
  32. InitializeDriver(
  33. PUNICODE_STRING ServiceKeyRegPath
  34. )
  35. /*++
  36. Routine Description:
  37. Arguments:
  38. Return Value:
  39. --*/
  40. {
  41. return STATUS_SUCCESS;
  42. }
  43. NTSTATUS
  44. InitializeNonAcpiPerformanceStates(
  45. IN PFDO_DATA DeviceExtension
  46. )
  47. /*++
  48. Routine Description:
  49. This function tries to gather as much information as it can about what
  50. states are available. It puts a table in the device extension that
  51. describes the available states. Unfortunately, we might not have enough
  52. information to fill in the state table, as the BIOS doesn't tell us much.
  53. We try to run through all the states, figuring out what we can about them
  54. as we pass through them. But some states may not be available at the
  55. moment, particularly if we are running on DC power at the moment. So some
  56. states may have zeros in the table.
  57. Arguments:
  58. FdoData - pointer to the device extension
  59. Return Value:
  60. NT status code
  61. --*/
  62. {
  63. LARGE_INTEGER perfCounterOld, perfCounterNew;
  64. LARGE_INTEGER perfFreq, latency;
  65. ULONG newState, maxFreq, currentFreq;
  66. ULONG currentlatency, maxTransitionLatency = 0;
  67. ULONG perfStatesSize;
  68. UCHAR i;
  69. NTSTATUS status;
  70. PLEGACY_GEMINI_SMI info = &LegacyInterface;
  71. DebugEnter();
  72. PAGED_CODE();
  73. //
  74. // We automatically fail to use the Legacy Interface
  75. //
  76. if (Globals.HackFlags & DISABLE_LEGACY_INTERFACE_FLAG) {
  77. DebugPrint((ERROR, " Legacy Interface Disabled\n"));
  78. return STATUS_NOT_FOUND;
  79. }
  80. //
  81. // Find and gather legacy interface info
  82. //
  83. status = InitializeLegacyInterface();
  84. if (!NT_SUCCESS(status)) {
  85. DebugExitStatus(status);
  86. return status;
  87. }
  88. //
  89. // Found Legacy Interface, and is available to use.
  90. //
  91. DeviceExtension->LegacyInterface = TRUE;
  92. if (info->CurrentlyAvailableStates == 0) {
  93. status = STATUS_NOT_FOUND;
  94. DebugPrint((ERROR, " Found Legacy Interface, but no perfstates.\n"));
  95. DebugExitStatus(status);
  96. return status;
  97. }
  98. //
  99. // if there were already PerfStates, they were probably acpi 1.0 type
  100. // throttling, so we will blow them away, because they will be recreated
  101. // in MergePerformanceStates()
  102. //
  103. if (DeviceExtension->PerfStates) {
  104. ExFreePool(DeviceExtension->PerfStates);
  105. }
  106. perfStatesSize = sizeof(PROCESSOR_PERFORMANCE_STATES) +
  107. (sizeof(PROCESSOR_PERFORMANCE_STATE) *
  108. (info->CurrentlyAvailableStates - 1));
  109. DeviceExtension->PerfStates = ExAllocatePoolWithTag(PagedPool,
  110. perfStatesSize,
  111. PROCESSOR_POOL_TAG);
  112. if (!DeviceExtension->PerfStates) {
  113. status = STATUS_INSUFFICIENT_RESOURCES;
  114. goto InitalizeNonAcpiPerformanceStatesExit;
  115. }
  116. RtlZeroMemory(DeviceExtension->PerfStates, perfStatesSize);
  117. //
  118. // Jump through each state so that we can figure out how to fill in
  119. // the table. Start by jumping to the low state.
  120. //
  121. DebugPrint((INFO, "Perf States available: 0x%x Current State: 0x%x\n",
  122. info->CurrentlyAvailableStates,
  123. info->CurrentState));
  124. if (info->CurrentlyAvailableStates >= 1) {
  125. if (info->CurrentState != 0) {
  126. TRAP();
  127. //
  128. // Go to the highest state available
  129. //
  130. status = AcpiPerfStateTransition(DeviceExtension, 0);
  131. if (!NT_SUCCESS(status)) {
  132. goto InitalizeNonAcpiPerformanceStatesExit;
  133. }
  134. }
  135. maxFreq = GetMaxProcFrequency(DeviceExtension);
  136. DebugAssert(maxFreq != 0);
  137. //
  138. // Get Perf Counter Frequency
  139. //
  140. KeQueryPerformanceCounter(&perfFreq);
  141. for (i = 0; i < info->CurrentlyAvailableStates; i++) {
  142. newState = info->CurrentlyAvailableStates - i - 1;
  143. perfCounterOld = KeQueryPerformanceCounter(NULL);
  144. status = AcpiPerfStateTransition(DeviceExtension, newState);
  145. perfCounterNew = KeQueryPerformanceCounter(NULL);
  146. if (!NT_SUCCESS(status)) {
  147. goto InitalizeNonAcpiPerformanceStatesExit;
  148. }
  149. //
  150. // Calculate transition latency.
  151. //
  152. currentlatency = (ULONG)((perfCounterNew.QuadPart - perfCounterOld.QuadPart) *
  153. 1000000 / perfFreq.QuadPart);
  154. //
  155. // Save highest transition latency
  156. //
  157. maxTransitionLatency = MAX(maxTransitionLatency, currentlatency);
  158. DebugPrint((INFO, "Jumped to state 0x%x in %d microseconds\n",
  159. newState,
  160. currentlatency));
  161. //
  162. // Get current speed.
  163. //
  164. GetCpuFrequency(newState, &currentFreq);
  165. DebugAssert(currentFreq != 0);
  166. DeviceExtension->PerfStates->State[newState].Frequency = currentFreq;
  167. DeviceExtension->PerfStates->State[newState].PercentFrequency = (UCHAR)
  168. PERCENT_TO_PERF_LEVEL((currentFreq * 100) / maxFreq);
  169. //
  170. // Mark this as a Perf State
  171. //
  172. DeviceExtension->PerfStates->State[newState].Flags = PROCESSOR_STATE_TYPE_PERFORMANCE;
  173. }
  174. }
  175. DeviceExtension->PerfStates->TransitionLatency = maxTransitionLatency;
  176. DeviceExtension->PerfStates->TransitionFunction = SetPerfLevel;
  177. DeviceExtension->PerfStates->Count = (UCHAR) info->CurrentlyAvailableStates;
  178. DeviceExtension->LowestPerfState = info->CurrentlyAvailableStates - 1;
  179. //
  180. // Return to orginal perf state.
  181. //
  182. status = AcpiPerfStateTransition(DeviceExtension, info->CurrentState);
  183. if (!NT_SUCCESS(status)) {
  184. goto InitalizeNonAcpiPerformanceStatesExit;
  185. }
  186. //
  187. // Check to ensure that state 0 is higher than lowest perf state.
  188. //
  189. DebugAssert(DeviceExtension->PerfStates->State[0].Frequency >
  190. DeviceExtension->PerfStates->State[DeviceExtension->LowestPerfState].Frequency);
  191. //
  192. // Merge Perf states with other states we may have.
  193. //
  194. DumpProcessorPerfStates(DeviceExtension->PerfStates);
  195. status = MergePerformanceStates(DeviceExtension);
  196. InitalizeNonAcpiPerformanceStatesExit:
  197. if (!NT_SUCCESS(status)) {
  198. if (DeviceExtension->PerfStates) {
  199. ExFreePool(DeviceExtension->PerfStates);
  200. }
  201. DeviceExtension->PerfStates = NULL;
  202. DeviceExtension->LegacyInterface = FALSE;
  203. }
  204. DebugExitStatus(status);
  205. return status;
  206. }
  207. NTSTATUS
  208. AcpiLegacyPerfStateTransition(
  209. IN PFDO_DATA DeviceExtension,
  210. IN ULONG State
  211. )
  212. /*++
  213. Routine Description:
  214. Arguments:
  215. Return Value:
  216. --*/
  217. {
  218. //return SetCurrentStateSmm(State);
  219. return SetCurrentStateMSR(State);
  220. }
  221. NTSTATUS
  222. FASTCALL
  223. SetPerfLevel(
  224. IN UCHAR Throttle
  225. )
  226. /*++
  227. Routine Description:
  228. Arguments:
  229. Return Value:
  230. --*/
  231. {
  232. PFDO_DATA DeviceExtension;
  233. ULONG apicId;
  234. ULONG index = 0;
  235. DebugEnter();
  236. //
  237. // Get APIC Id and retrieve Device Extension index
  238. //
  239. if (!Globals.SingleProcessorProfile) {
  240. apicId = GetApicId();
  241. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  242. }
  243. //
  244. // Get the DeviceExtension.
  245. //
  246. DeviceExtension = DeviceExtensions[index];
  247. //
  248. // Since this driver does not support Functional Fixed Hardware, we
  249. // use generic method.
  250. //
  251. return SetPerfLevelGeneric(Throttle, DeviceExtension);
  252. }
  253. NTSTATUS
  254. FASTCALL
  255. SetThrottleLevel(
  256. IN UCHAR Throttle
  257. )
  258. /*++
  259. Routine Description:
  260. Arguments:
  261. Return Value:
  262. --*/
  263. {
  264. PFDO_DATA DeviceExtension;
  265. ULONG apicId;
  266. ULONG index = 0;
  267. DebugEnter();
  268. //
  269. // Get APIC Id and retrieve Device Extension index
  270. //
  271. if (!Globals.SingleProcessorProfile) {
  272. apicId = GetApicId();
  273. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  274. }
  275. //
  276. // Get the DeviceExtension.
  277. //
  278. DeviceExtension = DeviceExtensions[index];
  279. //
  280. // Since this driver does not support Functional Fixed Hardware, we
  281. // use generic method.
  282. //
  283. return SetThrottleLevelGeneric(Throttle, DeviceExtension);
  284. }
  285. NTSTATUS
  286. InitializeAcpi2PStates(
  287. IN PFDO_DATA DevExt
  288. )
  289. /*++
  290. Routine Description:
  291. Arguments:
  292. Return Value:
  293. --*/
  294. {
  295. NTSTATUS status;
  296. status = InitializeAcpi2PStatesGeneric(DevExt);
  297. //
  298. // Make sure we didn't find any NON I/O or MEM addresses
  299. //
  300. if (NT_SUCCESS(status)) {
  301. if (((DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceIO) ||
  302. (DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceMemory)) ||
  303. ((DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceIO) ||
  304. (DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceMemory))) {
  305. DebugPrint((WARN, "ONLY Memory & I/O _PCT addresses are supported\n"));
  306. DebugPrint((WARN, "NOT using Acpi 2.0 Performance States\n"));
  307. //
  308. // Undo what InitializeAcpi2PStatesGeneric() did
  309. //
  310. if (DevExt->PssPackage) {
  311. ExFreePool(DevExt->PssPackage);
  312. DevExt->PssPackage = NULL;
  313. }
  314. return STATUS_NOT_SUPPORTED;
  315. }
  316. //
  317. // Walk through _PSS states to calculate latency values
  318. //
  319. ValidatePssLatencyValues(DevExt);
  320. //
  321. // Need to merge this new data with our perfstates
  322. //
  323. MergePerformanceStates(DevExt);
  324. }
  325. return status;
  326. }
  327. NTSTATUS
  328. InitializeAcpi2Cstates(
  329. PFDO_DATA DevExt
  330. )
  331. /*++
  332. Routine Description:
  333. This function looks to see if there is an ACPI 2.0 _CST object in the
  334. namespace, and, if there is, it replaces the functions found by
  335. InitializeAcpi1Cstates.
  336. Further note: This function leaves the filling in of throttling functions
  337. to the InitializePerformanceStates functions.
  338. Arguments:
  339. DeviceExtension
  340. Return Value:
  341. A NTSTATUS code to indicate the result of the initialization.
  342. --*/
  343. {
  344. ULONG apicId;
  345. ULONG index = 0;
  346. DebugEnter();
  347. //
  348. // Record the address of this processor's DeviceExtension, as the
  349. // throttling API doesn't give it to us.
  350. //
  351. if (!Globals.SingleProcessorProfile) {
  352. //
  353. // save the index into the DeviceExtension[] for later retrieval based
  354. // on APIC Id.
  355. //
  356. apicId = Globals.ProcInfo.ProcIdToApicId[DevExt->ProcObjInfo.PhysicalID];
  357. Globals.ProcInfo.ApicIdToDevExtIndex[apicId] = DevExtIndex;
  358. index = DevExtIndex++;
  359. }
  360. //
  361. // save Device Extension pointer
  362. //
  363. DeviceExtensions[index] = DevExt;
  364. //
  365. // This processor driver only supports I/O Space based Cstates.
  366. // InitializeAcpi2IoSpaceCstates() will fail if it finds Cstates with
  367. // non AcpiGenericSpaceIO type addresses.
  368. //
  369. return InitializeAcpi2IoSpaceCstates(DevExt);
  370. }
  371. NTSTATUS
  372. MergePerformanceStates (
  373. IN PFDO_DATA DeviceExtension
  374. )
  375. /*++
  376. Routine Description:
  377. This routine looks at the performance states stored in the device extension.
  378. Arguments:
  379. DeviceExtension
  380. Return Value:
  381. A NTSTATUS code to indicate the result of the initialization.
  382. NOTE:
  383. - The caller must hold PerfStateLock.
  384. - This is called during START_DEVICE, and after recieving a Notify(0x80)
  385. on the processor.
  386. --*/
  387. {
  388. DebugEnter();
  389. //
  390. // Since this driver does not support Functional Fixed Hardware, we
  391. // use generic method.
  392. //
  393. return MergePerformanceStatesGeneric(DeviceExtension);
  394. }
  395. NTSTATUS
  396. Acpi2PerfStateTransition(
  397. IN PFDO_DATA DeviceExtension,
  398. IN ULONG State
  399. )
  400. /*++
  401. Routine Description:
  402. This routine changes the performance state of the processor
  403. based on ACPI 2.0 performance state objects.
  404. Arguments:
  405. State - Index into _PSS object
  406. Return Value:
  407. none
  408. --*/
  409. {
  410. //
  411. // Since this driver does not support Functional Fixed Hardware, we
  412. // use generic method.
  413. //
  414. return Acpi2PerfStateTransitionGeneric(DeviceExtension, State);
  415. }
  416. NTSTATUS
  417. ProcessResumeFromSleepState(
  418. SYSTEM_POWER_STATE PreviousState,
  419. PFDO_DATA DeviceExtension
  420. )
  421. /*++
  422. Routine Description:
  423. Arguments:
  424. Return Value:
  425. --*/
  426. {
  427. DebugEnter();
  428. //
  429. // if we are resuming from Hibernate, and this is an Acpi 2.0 system,
  430. // we must re-claim perf state and cstate control from the bios.
  431. //
  432. if (PreviousState == PowerSystemHibernate) {
  433. if (DeviceExtension->PssPackage) {
  434. AssumeProcessorPerformanceControl();
  435. }
  436. if (DeviceExtension->CstPresent) {
  437. AssumeCStateControl();
  438. }
  439. }
  440. //
  441. // Reinit the legacy interface
  442. //
  443. if (DeviceExtension->LegacyInterface) {
  444. EnableGeminiTransitionsMSR(&LegacyInterface.EpmIoAddress);
  445. }
  446. //
  447. // restore previous state
  448. //
  449. return RestoreToSavedPerformanceState(DeviceExtension);
  450. }
  451. NTSTATUS
  452. ProcessSuspendToSleepState(
  453. SYSTEM_POWER_STATE TargetState,
  454. PFDO_DATA DeviceExtension
  455. )
  456. /*++
  457. Routine Description:
  458. Arguments:
  459. Return Value:
  460. --*/
  461. {
  462. DebugEnter();
  463. //
  464. // save current state, transition to lowest non-throttled perf state
  465. //
  466. return SaveCurrentStateGoToLowVolts(DeviceExtension);
  467. }
  468. NTSTATUS
  469. GetProcessorBrandString (
  470. PUCHAR BrandString,
  471. PULONG Size
  472. )
  473. /*++
  474. Routine Description:
  475. Arguments:
  476. Return Value:
  477. --*/
  478. {
  479. //
  480. // This processor family supports CPUID Brand String
  481. //
  482. return GetCPUIDProcessorBrandString(BrandString, Size);
  483. }