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.

1082 lines
21 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. bios.c
  5. Abstract:
  6. This module implements code to make BIOS calls
  7. Author:
  8. Jake Oshins (3/18/00) - create file
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include <ntddk.h>
  15. #include "p3.h"
  16. #include "ntacpi.h"
  17. extern P3_GLOBALS P3_Globals;
  18. extern PROCESSOR_STATE_INFO Coppermine100[];
  19. extern PROCESSOR_STATE_INFO Coppermine133[];
  20. extern PROCESSOR_STATE_INFO Tualatin100[];
  21. extern PROCESSOR_STATE_INFO Tualatin133[];
  22. ULONG StateFlags;
  23. PPROCESSOR_STATE_INFO ProcessorStateInfo;
  24. LEGACY_GEYSERVILLE_INT15 LegacyInterface;
  25. const CHAR SignatureString[] = "Copyright (c) 1999 Intel Corporation";
  26. NTSTATUS
  27. AcpiFindRsdt (
  28. OUT PACPI_BIOS_MULTI_NODE *AcpiMulti
  29. );
  30. __inline
  31. ULONG
  32. GetBusRatio (
  33. VOID
  34. );
  35. __inline
  36. BOOLEAN
  37. Is133MhzBus (
  38. VOID
  39. );
  40. NTSTATUS
  41. GetMaxProcFrequencySMM (
  42. PULONG MaxSpeed
  43. );
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text (PAGE, InitializeLegacyInterface)
  46. #pragma alloc_text (PAGE, FindLegacyGeyservilleInterface)
  47. #pragma alloc_text (PAGE, GetMaxProcFrequencySMM)
  48. #pragma alloc_text (PAGE, GetCurrentStateSmm)
  49. #pragma alloc_text (PAGE, SetCurrentSetupSmm)
  50. #pragma alloc_text (PAGE, GetCurrentProcFrequency)
  51. #pragma alloc_text (PAGE, GetBusRatio)
  52. #pragma alloc_text (PAGE, GetLegacyMaxProcFrequency)
  53. #pragma alloc_text (PAGE, CollectProcessorInfomation)
  54. #endif
  55. NTSTATUS
  56. InitializeLegacyInterface (
  57. PLEGACY_GEYSERVILLE_INTERFACE_INFO Info,
  58. PFDO_DATA DeviceExtension
  59. )
  60. /*++
  61. Description:
  62. Arguments:
  63. Return Value:
  64. NTSTATUS
  65. --*/
  66. {
  67. NTSTATUS status;
  68. ULONG currentState;
  69. ULONG smiCmdData = 0;
  70. ULONG smiCmdPort = 0;
  71. DebugEnter();
  72. PAGED_CODE();
  73. //
  74. // Must be a Geyserville processor
  75. //
  76. status = CollectProcessorInfomation();
  77. if (!NT_SUCCESS(status)) {
  78. goto InitializeLegacyInterfaceExit;
  79. }
  80. DumpStateFlags(StateFlags);
  81. DebugPrint((MAXTRACE, "Bus Ratio == %u\n", GetBusRatio()));
  82. DebugPrint((MAXTRACE, "Ist Field == %u\n", P3_Globals.IstField));
  83. //
  84. // Check for Legacy Geyserville Interface override values.
  85. //
  86. GetRegistryDwordValue(P3_PARAMETERS_KEY,
  87. L"SmiCmdPort",
  88. &smiCmdPort);
  89. GetRegistryDwordValue(P3_PARAMETERS_KEY,
  90. L"SmiCmdData",
  91. &smiCmdData);
  92. //
  93. // NOTE: if we have the SmiCmdData value but not the SmiCmdPort value, we
  94. // could grab the SmiCmdPort value from HalpFixedAcpiDescTable->smi_cmd_io_port
  95. //
  96. //
  97. // If we already have both the SmiCmdPort and the SmiCmdData,
  98. // then we already have the data we need, otherwise copy INT 15 E820
  99. // data to LegacyInterface structure...
  100. //
  101. if (!(smiCmdPort && smiCmdData)) {
  102. status = FindLegacyGeyservilleInterface();
  103. if (!NT_SUCCESS(status)) {
  104. goto InitializeLegacyInterfaceExit;
  105. }
  106. }
  107. if (smiCmdPort) {
  108. LegacyInterface.CommandPortAddress = (UCHAR) smiCmdPort;
  109. DebugPrint((INFO, " Overriding SmiCommandPortAddress with registry value 0x%x\n",
  110. smiCmdPort));
  111. }
  112. if (smiCmdData) {
  113. LegacyInterface.CommandDataValue = (UCHAR) smiCmdData;
  114. DebugPrint((INFO, " Overriding SmiCommandDataVale with registry value 0x%x\n",
  115. smiCmdData));
  116. }
  117. //
  118. // Set the Default Behavior for AC and DC
  119. //
  120. P3_Globals.MaxLevelAc = 0;
  121. P3_Globals.MaxLevelDc = 1;
  122. //
  123. // Check for INT 15 or Registy Flag overrides
  124. //
  125. if (LegacyInterface.Signature == 'GS') {
  126. //
  127. // If the values returned from the INT 15 Interface look
  128. // reasonable, use them, other wise we'll use the defaults.
  129. //
  130. if (LegacyInterface.MaxLevelAc < MAX_GEYSERVILLE_STATES) {
  131. P3_Globals.MaxLevelAc = LegacyInterface.MaxLevelAc;
  132. }
  133. if (LegacyInterface.MaxLevelDc < MAX_GEYSERVILLE_STATES) {
  134. P3_Globals.MaxLevelDc = LegacyInterface.MaxLevelDc;
  135. }
  136. //
  137. // sanity check, some machines report this info incorrectly.
  138. //
  139. if (P3_Globals.MaxLevelAc > P3_Globals.MaxLevelDc) {
  140. P3_Globals.MaxLevelAc = P3_Globals.MaxLevelDc;
  141. }
  142. }
  143. if (P3_Globals.HackFlags & ENABLE_HIGH_SPEED_ON_BATTERY) {
  144. P3_Globals.MaxLevelDc = 0;
  145. DeviceExtension->PpcResult = 0;
  146. }
  147. //
  148. // Init the SMI Interface
  149. //
  150. status = InitializeSmmInterface();
  151. if (!NT_SUCCESS(status)) {
  152. //
  153. // found INT 15 interface or registry override values,
  154. // but were unable to Initialize SMM Interface, log error
  155. //
  156. QueueEventLogWrite(DeviceExtension,
  157. PROCESSOR_LEGACY_INTERFACE_FAILURE,
  158. 0);
  159. goto InitializeLegacyInterfaceExit;
  160. }
  161. //
  162. // Find out more about what state we're in and what
  163. // states we can use.
  164. //
  165. status = GetCurrentStateSmm(Info);
  166. InitializeLegacyInterfaceExit:
  167. DebugExitStatus(status);
  168. return status;
  169. }
  170. NTSTATUS
  171. FindLegacyGeyservilleInterface (
  172. VOID
  173. )
  174. /*++
  175. Routine Description:
  176. This routine looks in the registry to find out if Geyserville
  177. is supported on this system via Intel's SMI interface. If
  178. so it collects information about how to use the interface.
  179. Arguments:
  180. Return Value:
  181. NTSTATUS
  182. --*/
  183. {
  184. PACPI_BIOS_MULTI_NODE multiNode;
  185. PLEGACY_GEYSERVILLE_INT15 int15Info;
  186. NTSTATUS status;
  187. DebugEnter();
  188. PAGED_CODE();
  189. status = AcpiFindRsdt(&multiNode);
  190. if (!NT_SUCCESS(status)) {
  191. goto FindLegacyGeyservilleInterfaceExit;
  192. }
  193. //
  194. // Geyserville BIOS information is appended to the E820 entries.
  195. //
  196. int15Info = (PLEGACY_GEYSERVILLE_INT15)&(multiNode->E820Entry[multiNode->Count]);
  197. if (int15Info->Signature == 'GS') {
  198. //
  199. // This BIOS supports Geyserville.
  200. //
  201. RtlCopyMemory(&LegacyInterface,
  202. int15Info,
  203. sizeof(LEGACY_GEYSERVILLE_INT15));
  204. status = STATUS_SUCCESS;
  205. } else {
  206. status = STATUS_NOT_FOUND;
  207. }
  208. ExFreePool(multiNode);
  209. FindLegacyGeyservilleInterfaceExit:
  210. DebugExitStatus(status);
  211. return status;
  212. }
  213. NTSTATUS
  214. InitializeSmmInterface (
  215. VOID
  216. )
  217. /*++
  218. Routine Description:
  219. This routine makes the first Geyserville SMI, enabling
  220. the other functions.
  221. Arguments:
  222. Return Value:
  223. NTSTATUS
  224. --*/
  225. {
  226. ULONG regEax, regEbx, regEdx, returnCode;
  227. PHYSICAL_ADDRESS signatureAddr;
  228. //
  229. // Enable Geyserville SMM.
  230. //
  231. regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
  232. regEbx = GeyservilleControl;
  233. regEdx = LegacyInterface.CommandPortAddress;
  234. signatureAddr = MmGetPhysicalAddress((PVOID)SignatureString);
  235. ASSERT(signatureAddr.QuadPart);
  236. _asm {
  237. mov edx, regEdx
  238. mov eax, regEax
  239. mov ebx, regEbx
  240. mov ecx, GeyservilleControlEnableApp
  241. mov esi, signatureAddr.LowPart
  242. xor edi, edi
  243. out dx, al
  244. mov returnCode, edi
  245. }
  246. if (returnCode == GeyservilleControlSuccessful) {
  247. return STATUS_SUCCESS;
  248. } else {
  249. DebugPrint((ERROR, "InitializeSmmInterface() Failed! rc=0x%x\n", returnCode));
  250. return STATUS_UNSUCCESSFUL;
  251. }
  252. }
  253. NTSTATUS
  254. GetMaxProcFrequencySMM (
  255. PULONG MaxSpeed
  256. )
  257. /*++
  258. Routine Description:
  259. This routine determines the maximun speed of the processor.
  260. Arguments:
  261. MaxSpeed - returned information
  262. Return Value:
  263. NTSTATUS
  264. --*/
  265. {
  266. LEGACY_GEYSERVILLE_INTERFACE_INFO info;
  267. NTSTATUS status;
  268. ULONG cpuSpeed;
  269. ULONG msrResult;
  270. ULONG busRatio;
  271. DebugEnter();
  272. PAGED_CODE();
  273. status = GetCurrentStateSmm(&info);
  274. if (!NT_SUCCESS(status)) {
  275. goto GetMaxProcFrequencySMMExit;
  276. }
  277. //
  278. // If we are in state 0, then just get current speed
  279. //
  280. // If we are in state 1:
  281. // get current state's bin value
  282. // add bin delta value
  283. // convert bin value to Cpu Speed
  284. //
  285. //
  286. // High Volts
  287. //
  288. if (info.CurrentState == 0) {
  289. GetCurrentProcFrequency(0, &cpuSpeed);
  290. } else {
  291. ULONG binValue;
  292. ULONG newBinValue;
  293. ULONG index;
  294. //
  295. // Low Volts
  296. //
  297. DebugAssert(info.CurrentState == 1);
  298. //
  299. // Get Current Bin Value
  300. //
  301. busRatio = GetBusRatio();
  302. DebugPrint((MAXTRACE, "BusRatio == %u\n", busRatio));
  303. //
  304. // An error has occurred
  305. //
  306. if (busRatio >= PROC_STATE_INFO_SIZE) {
  307. DebugPrint((ERROR, "BusRatio invalid value = 0x%x\n", busRatio));
  308. DebugAssert(busRatio >= PROC_STATE_INFO_SIZE);
  309. return STATUS_UNSUCCESSFUL;
  310. }
  311. binValue = ProcessorStateInfo[busRatio].BinValue;
  312. DebugPrint((MAXTRACE, "BinValue == %u\n", binValue));
  313. newBinValue = binValue + P3_Globals.IstField;
  314. DebugPrint((MAXTRACE, "IstField == %u\n", P3_Globals.IstField));
  315. DebugPrint((MAXTRACE, "New BinValue == %u\n", newBinValue));
  316. cpuSpeed = FindCpuSpeedByBinValue(newBinValue, ProcessorStateInfo);
  317. DebugPrint((MAXTRACE, "Current CpuSpeed == %u\n", ProcessorStateInfo[busRatio].Frequency));
  318. DebugPrint((MAXTRACE, "Max CpuSpeed == %u\n", cpuSpeed));
  319. }
  320. if (ARGUMENT_PRESENT(MaxSpeed)) {
  321. DebugPrint((TRACE, "GetMaxProcFrequencySMM() returning %u Mhz\n", cpuSpeed));
  322. *MaxSpeed = cpuSpeed;
  323. }
  324. GetMaxProcFrequencySMMExit:
  325. DebugExitStatus(status);
  326. return status;
  327. }
  328. NTSTATUS
  329. GetCurrentStateSmm (
  330. PLEGACY_GEYSERVILLE_INTERFACE_INFO Info
  331. )
  332. /*++
  333. Routine Description:
  334. This routine determines the current processor state.
  335. Arguments:
  336. Info - returned information
  337. Return Value:
  338. NTSTATUS
  339. --*/
  340. {
  341. ULONG regEax, regEbx, regEdx;
  342. ULONG returnCode, currentState, interfaceInfo;
  343. PAGED_CODE();
  344. ASSERT(Info);
  345. //
  346. // GetGeyservilleStatus
  347. //
  348. regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
  349. regEbx = GetGeyservilleStatus;
  350. regEdx = LegacyInterface.CommandPortAddress;
  351. _asm {
  352. mov edx, regEdx
  353. mov eax, regEax
  354. mov ebx, regEbx
  355. xor esi, esi
  356. xor edi, edi
  357. out dx, al
  358. mov interfaceInfo, esi
  359. mov returnCode, edi
  360. mov currentState, ebx
  361. }
  362. //
  363. // Suck up the return values.
  364. //
  365. Info->CurrentState = currentState;
  366. Info->InterfaceMajorRev = (UCHAR)(interfaceInfo >> 24);
  367. Info->InterfaceMinorRev = (USHORT)((interfaceInfo >> 8) & 0xffff);
  368. Info->InterfaceReserved = (UCHAR)(interfaceInfo & 0xff);
  369. Info->MaxSupportedStates = (UCHAR)(returnCode >> 24);
  370. Info->CurrentlyAvailableStates = (UCHAR)((returnCode >> 16) & 0xff);
  371. Info->CurrentBiosSettings = (UCHAR)(returnCode & 0xff);
  372. return STATUS_SUCCESS;
  373. }
  374. NTSTATUS
  375. SetCurrentStateSmm (
  376. ULONG NewState
  377. )
  378. /*++
  379. Routine Description:
  380. This routine sets the current processor state.
  381. Arguments:
  382. NewState - target state
  383. Return Value:
  384. STATUS_SUCCESS - new state currently in use
  385. STATUS_NOT_FOUND - new state unreachable
  386. STATUS_RETRY - new state reachable, but this transition didn't work
  387. STATUS_UNSUCCESSFUL - hard error
  388. --*/
  389. {
  390. ULONG regEax, regEbx, regEdx;
  391. ULONG returnCode, currentState;
  392. static ULONG errorCount;
  393. if (NewState > 1) {
  394. DebugAssert((NewState == 0) || (NewState == 1));
  395. return STATUS_INVALID_PARAMETER;
  396. }
  397. //
  398. // SetGeyservilleState
  399. //
  400. regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
  401. regEbx = SetGeyservilleState;
  402. regEdx = LegacyInterface.CommandPortAddress;
  403. _asm {
  404. mov edx, regEdx
  405. mov eax, regEax
  406. mov ebx, regEbx
  407. mov ecx, NewState
  408. xor edi, edi
  409. out dx, al
  410. mov returnCode, edi
  411. mov currentState, ebx
  412. }
  413. switch (returnCode) {
  414. case GeyservilleSetSuccessful:
  415. if (currentState != NewState) {
  416. DebugPrint((ERROR, "SetCurrentStateSmm(%u): BIOS ERROR: SMI returned"
  417. " success with invalid current SpeedStep state = %u\n",
  418. NewState,
  419. currentState));
  420. DebugAssert(currentState != NewState);
  421. return STATUS_INVALID_DEVICE_STATE;
  422. }
  423. return STATUS_SUCCESS;
  424. case GeyservilleStateUnavailable:
  425. return STATUS_NOT_FOUND;
  426. case GeyservilleUnsuccessfulTransition:
  427. return STATUS_RETRY;
  428. case GeyservilleAbortCritical:
  429. return STATUS_CANCELLED;
  430. case GeyservilleSetUnknownError:
  431. //DebugPrint((ERROR, "SetCurrentStateSmm() rc=GeyservilleSetUnknownError\n"));
  432. return STATUS_UNSUCCESSFUL;
  433. case GeyservilleTransitionUnavailable:
  434. return STATUS_PERF_TRANSITIONS_UNAVAILABLE;
  435. default:
  436. //DebugPrint((ERROR, "SetCurrentStateSmm() Unknown return code 0x%x\n", returnCode));
  437. return STATUS_UNSUCCESSFUL;
  438. }
  439. }
  440. NTSTATUS
  441. SetCurrentSetupSmm (
  442. IN ULONG NewState
  443. )
  444. /*++
  445. Description:
  446. Arguments:
  447. Return Value:
  448. NTSTATUS
  449. --*/
  450. {
  451. ULONG regEax, regEbx, regEdx;
  452. ULONG returnCode;
  453. PAGED_CODE();
  454. TRAP();
  455. //
  456. // SetGeyservilleSetup
  457. //
  458. regEax = ('GSI' << 8) | LegacyInterface.CommandDataValue;
  459. regEbx = SetGeyservilleSetup;
  460. regEdx = LegacyInterface.CommandPortAddress;
  461. _asm {
  462. mov edx, regEdx
  463. mov eax, regEax
  464. mov ebx, regEbx
  465. mov ecx, NewState
  466. xor edi, edi
  467. out dx, al
  468. mov returnCode, edi
  469. }
  470. if (returnCode == 0) {
  471. return STATUS_SUCCESS;
  472. } else {
  473. return STATUS_UNSUCCESSFUL;
  474. }
  475. }
  476. NTSTATUS
  477. GetCurrentProcFrequency (
  478. IN ULONG State,
  479. OUT PULONG CpuSpeed
  480. )
  481. /*++
  482. Description:
  483. Arguments:
  484. Return Value:
  485. --*/
  486. {
  487. ULONG cpuSpeed = 0;
  488. DebugAssert(CpuSpeed);
  489. UNREFERENCED_PARAMETER(State);
  490. PAGED_CODE();
  491. //
  492. // If this is a known Cpu, then we should be able
  493. // to use the tables for a fast look up.
  494. //
  495. if (P3_Globals.KnownCPUID) {
  496. ULONG index = GetBusRatio();
  497. if (index < PROC_STATE_INFO_SIZE) {
  498. cpuSpeed = ProcessorStateInfo[index].Frequency;
  499. }
  500. }
  501. if (!cpuSpeed) {
  502. //
  503. // Something went wrong, and we weren't able to use the tables,
  504. // calculate by hand.
  505. //
  506. CalculateCpuFrequency(CpuSpeed);
  507. }
  508. *CpuSpeed = cpuSpeed;
  509. return STATUS_SUCCESS;
  510. }
  511. __inline
  512. ULONG
  513. GetBusRatio (
  514. VOID
  515. )
  516. /*++
  517. Description:
  518. Arguments:
  519. Return Value:
  520. --*/
  521. {
  522. LARGE_INTEGER msrResult;
  523. ULONG busRatio;
  524. PAGED_CODE();
  525. //
  526. // Get Bus Ratio Value
  527. //
  528. msrResult.QuadPart = ReadMSR(MSR_2A);
  529. busRatio = msrResult.LowPart >> MSR_2A_BUS_RATIO_OFFSET;
  530. busRatio &= (BIT0+BIT1+BIT2+BIT3);
  531. //
  532. // This flag should be set on all 0x686 and newer cpu's
  533. //
  534. if (StateFlags & EXTENDED_BUS_RATIO) {
  535. if (msrResult.LowPart & MSR_2A_BUS_RATIO_MSB_BIT) {
  536. busRatio |= BIT4;
  537. }
  538. }
  539. return busRatio;
  540. }
  541. NTSTATUS
  542. GetLegacyMaxProcFrequency(
  543. OUT PULONG CpuSpeed
  544. )
  545. /*++
  546. Description:
  547. Arguments:
  548. Return Value:
  549. NTSTATUS
  550. --*/
  551. {
  552. static ULONG maxCpuSpeed;
  553. NTSTATUS status = STATUS_SUCCESS;
  554. DebugAssert(CpuSpeed);
  555. PAGED_CODE();
  556. //
  557. // if we have already calculated the max speed, use it
  558. //
  559. if (!maxCpuSpeed) {
  560. status = GetMaxProcFrequencySMM(&maxCpuSpeed);
  561. }
  562. *CpuSpeed = maxCpuSpeed;
  563. return STATUS_SUCCESS;
  564. }
  565. NTSTATUS
  566. CollectProcessorInfomation (
  567. VOID
  568. )
  569. /*++
  570. Description:
  571. Arguments:
  572. Return Value:
  573. NTSTATUS
  574. --*/
  575. {
  576. LARGE_INTEGER msr17;
  577. LARGE_INTEGER msr2a;
  578. LARGE_INTEGER msr20;
  579. LARGE_INTEGER msr119;
  580. NTSTATUS status = STATUS_SUCCESS;
  581. ULONG cpuIdentifier;
  582. ULONG istField;
  583. ULONG platformId;
  584. ULONG junk;
  585. ULONG tmp;
  586. PAGED_CODE();
  587. //
  588. // Get CpuId
  589. //
  590. CPUID(1, &cpuIdentifier, &junk, &junk, &junk);
  591. //
  592. // Get MSR 0x17 results
  593. //
  594. msr17.QuadPart = ReadMSR(MSR_17);
  595. //
  596. // Check mobile bit, MSR 0x17[50] .. EDX[18]
  597. //
  598. if (!(msr17.HighPart & MSR_17_HIGH_MOBILE_PROCESSOR)) {
  599. DebugPrint((WARN, "This is NOT a Mobile Intel Processor\n"));
  600. status = STATUS_UNSUCCESSFUL;
  601. goto CollectProcessorInfomationExit;
  602. }
  603. //
  604. // Collect Bus Speed Information (MSR2A[19:18])
  605. // 0x1 == 133mhz Bus
  606. //
  607. msr2a.QuadPart = ReadMSR(MSR_2A);
  608. msr2a.LowPart >>= MSR_2A_BUS_SPEED_OFFSET;
  609. if ((msr2a.LowPart & (BIT0+BIT1)) == 0x1) {
  610. StateFlags |= BUS_133MHZ;
  611. }
  612. //
  613. // Collect Bin value Delta MSR17[57:56] .. EDX[25:24]
  614. //
  615. istField = (msr17.HighPart >> MSR_17_IST_FIELD_OFFSET) & (BIT0 + BIT1);
  616. //
  617. // Modify istField for specific processor steppings
  618. //
  619. //
  620. // If Tualatin Processor, we have to check the Stride bit MSR17[15].
  621. // If the Stride bit is set, add 5 to IST value, otherwise add 2
  622. //
  623. if ((cpuIdentifier & FAMILYMODEL_MASK) == FAMILYMODEL_TUALATIN) {
  624. StateFlags |= TUALATINE_PROCESSOR;
  625. StateFlags |= EXTENDED_BUS_RATIO;
  626. if (cpuIdentifier <= HIGHEST_KNOWN_TUALATIN_CPUID) {
  627. P3_Globals.KnownCPUID = TRUE;
  628. }
  629. //
  630. // Select the correct table
  631. //
  632. ProcessorStateInfo = (StateFlags & BUS_133MHZ) ? Tualatin133 : Tualatin100;
  633. //
  634. // Read MSR20h[15] "Stride fuse"
  635. //
  636. msr20.QuadPart = ReadMSR(MSR_20);
  637. istField += (msr20.LowPart & MSR_20_STRIDE_BIT) ? 5 : 2;
  638. } else if ((cpuIdentifier & FAMILYMODEL_MASK) == FAMILYMODEL_COPPERMINE) {
  639. StateFlags |= COPPERMINE_PROCESSOR;
  640. if (cpuIdentifier <= HIGHEST_KNOWN_COPPERMINE_CPUID) {
  641. P3_Globals.KnownCPUID = TRUE;
  642. }
  643. //
  644. // Select the correct table
  645. //
  646. ProcessorStateInfo = (StateFlags & BUS_133MHZ) ? Coppermine133 : Coppermine100;
  647. if (cpuIdentifier == 0x686) {
  648. //
  649. // C Stepping ...
  650. // For 0x686 we need to perform some magic based on the PlatformId bits,
  651. // possibly set bit 2 in istField
  652. //
  653. StateFlags |= EXTENDED_BUS_RATIO;
  654. platformId = (msr17.HighPart >> MSR_17_PLATFORM_ID_OFFSET) & (BIT0 + BIT1);
  655. if (platformId & BIT1) {
  656. //
  657. // Componet Type
  658. //
  659. if (platformId & BIT0) {
  660. istField |= BIT2;
  661. }
  662. } else {
  663. //
  664. // Module Type
  665. //
  666. if (!(platformId & BIT0)) {
  667. istField |= BIT2;
  668. }
  669. }
  670. } else if (cpuIdentifier > 0x686) {
  671. //
  672. // D Stepping ...
  673. // We need to set bit 2 in istField if MSR 0x119[0] is set
  674. //
  675. StateFlags |= EXTENDED_BUS_RATIO;
  676. msr119.QuadPart = ReadMSR(MSR_119);
  677. if (msr119.LowPart & BIT0) {
  678. istField |= BIT2;
  679. }
  680. }
  681. } else {
  682. DebugAssert(!"Unknown Processor Family\n");
  683. StateFlags = 0;
  684. }
  685. //
  686. // Check to see if this processor is SpeedStep capable
  687. //
  688. if (!(istField & (BIT0 + BIT1 + BIT2 + BIT3 + BIT4))) {
  689. DebugPrint((WARN, "This processor is NOT SpeedStep capable.\n"));
  690. status = STATUS_UNSUCCESSFUL;
  691. goto CollectProcessorInfomationExit;
  692. }
  693. //
  694. // Save the IST
  695. //
  696. P3_Globals.IstField = istField;
  697. CollectProcessorInfomationExit:
  698. DebugExitStatus(status);
  699. return status;
  700. }
  701. ULONG
  702. FindCpuSpeedByBinValue (
  703. ULONG BinValue,
  704. PPROCESSOR_STATE_INFO Table
  705. )
  706. {
  707. ULONG x;
  708. DebugAssert(Table);
  709. //
  710. // Walk tables looking for entry with matching bin value
  711. //
  712. for (x = 0; x < PROC_STATE_INFO_SIZE; x++) {
  713. if (Table[x].BinValue == BinValue) {
  714. return Table[x].Frequency;
  715. }
  716. }
  717. return 0;
  718. }
  719. VOID
  720. DumpStateFlags (
  721. ULONG StateFlags
  722. )
  723. {
  724. DebugPrint((MAXTRACE, "\n"));
  725. DebugPrint((MAXTRACE, "State Flags:\n"));
  726. DebugPrint((MAXTRACE, " Coppermine Processor: %s\n", (StateFlags & COPPERMINE_PROCESSOR) ? "Yes" : "No"));
  727. DebugPrint((MAXTRACE, " Tualatine Processor: %s\n", (StateFlags & TUALATINE_PROCESSOR) ? "Yes" : "No"));
  728. DebugPrint((MAXTRACE, " 133mhz Bus: %s\n", (StateFlags & BUS_133MHZ) ? "Yes" : "No"));
  729. DebugPrint((MAXTRACE, " Extended Bus Ratio %s\n", (StateFlags & EXTENDED_BUS_RATIO) ? "Yes" : "No"));
  730. DebugPrint((MAXTRACE, "\n"));
  731. }