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.

717 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. legacy.c
  5. Abstract:
  6. Author:
  7. Todd Carpenter (1/30/01) - create file
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #include "..\lib\processor.h"
  13. #include "amdk7.h"
  14. #include "legacy.h"
  15. #include "fidvid.h"
  16. PST_SIGNATURE SystemSignature;
  17. PPST_BLOCK_HEADER PstBlockHeader;
  18. extern ULONG AmdK7HackFlags;
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
  21. #pragma alloc_text (PAGE, GetLegacyMaxProcFrequency)
  22. #endif
  23. //
  24. // Legacy functions that must have a stub.
  25. //
  26. NTSTATUS
  27. InitializeNonAcpiPerformanceStates(
  28. IN PFDO_DATA DevExt
  29. )
  30. /*++
  31. Routine Description:
  32. The generic processor driver doesn't have non-ACPI performance states.
  33. Arguments:
  34. FdoData - pointer to the device extension
  35. Return Value:
  36. NT status code
  37. --*/
  38. {
  39. NTSTATUS status;
  40. PPST_ENTRY pstMatch;
  41. DebugEnter();
  42. //
  43. // Check hack flags to see if we should use the Legacy interface.
  44. //
  45. if (!(AmdK7HackFlags & ENABLE_LEGACY_INTERFACE)) {
  46. status = STATUS_NOT_SUPPORTED;
  47. goto InitializeNonAcpiPerformanceStatesExit;
  48. }
  49. //
  50. // Find the Perf States
  51. //
  52. status = FindPSTBlock(&PstBlockHeader);
  53. if (!NT_SUCCESS(status)) {
  54. DebugPrint((ERROR, "ERROR!! PST Block Header NOT found\n"));
  55. goto InitializeNonAcpiPerformanceStatesExit;
  56. }
  57. DumpPSTBlock(PstBlockHeader);
  58. //
  59. // Generate Signature to help find correct PST
  60. //
  61. status = CreateSystemSignature(&SystemSignature);
  62. DebugPrint((TRACE, "Dumping System Signature...\n"));
  63. DumpPSTSignature(&SystemSignature);
  64. if (!NT_SUCCESS(status)) {
  65. goto InitializeNonAcpiPerformanceStatesExit;
  66. }
  67. //
  68. // Walk through one or more PST entries to find the best match
  69. //
  70. status = FindMatchingPSTEntry(PstBlockHeader,
  71. &SystemSignature,
  72. &pstMatch);
  73. if (!NT_SUCCESS(status)) {
  74. DebugPrint((ERROR, "ERROR!! Couldn't find PST entry to match system signature\n"));
  75. goto InitializeNonAcpiPerformanceStatesExit;
  76. }
  77. DebugPrint((TRACE, "Dumping Matching Signature...\n"));
  78. DumpPSTEntry(pstMatch);
  79. DevExt->LegacyInterface = TRUE;
  80. //
  81. // Set up _PCT
  82. //
  83. DevExt->PctPackage.Control.AddressSpaceID = AcpiGenericSpaceFixedFunction;
  84. DevExt->PctPackage.Status.AddressSpaceID = AcpiGenericSpaceFixedFunction;
  85. //
  86. // Convert matching PST entry into _PSS package
  87. //
  88. status = ConvertPstToPss(DevExt, pstMatch, &DevExt->PssPackage);
  89. InitializeNonAcpiPerformanceStatesExit:
  90. if (!NT_SUCCESS(status)) {
  91. //
  92. // undo what we have done
  93. //
  94. if (PstBlockHeader) {
  95. ExFreePool(PstBlockHeader);
  96. PstBlockHeader = NULL;
  97. }
  98. if (DevExt->PssPackage) {
  99. ExFreePool(DevExt->PssPackage);
  100. DevExt->PssPackage = NULL;
  101. }
  102. DevExt->LegacyInterface = FALSE;
  103. }
  104. DebugExitStatus(status);
  105. return status;
  106. }
  107. NTSTATUS
  108. AcpiLegacyPerfStateTransition(
  109. IN PFDO_DATA DevExt,
  110. IN ULONG State
  111. )
  112. /*++
  113. Routine Description:
  114. The generic processor driver doesn't have non-ACPI performance states.
  115. Arguments:
  116. State - Target State
  117. Return Value:
  118. NT Status
  119. --*/
  120. {
  121. return Acpi2PerfStateTransition(DevExt, State + DevExt->PpcResult);
  122. }
  123. NTSTATUS
  124. GetLegacyMaxProcFrequency(
  125. OUT PULONG CpuSpeed
  126. )
  127. /*++
  128. Routine Description:
  129. Arguments:
  130. Return Value:
  131. --*/
  132. {
  133. FID_VID_STATUS fidVidStatus;
  134. DebugAssert(CpuSpeed);
  135. fidVidStatus.AsQWord = ReadMSR(AMDK7_FID_VID_STATUS_MSR);
  136. *CpuSpeed = FSB100FidToCpuFreq[fidVidStatus.MFid];
  137. return STATUS_SUCCESS;
  138. }
  139. NTSTATUS
  140. FindPSTBlock (
  141. OUT PPPST_BLOCK_HEADER PstBlock
  142. )
  143. /*++
  144. Description:
  145. This routine looks in the BIOS memory area for the PST Block Header. The
  146. signature will be located on a 16-byte bountry in the area from C0000h to FFFF0h.
  147. Arguments:
  148. Return Value:
  149. NTSTATUS
  150. --*/
  151. {
  152. NTSTATUS status = STATUS_UNSUCCESSFUL;
  153. ULONG size = 0;
  154. PVOID baseAddress;
  155. ULONG_PTR address;
  156. ULONG_PTR limit;
  157. PHYSICAL_ADDRESS PhysAddress;
  158. DebugEnter();
  159. DebugAssert(PstBlock);
  160. PAGED_CODE();
  161. PhysAddress.HighPart = 0;
  162. PhysAddress.LowPart = PST_SEARCH_RANGE_BEGIN;
  163. //
  164. // Map memory to search for PST Table
  165. //
  166. baseAddress = MmMapIoSpace(PhysAddress, PST_SEARCH_RANGE_LENGTH, 0);
  167. if (!baseAddress) {
  168. status = STATUS_INSUFFICIENT_RESOURCES;
  169. goto FindPSTBlockExit;
  170. }
  171. //
  172. // Compute limit for the for loop. Do not start a scan within 16 bytes of
  173. // physical address 0xFFFFF
  174. //
  175. address = (ULONG_PTR) baseAddress;
  176. limit = address + PST_SEARCH_RANGE_LENGTH - PST_SEARCH_INTERVAL;
  177. for (; address <= limit; address += PST_SEARCH_INTERVAL) {
  178. if (*(PULONG)address == PST_BLOCK_SIGNATURE &&
  179. (!memcmp(((PPST_BLOCK_HEADER)address)->Signature,
  180. PST_BLOCK_SIGNATURE_STRING,
  181. PST_BLOCK_SIGNATURE_STRING_LEN))) {
  182. DebugPrint((TRACE, "Found PST Header Block at %p\n", address));
  183. //
  184. // We found the PST Block Header, copy it.
  185. //
  186. size = GetPSTSize((PPST_BLOCK_HEADER)address);
  187. *PstBlock = ExAllocatePoolWithTag(PagedPool,
  188. size,
  189. PROCESSOR_POOL_TAG);
  190. if (!(*PstBlock)) {
  191. status = STATUS_INSUFFICIENT_RESOURCES;
  192. goto FindPSTBlockExit;
  193. }
  194. RtlCopyMemory(*PstBlock, (PVOID)address, size);
  195. status = STATUS_SUCCESS;
  196. break;
  197. }
  198. }
  199. FindPSTBlockExit:
  200. //
  201. // Unmap mapped memory
  202. //
  203. if (baseAddress) {
  204. MmUnmapIoSpace(baseAddress, PST_SEARCH_RANGE_LENGTH);
  205. }
  206. DebugExitStatus(status);
  207. return status;
  208. }
  209. NTSTATUS
  210. FindMatchingPSTEntry(
  211. IN PPST_BLOCK_HEADER PstBlock,
  212. IN PPST_SIGNATURE Signature,
  213. OUT PPPST_ENTRY PstStates
  214. )
  215. /*++
  216. Routine Description:
  217. Arguments:
  218. Return Value:
  219. --*/
  220. {
  221. NTSTATUS status = STATUS_UNSUCCESSFUL;
  222. ULONG x, y;
  223. PPST_ENTRY pstEntry;
  224. //DebugEnter();
  225. DebugAssert(PstBlock);
  226. DebugAssert(Signature);
  227. DebugAssert(PstStates);
  228. //
  229. // Walk PST Block looking for matching PST Signature.
  230. //
  231. //
  232. // Get First PST Entry
  233. //
  234. pstEntry = &PstBlock->PstState;
  235. for (x=0; x < PstBlock->NumPST; x++) {
  236. if ((pstEntry->CpuId == Signature->CpuId) &&
  237. (pstEntry->FSBSpeed == Signature->FSBSpeed) &&
  238. (pstEntry->MaxFid == Signature->MaxFid) &&
  239. (pstEntry->StartVid == Signature->StartVid)) {
  240. //
  241. // Found Match, we assume there should only be one match, but
  242. // if there are more, we take the first one.
  243. //
  244. *PstStates = pstEntry;
  245. status = STATUS_SUCCESS;
  246. break;
  247. }
  248. //
  249. // Get Next PST State
  250. //
  251. pstEntry = (PPST_ENTRY)((PUCHAR)pstEntry + sizeof(PST_ENTRY) +
  252. (sizeof(PST_DATA) * (pstEntry->NumPStates - 1)));
  253. }
  254. return status;
  255. }
  256. NTSTATUS
  257. CreateSystemSignature(
  258. PPST_SIGNATURE Signature
  259. )
  260. /*++
  261. Routine Description:
  262. Arguments:
  263. Return Value:
  264. --*/
  265. {
  266. NTSTATUS status;
  267. ULONG junk;
  268. FID_VID_STATUS fidVidStatus;
  269. //DebugEnter();
  270. DebugAssert(Signature);
  271. PAGED_CODE();
  272. //
  273. // Gather info needed to select the correct PST for this processor.
  274. //
  275. //
  276. // Get special CPUID using extended CPUID fuction 1
  277. //
  278. CPUID(0x80000001, &Signature->CpuId, &junk, &junk, &junk);
  279. //
  280. // Get MAX Fid & Startup VID
  281. //
  282. fidVidStatus.AsQWord = ReadMSR(AMDK7_FID_VID_STATUS_MSR);
  283. Signature->MaxFid = (UCHAR) fidVidStatus.MFid;
  284. Signature->StartVid = (UCHAR) fidVidStatus.SVid;
  285. //
  286. // Get Front Side Bus speed
  287. //
  288. Signature->FSBSpeed = GetFSBSpeed();
  289. DebugAssert(Signature->FSBSpeed);
  290. return STATUS_SUCCESS;
  291. }
  292. UCHAR
  293. GetFSBSpeed(
  294. VOID
  295. )
  296. /*++
  297. Routine Description:
  298. Arguments:
  299. Return Value:
  300. --*/
  301. {
  302. UCHAR speed;
  303. PAGED_CODE();
  304. //
  305. // FSB Speed == CPU frequency / FSB multiplier
  306. //
  307. // toddcar - 4/30/01 - ISSUE:
  308. // Need to finish support for 133mhz
  309. //
  310. speed = 100;
  311. return speed;
  312. }
  313. NTSTATUS
  314. ConvertPstToPss (
  315. IN PFDO_DATA DevExt,
  316. IN PPST_ENTRY PstEntry,
  317. OUT PACPI_PSS_PACKAGE *PssPackage
  318. )
  319. /*++
  320. Routine Description:
  321. Arguments:
  322. Return Value:
  323. --*/
  324. {
  325. NTSTATUS status = STATUS_SUCCESS;
  326. ULONG pssSize;
  327. ULONG x;
  328. ULONG currentState;
  329. PACPI_PSS_PACKAGE tmpPss;
  330. DebugEnter();
  331. DebugAssert(PstEntry);
  332. DebugAssert(PssPackage);
  333. PAGED_CODE();
  334. //
  335. // Allocate a chunk for PssPackage
  336. //
  337. pssSize = (sizeof(ACPI_PSS_DESCRIPTOR) * (PstEntry->NumPStates - 1)) +
  338. sizeof(ACPI_PSS_PACKAGE);
  339. tmpPss = ExAllocatePoolWithTag(NonPagedPool,
  340. pssSize,
  341. PROCESSOR_POOL_TAG);
  342. if (!tmpPss) {
  343. status = STATUS_INSUFFICIENT_RESOURCES;
  344. goto ConvertPstToPssExit;
  345. }
  346. RtlZeroMemory(tmpPss, pssSize);
  347. tmpPss->NumPStates = PstEntry->NumPStates;
  348. //
  349. // Build a _PSS table
  350. //
  351. for (x = 0; x < PstEntry->NumPStates; x++) {
  352. PSS_CONTROL pssControl = {0};
  353. PSS_STATUS pssStatus = {0};
  354. ULONG pssState = (PstEntry->NumPStates - 1) - x;
  355. pssControl.Fid = pssStatus.Fid = PstEntry->States[x].Fid;
  356. pssControl.Vid = pssStatus.Vid = PstEntry->States[x].Vid;
  357. pssControl.SGTC = PstEntry->FSBSpeed * 100; // need to finish support for 133mhz bus
  358. tmpPss->State[pssState].Control = pssControl.AsDWord;
  359. tmpPss->State[pssState].Status = pssStatus.AsDWord;
  360. DebugAssert(pssControl.Fid < INVALID_FID_VALUE);
  361. tmpPss->State[pssState].CoreFrequency = FSB100FidToCpuFreq[pssControl.Fid];
  362. DebugAssert(pssControl.Vid < INVALID_VID_VALUE);
  363. tmpPss->State[pssState].Power = MobileVidToCpuVoltage[pssControl.Vid];
  364. }
  365. //
  366. // Walk through each state collecting more information
  367. //
  368. status = FindCurrentPssPerfState(tmpPss, &currentState);
  369. if (!NT_SUCCESS(status)) {
  370. goto ConvertPstToPssExit;
  371. }
  372. DevExt->CurrentPssState = currentState;
  373. DevExt->PssPackage = tmpPss;
  374. //
  375. // Set Latency Info
  376. //
  377. status = ValidatePssLatencyValues(DevExt);
  378. //
  379. // Restore saved state
  380. //
  381. if (DevExt->CurrentPssState != currentState) {
  382. Acpi2PerfStateTransition(DevExt, currentState);
  383. }
  384. //
  385. // Need to merge this new data with our perfstates
  386. //
  387. MergePerformanceStates(DevExt);
  388. ConvertPstToPssExit:
  389. if (!NT_SUCCESS(status)) {
  390. if (DevExt->PssPackage) {
  391. ExFreePool(DevExt->PssPackage);
  392. DevExt->PssPackage = NULL;
  393. }
  394. }
  395. DebugExitStatus(status);
  396. return status;
  397. }
  398. ULONG
  399. GetPSTSize(
  400. IN PPST_BLOCK_HEADER PstBlock
  401. )
  402. /*++
  403. Routine Description:
  404. Arguments:
  405. Return Value:
  406. --*/
  407. {
  408. ULONG size;
  409. ULONG x;
  410. PPST_ENTRY pstEntry;
  411. DebugAssert(PstBlock);
  412. size = sizeof(PST_BLOCK_HEADER); // include block header, and one pst entry
  413. size += sizeof(PST_ENTRY) * (PstBlock->NumPST - 1);
  414. pstEntry = &PstBlock->PstState;
  415. for (x=0; x < PstBlock->NumPST; x++) {
  416. size += sizeof(PST_DATA) * (pstEntry->NumPStates-1);
  417. pstEntry = (PPST_ENTRY)((PUCHAR)pstEntry + sizeof(PST_ENTRY) +
  418. (sizeof(PST_DATA) * (pstEntry->NumPStates - 1)));
  419. }
  420. return size;
  421. }
  422. #if DBG
  423. VOID
  424. DumpPSTBlock(
  425. PPST_BLOCK_HEADER PstBlock
  426. )
  427. {
  428. ULONG x, y;
  429. PPST_ENTRY pstEntry;
  430. DebugAssert(PstBlock);
  431. DebugPrint((TRACE, "\n"));
  432. DebugPrint((TRACE, "PstBlock:\n"));
  433. DebugPrint((TRACE, " Signature: %.10s\n", PstBlock->Signature));
  434. DebugPrint((TRACE, " TableVersion: %u\n", PstBlock->TableVersion));
  435. DebugPrint((TRACE, " Flags: 0x%x\n", PstBlock->Flags));
  436. DebugPrint((TRACE, " SettlingTime: %u us\n", PstBlock->SettlingTime));
  437. DebugPrint((TRACE, " Reserved1: 0x0\n", PstBlock->Reserved1));
  438. DebugPrint((TRACE, " NumPST: %u\n", PstBlock->NumPST));
  439. DebugPrint((TRACE, "\n"));
  440. //
  441. // Get First PST Entry
  442. //
  443. pstEntry = &PstBlock->PstState;
  444. for (x=0; x < PstBlock->NumPST; x++) {
  445. DumpPSTEntry(pstEntry);
  446. //
  447. // Get Next PST State
  448. //
  449. pstEntry = (PPST_ENTRY)((PUCHAR)pstEntry + sizeof(PST_ENTRY) +
  450. (sizeof(PST_DATA) * (pstEntry->NumPStates - 1)));
  451. }
  452. }
  453. VOID
  454. DumpPSTEntry(
  455. PPST_ENTRY PstEntry
  456. )
  457. {
  458. ULONG y;
  459. DebugPrint((TRACE, "PST Entry:\n"));
  460. DebugPrint((TRACE, " CpuId: 0x%x\n", PstEntry->CpuId));
  461. DebugPrint((TRACE, " FSBSpeed: %u mhz\n", PstEntry->FSBSpeed));
  462. DebugPrint((TRACE, " MaxFid: 0x%x\n", PstEntry->MaxFid));
  463. DebugPrint((TRACE, " StartVid: 0x%x\n", PstEntry->StartVid));
  464. DebugPrint((TRACE, " NumPStates %u\n", PstEntry->NumPStates));
  465. for (y=0; y < PstEntry->NumPStates; y++) {
  466. DebugPrint((TRACE, " State #%u (Fid: 0x%x, Vid: 0x%x)\n",
  467. y,
  468. PstEntry->States[y].Fid,
  469. PstEntry->States[y].Vid));
  470. }
  471. DebugPrint((TRACE, "\n"));
  472. }
  473. VOID
  474. DumpPSTSignature(
  475. PPST_SIGNATURE PstSig
  476. )
  477. {
  478. DebugPrint((TRACE, "PST Signature:\n"));
  479. DebugPrint((TRACE, " CpuId: 0x%x\n", PstSig->CpuId));
  480. DebugPrint((TRACE, " FSBSpeed: %u mhz\n", PstSig->FSBSpeed));
  481. DebugPrint((TRACE, " MaxFid: 0x%x\n", PstSig->MaxFid));
  482. DebugPrint((TRACE, " StartVid: 0x%x\n", PstSig->StartVid));
  483. DebugPrint((TRACE, "\n"));
  484. }
  485. #endif