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.

1166 lines
22 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. p3.c
  5. Abstract:
  6. This module implements code specific to the PentiumIII processor
  7. Author:
  8. Jake Oshins (3/21/00) - create file
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. DeviceInst = "ACPI\GenuineIntel_-_x86_Family_6_Model_8"
  13. ServiceName = "P3"
  14. Revision History:
  15. --*/
  16. #include "p3.h"
  17. #include "..\lib\processor.h"
  18. #if DBG
  19. PUCHAR DebugName = "P3.sys";
  20. #endif
  21. PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS];
  22. UCHAR DevExtIndex;
  23. P3_GLOBALS P3_Globals;
  24. extern ULONG HalpThrottleScale;
  25. extern GLOBALS Globals;
  26. extern LEGACY_GEYSERVILLE_INT15 LegacyInterface;
  27. VOID
  28. AcpiNotify80CallbackWorker(
  29. IN PDEVICE_OBJECT DeviceObject,
  30. IN PVOID Context
  31. );
  32. NTSTATUS
  33. UpdateAcDcMaxLevel(
  34. IN PVOID Context,
  35. IN BOOLEAN AC
  36. );
  37. #ifdef ALLOC_PRAGMA
  38. #pragma alloc_text (PAGE, InitializeDriver)
  39. #pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
  40. #pragma alloc_text (PAGE, InitializeAcpi2PStates)
  41. #pragma alloc_text (PAGE, InitializeAcpi2Cstates)
  42. #pragma alloc_text (PAGE, MergePerformanceStates)
  43. #pragma alloc_text (PAGE, AdjustLegacyProcessorPerformanceStates)
  44. #pragma alloc_text (PAGE, GetProcessorBrandString)
  45. #endif
  46. NTSTATUS
  47. InitializeDriver(
  48. PUNICODE_STRING ServiceKeyRegPath
  49. )
  50. /*++
  51. Routine Description:
  52. Arguments:
  53. Return Value:
  54. --*/
  55. {
  56. //
  57. // Get P3 Hack Flags
  58. //
  59. GetRegistryDwordValue((PWCHAR) P3_PARAMETERS_KEY,
  60. L"HackFlags",
  61. &P3_Globals.HackFlags);
  62. //
  63. // Setup Timer Dpc Thread, this is not MP safe.
  64. //
  65. if (Globals.SingleProcessorProfile) {
  66. LONG timeOutSeconds = 0;
  67. //
  68. // Initialize CustomTimerDpc
  69. //
  70. KeInitializeDpc(&P3_Globals.Dpc, P3TimerDpcHandler, NULL);
  71. KeInitializeTimer(&P3_Globals.Timer);
  72. //
  73. // Get tranistion timeout value from Registry
  74. //
  75. GetRegistryDwordValue((PWCHAR) P3_PARAMETERS_KEY,
  76. L"RetryTimeOut",
  77. &timeOutSeconds);
  78. if (timeOutSeconds) {
  79. //
  80. // Validate timeout values
  81. //
  82. timeOutSeconds = MIN(timeOutSeconds, MAX_RETRY_TIMEOUT);
  83. timeOutSeconds = MAX(timeOutSeconds, MIN_RETRY_TIMEOUT);
  84. } else {
  85. //
  86. // Set default 1 minute timeout
  87. //
  88. timeOutSeconds = DEFAULT_RETRY_TIMEOUT;
  89. }
  90. P3_Globals.TimeOut.QuadPart = -(timeOutSeconds * SECOND);
  91. // tmp debug
  92. DebugPrint((ERROR, "Using TimeOutRetry value of %d minutes (%d seconds)\n",
  93. timeOutSeconds/60,
  94. timeOutSeconds));
  95. }
  96. return STATUS_SUCCESS;
  97. }
  98. NTSTATUS
  99. InitializeNonAcpiPerformanceStates(
  100. IN PFDO_DATA DevExt
  101. )
  102. /*++
  103. Routine Description:
  104. This function tries to gather as much information as it can about what
  105. states are available. It puts a table in the device extension that
  106. describes the available states. Unfortunately, we might not have enough
  107. information to fill in the state table, as the BIOS doesn't tell us much.
  108. We try to run through all the states, figuring out what we can about them
  109. as we pass through them. But some states may not be available at the
  110. moment, particularly if we are running on DC power at the moment. So some
  111. states may have zeros in the table.
  112. Arguments:
  113. FdoData - pointer to the device extension
  114. Return Value:
  115. NT status code
  116. --*/
  117. {
  118. LARGE_INTEGER startTime;
  119. LARGE_INTEGER endTime;
  120. LARGE_INTEGER perfFreq;
  121. ULONG newState;
  122. ULONG currentFreq;
  123. ULONG pssSize;
  124. ULONG latency;
  125. NTSTATUS status;
  126. PLEGACY_GEYSERVILLE_INTERFACE_INFO info = &P3_Globals.LegacyInterfaceInfo;
  127. DebugEnter();
  128. PAGED_CODE();
  129. //
  130. // We automatically fail to use the Legacy Interface
  131. //
  132. if (Globals.HackFlags & DISABLE_LEGACY_INTERFACE_FLAG) {
  133. DebugPrint((ERROR, " Legacy Interface Disabled\n"));
  134. return STATUS_NOT_FOUND;
  135. }
  136. //
  137. // Check hack flags to see if we should use the Legacy interface.
  138. //
  139. if (!(P3_Globals.HackFlags & ENABLE_LEGACY_SPEEDSTEP_INTERFACE)) {
  140. status = STATUS_NOT_FOUND;
  141. DebugPrint((WARN, " Legacy Interface NOT enabled in P3\\parameters\\HackFlags.\n"));
  142. DebugExitStatus(status);
  143. return status;
  144. }
  145. //
  146. // Find and gather legacy interface info
  147. //
  148. status = InitializeLegacyInterface(info, DevExt);
  149. if (!NT_SUCCESS(status)) {
  150. DebugExitStatus(status);
  151. return status;
  152. }
  153. if (!info->CurrentlyAvailableStates) {
  154. status = STATUS_NOT_FOUND;
  155. DebugPrint((ERROR, " Found Legacy Interface, but no perfstates.\n"));
  156. DebugExitStatus(status);
  157. return status;
  158. } else if (info->CurrentlyAvailableStates > MAX_GEYSERVILLE_STATES) {
  159. status = STATUS_NOT_FOUND;
  160. DebugPrint((ERROR, " Found Legacy Interface. Error: %u PerfStates defined\n",
  161. info->CurrentlyAvailableStates));
  162. DebugExitStatus(status);
  163. return status;
  164. }
  165. //
  166. // Found Legacy Interface, and is available to use.
  167. //
  168. DevExt->LegacyInterface = TRUE;
  169. //
  170. // Allocate enough space for 2 perf states.
  171. //
  172. pssSize = sizeof(ACPI_PSS_PACKAGE) + sizeof(ACPI_PSS_DESCRIPTOR);
  173. DevExt->PssPackage = ExAllocatePoolWithTag(NonPagedPool,
  174. pssSize,
  175. PROCESSOR_POOL_TAG);
  176. if (!DevExt->PssPackage) {
  177. status = STATUS_INSUFFICIENT_RESOURCES;
  178. goto InitalizeNonAcpiPerformanceStatesExit;
  179. }
  180. RtlZeroMemory(DevExt->PssPackage, pssSize);
  181. DevExt->PssPackage->NumPStates = MAX_GEYSERVILLE_STATES;
  182. //
  183. // Jump through each state so that we can figure out how to fill in
  184. // the table. Start by jumping to the low state.
  185. //
  186. DebugPrint((INFO, "Perf States available: 0x%x Current State: 0x%x\n",
  187. info->CurrentlyAvailableStates,
  188. info->CurrentState));
  189. //
  190. // Get Perf Counter Frequency
  191. //
  192. KeQueryPerformanceCounter(&perfFreq);
  193. //
  194. // Fill out the _PSS for first state, opposite of the current state
  195. //
  196. newState = info->CurrentState ? 0 : 1;
  197. startTime = KeQueryPerformanceCounter(NULL);
  198. status = AcpiPerfStateTransition(DevExt, newState);
  199. endTime = KeQueryPerformanceCounter(NULL);
  200. if (!NT_SUCCESS(status)) {
  201. QueueEventLogWrite(DevExt, PROCESSOR_INIT_TRANSITION_FAILURE, newState);
  202. goto InitalizeNonAcpiPerformanceStatesExit;
  203. }
  204. //
  205. // Calculate latency, speed, & power
  206. //
  207. latency = (ULONG)((endTime.QuadPart - startTime.QuadPart) * 1000000 / perfFreq.QuadPart);
  208. DevExt->PssPackage->State[newState].Latency = latency;
  209. GetCurrentProcFrequency(newState, &currentFreq);
  210. DevExt->PssPackage->State[newState].CoreFrequency = currentFreq;
  211. DevExt->PssPackage->State[newState].Power = currentFreq * 16;
  212. DebugPrint((INFO, "Jumped to state 0x%x in %d us\n", newState, latency));
  213. //
  214. // Jump back to orginal state
  215. //
  216. newState = info->CurrentState;
  217. startTime = KeQueryPerformanceCounter(NULL);
  218. status = AcpiPerfStateTransition(DevExt, newState);
  219. endTime = KeQueryPerformanceCounter(NULL);
  220. if (!NT_SUCCESS(status)) {
  221. QueueEventLogWrite(DevExt, PROCESSOR_INIT_TRANSITION_FAILURE, newState);
  222. goto InitalizeNonAcpiPerformanceStatesExit;
  223. }
  224. //
  225. // Calculate latency, speed, & power
  226. //
  227. latency = (ULONG)((endTime.QuadPart - startTime.QuadPart) * 1000000 / perfFreq.QuadPart);
  228. DevExt->PssPackage->State[newState].Latency = latency;
  229. GetCurrentProcFrequency(newState, &currentFreq);
  230. DevExt->PssPackage->State[newState].CoreFrequency = currentFreq;
  231. DevExt->PssPackage->State[newState].Power = currentFreq * 16;
  232. DebugPrint((INFO, "Jumped to state 0x%x in %d us\n", newState, latency));
  233. //
  234. // NOTE: This is a work around because the Policy Manager won't set our
  235. // low perf state to POP_THROTTLE_NON_LINEAR if we use the above algothrim,
  236. // because it makes each of our states very linear. In Acpi 2.0, this
  237. // information is given to us in the _PSS, but for legacy perfstates, we
  238. // have to make it up.
  239. //
  240. AdjustLegacyProcessorPerformanceStates(DevExt->PssPackage);
  241. //
  242. // Sanity Check the two states.
  243. //
  244. DebugAssert(DevExt->PssPackage->State[0].CoreFrequency >
  245. DevExt->PssPackage->State[1].CoreFrequency);
  246. //
  247. // Merge Perf states with other states we may have.
  248. //
  249. status = MergePerformanceStates(DevExt);
  250. if(!NT_SUCCESS(status)) {
  251. goto InitalizeNonAcpiPerformanceStatesExit;
  252. }
  253. //
  254. // Register for power state change notification so we can re-init the
  255. // legacy interface when resuming from S4
  256. //
  257. status = PowerStateHandlerNotificationRegistration(ProcessSleepStateNotification,
  258. NULL,
  259. TRUE);
  260. //
  261. // If the max state avaiablable on Ac & Dc is different, then
  262. // register for AC<->DC transition notification.
  263. //
  264. if (P3_Globals.MaxLevelAc != P3_Globals.MaxLevelDc) {
  265. RegisterAcDcTransitionNotifyHandler(UpdateAcDcMaxLevel, (PVOID) DevExt);
  266. }
  267. InitalizeNonAcpiPerformanceStatesExit:
  268. if (!NT_SUCCESS(status)) {
  269. if (DevExt->PssPackage) {
  270. ExFreePool(DevExt->PssPackage);
  271. }
  272. DevExt->PssPackage = NULL;
  273. DevExt->LegacyInterface = FALSE;
  274. }
  275. DebugExitStatus(status);
  276. return status;
  277. }
  278. NTSTATUS
  279. AcpiLegacyPerfStateTransition(
  280. IN PFDO_DATA DeviceExtension,
  281. IN ULONG State
  282. )
  283. /*++
  284. Routine Description:
  285. Arguments:
  286. Return Value:
  287. --*/
  288. {
  289. #define TRANSITION_RETRY_VALUE 1000
  290. NTSTATUS status;
  291. ULONG x;
  292. //
  293. // Performance Transitions are currently unavailable.
  294. //
  295. if (P3_Globals.TransitionsUnavailable) {
  296. return STATUS_UNSUCCESSFUL;
  297. }
  298. //
  299. // Adjust the actual state value.
  300. //
  301. State += DeviceExtension->PpcResult;
  302. //
  303. // Attempt transition
  304. //
  305. for (x = 0; x < TRANSITION_RETRY_VALUE; x++) {
  306. status = SetCurrentStateSmm(State);
  307. if (NT_SUCCESS(status) || (status == STATUS_PERF_TRANSITIONS_UNAVAILABLE)) {
  308. break;
  309. } else if (status == STATUS_INVALID_DEVICE_STATE) {
  310. status = STATUS_SUCCESS;
  311. break;
  312. }
  313. }
  314. if (x) {
  315. DebugPrint((WARN, "SetCurrentStateSmm() Failed %u of 1000 retries\n", x));
  316. }
  317. if (status == STATUS_PERF_TRANSITIONS_UNAVAILABLE) {
  318. // tmp debug
  319. DebugPrint((ERROR, "SetCurrentStateSmm() failed STATUS_PERF_TRANSITIONS_UNAVAILABLE\n"));
  320. DebugPrint((ERROR, "*** Disabling Transitions\n"));
  321. //
  322. // Transitions are no longer available.
  323. //
  324. P3_Globals.TransitionsUnavailable = TRUE;
  325. //
  326. // Set timer to launch DPC thread
  327. //
  328. KeSetTimer(&P3_Globals.Timer, P3_Globals.TimeOut, &P3_Globals.Dpc);
  329. status = STATUS_UNSUCCESSFUL;
  330. }
  331. return status;
  332. }
  333. NTSTATUS
  334. FASTCALL
  335. SetPerfLevel(
  336. IN UCHAR Throttle
  337. )
  338. /*++
  339. Routine Description:
  340. Arguments:
  341. Return Value:
  342. --*/
  343. {
  344. PFDO_DATA DeviceExtension;
  345. ULONG apicId;
  346. ULONG index = 0;
  347. DebugEnter();
  348. //
  349. // Get APIC Id and retrieve Device Extension index
  350. //
  351. if (!Globals.SingleProcessorProfile) {
  352. apicId = GetApicId();
  353. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  354. }
  355. //
  356. // Get the DeviceExtension.
  357. //
  358. DeviceExtension = DeviceExtensions[index];
  359. //
  360. // Since this driver does not support Functional Fixed Hardware, we
  361. // use generic method.
  362. //
  363. return SetPerfLevelGeneric(Throttle, DeviceExtension);
  364. }
  365. NTSTATUS
  366. FASTCALL
  367. SetThrottleLevel(
  368. IN UCHAR Throttle
  369. )
  370. /*++
  371. Routine Description:
  372. Arguments:
  373. Return Value:
  374. --*/
  375. {
  376. PFDO_DATA DeviceExtension;
  377. ULONG apicId;
  378. ULONG index = 0;
  379. DebugEnter();
  380. //
  381. // Get APIC Id and retrieve Device Extension index
  382. //
  383. if (!Globals.SingleProcessorProfile) {
  384. apicId = GetApicId();
  385. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  386. }
  387. //
  388. // Get the DeviceExtension.
  389. //
  390. DeviceExtension = DeviceExtensions[index];
  391. //
  392. // Since this driver does not support Functional Fixed Hardware, we
  393. // use generic method.
  394. //
  395. return SetThrottleLevelGeneric(Throttle, DeviceExtension);
  396. }
  397. NTSTATUS
  398. InitializeAcpi2PStates(
  399. IN PFDO_DATA DevExt
  400. )
  401. /*++
  402. Routine Description:
  403. Arguments:
  404. Return Value:
  405. --*/
  406. {
  407. NTSTATUS status;
  408. status = InitializeAcpi2PStatesGeneric(DevExt);
  409. //
  410. // Make sure we didn't find any NON I/O or MEM addresses
  411. //
  412. if (NT_SUCCESS(status)) {
  413. if (((DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceIO) &&
  414. (DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceMemory)) ||
  415. ((DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceIO) &&
  416. (DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceMemory))) {
  417. DebugPrint((WARN, "ONLY Memory & I/O _PCT addresses are supported\n"));
  418. DebugPrint((WARN, "NOT using Acpi 2.0 Performance States\n"));
  419. //
  420. // Undo what InitializeAcpi2PStatesGeneric() did
  421. //
  422. if (DevExt->PssPackage) {
  423. ExFreePool(DevExt->PssPackage);
  424. DevExt->PssPackage = NULL;
  425. }
  426. return STATUS_NOT_SUPPORTED;
  427. }
  428. //
  429. // Walk through _PSS states to calculate latency values
  430. //
  431. ValidatePssLatencyValues(DevExt);
  432. //
  433. // Need to merge this new data with our perfstates
  434. //
  435. MergePerformanceStates(DevExt);
  436. }
  437. return status;
  438. }
  439. NTSTATUS
  440. InitializeAcpi2Cstates(
  441. PFDO_DATA DevExt
  442. )
  443. /*++
  444. Routine Description:
  445. This function looks to see if there is an ACPI 2.0 _CST object in the
  446. namespace, and, if there is, it replaces the functions found by
  447. InitializeAcpi1Cstates.
  448. Further note: This function leaves the filling in of throttling functions
  449. to the InitializePerformanceStates functions.
  450. Arguments:
  451. DeviceExtension
  452. Return Value:
  453. A NTSTATUS code to indicate the result of the initialization.
  454. --*/
  455. {
  456. ULONG apicId;
  457. ULONG index = 0;
  458. DebugEnter();
  459. //
  460. // Record the address of this processor's DeviceExtension, as the
  461. // throttling API doesn't give it to us.
  462. //
  463. if (!Globals.SingleProcessorProfile) {
  464. //
  465. // save the index into the DeviceExtension[] for later retrieval based
  466. // on APIC Id.
  467. //
  468. apicId = Globals.ProcInfo.ProcIdToApicId[DevExt->ProcObjInfo.PhysicalID];
  469. Globals.ProcInfo.ApicIdToDevExtIndex[apicId] = DevExtIndex;
  470. index = DevExtIndex++;
  471. }
  472. //
  473. // save Device Extension pointer
  474. //
  475. DebugAssert(DeviceExtensions[index] == 0);
  476. DeviceExtensions[index] = DevExt;
  477. //
  478. // This processor driver only supports I/O Space based Cstates.
  479. // InitializeAcpi2IoSpaceCstates() will fail if it finds Cstates with
  480. // non AcpiGenericSpaceIO type addresses.
  481. //
  482. return InitializeAcpi2IoSpaceCstates(DevExt);
  483. }
  484. NTSTATUS
  485. MergePerformanceStates (
  486. IN PFDO_DATA DeviceExtension
  487. )
  488. /*++
  489. Routine Description:
  490. This routine looks at the performance states stored in the device extension.
  491. Arguments:
  492. DeviceExtension
  493. Return Value:
  494. A NTSTATUS code to indicate the result of the initialization.
  495. NOTE:
  496. - The caller must hold PerfStateLock.
  497. - This is called during START_DEVICE, and after recieving a Notify(0x80)
  498. on the processor.
  499. --*/
  500. {
  501. DebugEnter();
  502. //
  503. // Since this driver does not support Functional Fixed Hardware, we
  504. // use generic method.
  505. //
  506. return MergePerformanceStatesGeneric(DeviceExtension);
  507. }
  508. NTSTATUS
  509. Acpi2PerfStateTransition(
  510. IN PFDO_DATA DeviceExtension,
  511. IN ULONG State
  512. )
  513. /*++
  514. Routine Description:
  515. This routine changes the performance state of the processor
  516. based on ACPI 2.0 performance state objects.
  517. Arguments:
  518. State - Index into _PSS object
  519. Return Value:
  520. none
  521. --*/
  522. {
  523. //
  524. // Since this driver does not support Functional Fixed Hardware, we
  525. // use generic method.
  526. //
  527. return Acpi2PerfStateTransitionGeneric(DeviceExtension, State);
  528. }
  529. NTSTATUS
  530. AdjustLegacyProcessorPerformanceStates(
  531. IN OUT PACPI_PSS_PACKAGE PssPackage
  532. )
  533. /*++
  534. Routine Description:
  535. Arguments:
  536. Return Value:
  537. --*/
  538. {
  539. DebugAssert(PssPackage->NumPStates <= 2)
  540. PssPackage->State[0].Power = PssPackage->State[0].CoreFrequency * 50;
  541. return STATUS_SUCCESS;
  542. }
  543. NTSTATUS
  544. ProcessResumeFromSleepState(
  545. SYSTEM_POWER_STATE PreviousState,
  546. PFDO_DATA DeviceExtension
  547. )
  548. /*++
  549. Routine Description:
  550. Arguments:
  551. Return Value:
  552. --*/
  553. {
  554. DebugEnter();
  555. //
  556. // if we are resuming from Hibernate, and this is an Acpi 2.0 system,
  557. // we must re-claim perf state and cstate control from the bios.
  558. //
  559. if (PreviousState == PowerSystemHibernate) {
  560. if (DeviceExtension->PssPackage) {
  561. AssumeProcessorPerformanceControl();
  562. }
  563. if (DeviceExtension->CstPresent) {
  564. AssumeCStateControl();
  565. }
  566. }
  567. //
  568. // restore previous state
  569. //
  570. return RestoreToSavedPerformanceState(DeviceExtension);
  571. }
  572. NTSTATUS
  573. ProcessSuspendToSleepState(
  574. SYSTEM_POWER_STATE TargetState,
  575. PFDO_DATA DeviceExtension
  576. )
  577. /*++
  578. Routine Description:
  579. Arguments:
  580. Return Value:
  581. --*/
  582. {
  583. DebugEnter();
  584. //
  585. // save current state, transition to lowest non-throttled perf state
  586. //
  587. return SaveCurrentStateGoToLowVolts(DeviceExtension);
  588. }
  589. NTSTATUS
  590. ProcessSleepStateNotification (
  591. IN POWER_STATE_HANDLER_TYPE State,
  592. IN PVOID Context,
  593. IN BOOLEAN Entering
  594. )
  595. /*++
  596. Routine Description:
  597. Arguments:
  598. Return Value:
  599. --*/
  600. {
  601. NTSTATUS status = STATUS_SUCCESS;
  602. PFDO_DATA DeviceExtension;
  603. DebugEnter();
  604. //
  605. // Currently we only support this for single proc machines.
  606. //
  607. if (Globals.SingleProcessorProfile) {
  608. //
  609. // Get the DeviceExtension.
  610. //
  611. DeviceExtension = DeviceExtensions[0];
  612. //
  613. // if we are resuming from Hibernate on a system using the legacy Geyserville
  614. // interface, we need to reinit the interface
  615. //
  616. if (!Entering && (State == PowerStateSleeping4)) {
  617. //
  618. // Initialize Throttle States to "Throttle off"
  619. //
  620. if (HalpThrottleScale) {
  621. ProcessorThrottle((UCHAR)HalpThrottleScale);
  622. }
  623. if (DeviceExtension->LegacyInterface) {
  624. status = InitializeSmmInterface();
  625. if (!NT_SUCCESS(status)) {
  626. //
  627. // Log event
  628. //
  629. QueueEventLogWrite(DeviceExtension,
  630. PROCESSOR_REINITIALIZATION_FAILURE,
  631. 0);
  632. DebugPrint((ERROR, "ProcessSleepStateNotification: InitializeSmmInterface() Failed! rc=0x%x\n",
  633. status));
  634. }
  635. }
  636. }
  637. }
  638. return status;
  639. }
  640. NTSTATUS
  641. GetProcessorBrandString (
  642. PUCHAR BrandString,
  643. PULONG Size
  644. )
  645. /*++
  646. Routine Description:
  647. Arguments:
  648. Return Value:
  649. --*/
  650. {
  651. #define CPUID_BRAND_STRING_LENGTH 49
  652. PUCHAR tmpPtr;
  653. ULONG tmp;
  654. ULONG brandIndex;
  655. ULONG cpuId;
  656. NTSTATUS status;
  657. DebugAssert(Size);
  658. PAGED_CODE();
  659. //
  660. // check incoming buffer size, the most we will need is CPUID_BRAND_STRING_LENGTH
  661. //
  662. if (!BrandString || (*Size < CPUID_BRAND_STRING_LENGTH)) {
  663. *Size = CPUID_BRAND_STRING_LENGTH;
  664. return STATUS_BUFFER_TOO_SMALL;
  665. }
  666. //
  667. // First we will check to see if this processor supports
  668. // brand strings
  669. //
  670. status = GetCPUIDProcessorBrandString(BrandString, Size);
  671. if (NT_SUCCESS(status)) {
  672. return status;
  673. }
  674. CPUID(1, &cpuId, &brandIndex, &tmp, &tmp);
  675. brandIndex &= 0xf;
  676. //
  677. // NOTE: these strings CANNOT exceed CPUID_BRAND_STRING_LENGTH in size
  678. // or the above code must change
  679. //
  680. switch (brandIndex) {
  681. case 0x1:
  682. tmpPtr = "Intel(r) Celeron(r) processor";
  683. break;
  684. case 0x2:
  685. tmpPtr = "Intel(r) Pentium(r)III processor";
  686. break;
  687. case 0x3:
  688. if (cpuId == 0x6B1) {
  689. tmpPtr = "Intel(r) Celeron(r) processor";
  690. } else {
  691. tmpPtr = "Intel(r) Pentium(r)III Xeon(tm) processor";
  692. }
  693. break;
  694. case 0x4:
  695. tmpPtr = "Intel(r) Pentium(r)III processor";
  696. break;
  697. case 0x6:
  698. tmpPtr = "Mobile Intel(r) Pentium(r)III Processor-M";
  699. break;
  700. case 0x7:
  701. tmpPtr = "Mobile Intel(r) Celeron(r) processor";
  702. break;
  703. case 0x8:
  704. if (cpuId >= 0xF20) {
  705. tmpPtr = "Intel(r) Genuine processor";
  706. } else {
  707. tmpPtr = "Intel(r) Pentium(r)4 processor";
  708. }
  709. break;
  710. case 0x9:
  711. tmpPtr = "Intel(r) Pentium(r)4 processor";
  712. break;
  713. case 0xA:
  714. tmpPtr = "Intel(r) Xeon(tm) processor";
  715. break;
  716. case 0xE:
  717. tmpPtr = "Intel(r) Xeon(tm) processor";
  718. break;
  719. default:
  720. return STATUS_NOT_SUPPORTED;
  721. }
  722. //
  723. // Copy string to buffer
  724. //
  725. strncpy(BrandString, tmpPtr, strlen(tmpPtr) + 1);
  726. return STATUS_SUCCESS;
  727. }
  728. NTSTATUS
  729. UpdateAcDcMaxLevel(
  730. IN PVOID Context,
  731. IN BOOLEAN AC
  732. )
  733. /*++
  734. Routine Description:
  735. Arguments:
  736. Return Value:
  737. --*/
  738. {
  739. ULONG newPpc;
  740. PFDO_DATA devExt = Context;
  741. //
  742. // We only do this when using the Legacy SpeedStep interface
  743. //
  744. if (devExt->LegacyInterface &&
  745. devExt->PssPackage) {
  746. newPpc = AC ? P3_Globals.MaxLevelAc : P3_Globals.MaxLevelDc;
  747. //
  748. // if the Max state currently available has changed, then
  749. // we will rebuilt the states.
  750. //
  751. if (devExt->PpcResult != newPpc) {
  752. DebugPrint((ERROR, "UpdateAcDcMaxLevel: New _PPC = %u\n", newPpc));
  753. devExt->PpcResult = newPpc;
  754. AcpiNotify80CallbackWorker(devExt->Self,
  755. NULL);
  756. }
  757. }
  758. return STATUS_SUCCESS;
  759. }
  760. VOID
  761. P3TimerDpcHandler (
  762. IN PKDPC Dpc,
  763. IN PVOID DeferredContext,
  764. IN PVOID SystemArgument1,
  765. IN PVOID SystemArgument2
  766. )
  767. {
  768. // tmp debug
  769. DebugPrint((ERROR, "*** Re-enabling Transitions\n"));
  770. //
  771. // Re-enable transitions
  772. //
  773. P3_Globals.TransitionsUnavailable = FALSE;
  774. }