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.

672 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. crusoe.c
  5. Abstract:
  6. This module implements code specific to the Crusoe processor
  7. Author:
  8. Todd Carpenter (10/31/00) - create file
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. DeviceInst = "ACPI\GenuineTMx86_-_x86_Family_5_Model_4"
  13. ServiceName = "crusoe"
  14. Revision History:
  15. --*/
  16. #include "crusoe.h"
  17. #include "..\lib\processor.h"
  18. #if DBG
  19. PUCHAR DebugName = "Crusoe.sys";
  20. #endif
  21. PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS];
  22. UCHAR DevExtIndex;
  23. extern GLOBALS Globals;
  24. extern LONGRUN_STATES LongRunStates;
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text (PAGE, InitializeDriver)
  27. #pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
  28. #pragma alloc_text (PAGE, InitializeAcpi2PStates)
  29. #pragma alloc_text (PAGE, InitializeAcpi2Cstates)
  30. #pragma alloc_text (PAGE, MergePerformanceStates)
  31. #pragma alloc_text (PAGE, GetLegacyMaxProcFrequency)
  32. #pragma alloc_text (PAGE, AdjustLegacyProcessorPerformanceStates)
  33. #pragma alloc_text (PAGE, GetProcessorBrandString)
  34. #endif
  35. NTSTATUS
  36. InitializeDriver(
  37. PUNICODE_STRING ServiceKeyRegPath
  38. )
  39. /*++
  40. Routine Description:
  41. Arguments:
  42. Return Value:
  43. --*/
  44. {
  45. PAGED_CODE();
  46. return STATUS_SUCCESS;
  47. }
  48. NTSTATUS
  49. InitializeNonAcpiPerformanceStates(
  50. IN PFDO_DATA DeviceExtension
  51. )
  52. /*++
  53. Routine Description:
  54. Arguments:
  55. Return Value:
  56. --*/
  57. {
  58. NTSTATUS status;
  59. DebugEnter();
  60. PAGED_CODE();
  61. //
  62. // We automatically fail to use the Legacy Interface
  63. //
  64. if (Globals.HackFlags & DISABLE_LEGACY_INTERFACE_FLAG) {
  65. DebugPrint((ERROR, " Legacy Interface Disabled\n"));
  66. return STATUS_NOT_FOUND;
  67. }
  68. //
  69. // Find and gather legacy interface info
  70. //
  71. status = InitializeLegacyInterface(DeviceExtension);
  72. if (!NT_SUCCESS(status)) {
  73. DebugExitStatus(status);
  74. return status;
  75. }
  76. //
  77. // Found Legacy Interface, and is available to use.
  78. //
  79. DeviceExtension->LegacyInterface = TRUE;
  80. //
  81. // Merge Perf states with other states we may have.
  82. //
  83. status = MergePerformanceStates(DeviceExtension);
  84. DumpProcessorPerfStates(DeviceExtension->PerfStates);
  85. if (!NT_SUCCESS(status)) {
  86. if (DeviceExtension->PerfStates) {
  87. ExFreePool(DeviceExtension->PerfStates);
  88. }
  89. if (DeviceExtension->PssPackage) {
  90. ExFreePool(DeviceExtension->PssPackage);
  91. }
  92. DeviceExtension->PerfStates = NULL;
  93. DeviceExtension->LegacyInterface = FALSE;
  94. }
  95. DebugExitStatus(status);
  96. return status;
  97. }
  98. NTSTATUS
  99. AcpiLegacyPerfStateTransition(
  100. IN PFDO_DATA DevExt,
  101. IN ULONG State
  102. )
  103. /*++
  104. Routine Description:
  105. Arguments:
  106. Return Value:
  107. --*/
  108. {
  109. return Acpi2PerfStateTransition(DevExt, State);
  110. }
  111. NTSTATUS
  112. FASTCALL
  113. SetPerfLevel(
  114. IN UCHAR Throttle
  115. )
  116. /*++
  117. Routine Description:
  118. Arguments:
  119. Return Value:
  120. --*/
  121. {
  122. PFDO_DATA DeviceExtension;
  123. ULONG apicId;
  124. ULONG index = 0;
  125. DebugEnter();
  126. //
  127. // Get APIC Id and retrieve Device Extension index
  128. //
  129. if (!Globals.SingleProcessorProfile) {
  130. apicId = GetApicId();
  131. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  132. }
  133. //
  134. // Get the DeviceExtension.
  135. //
  136. DeviceExtension = DeviceExtensions[index];
  137. //
  138. // Since this driver does not support Functional Fixed Hardware, we
  139. // use generic method.
  140. //
  141. return SetPerfLevelGeneric(Throttle, DeviceExtension);
  142. }
  143. NTSTATUS
  144. FASTCALL
  145. SetThrottleLevel(
  146. IN UCHAR Throttle
  147. )
  148. /*++
  149. Routine Description:
  150. Arguments:
  151. Return Value:
  152. --*/
  153. {
  154. PFDO_DATA DeviceExtension;
  155. ULONG apicId;
  156. ULONG index = 0;
  157. DebugEnter();
  158. //
  159. // Get APIC Id and retrieve Device Extension index
  160. //
  161. if (!Globals.SingleProcessorProfile) {
  162. apicId = GetApicId();
  163. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  164. }
  165. //
  166. // Get the DeviceExtension.
  167. //
  168. DeviceExtension = DeviceExtensions[index];
  169. //
  170. // Since this driver does not support Functional Fixed Hardware, we
  171. // use generic method.
  172. //
  173. return SetThrottleLevelGeneric(Throttle, DeviceExtension);
  174. }
  175. NTSTATUS
  176. InitializeAcpi2PStates(
  177. IN PFDO_DATA DevExt
  178. )
  179. /*++
  180. Routine Description:
  181. Arguments:
  182. Return Value:
  183. --*/
  184. {
  185. NTSTATUS status;
  186. status = InitializeAcpi2PStatesGeneric(DevExt);
  187. if (NT_SUCCESS(status)) {
  188. if ((DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceFixedFunction) ||
  189. (DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceFixedFunction)) {
  190. DebugPrint((ERROR, "This driver ONLY supports FFH addresses for Acpi 2.0\n"));
  191. status = STATUS_NOT_FOUND;
  192. }
  193. //
  194. // Walk through _PSS states to calculate latency values
  195. //
  196. ValidatePssLatencyValues(DevExt);
  197. //
  198. // Need to merge this new data with our perfstates
  199. //
  200. MergePerformanceStates(DevExt);
  201. }
  202. return status;
  203. }
  204. NTSTATUS
  205. InitializeAcpi2Cstates(
  206. PFDO_DATA DevExt
  207. )
  208. /*++
  209. Routine Description:
  210. This function looks to see if there is an ACPI 2.0 _CST object in the
  211. namespace, and, if there is, it replaces the functions found by
  212. InitializeAcpi1Cstates.
  213. Further note: This function leaves the filling in of throttling functions
  214. to the InitializePerformanceStates functions.
  215. Arguments:
  216. DeviceExtension
  217. Return Value:
  218. A NTSTATUS code to indicate the result of the initialization.
  219. --*/
  220. {
  221. ULONG apicId;
  222. ULONG index = 0;
  223. DebugEnter();
  224. PAGED_CODE();
  225. //
  226. // Record the address of this processor's DeviceExtension, as the
  227. // throttling API doesn't give it to us.
  228. //
  229. if (!Globals.SingleProcessorProfile) {
  230. //
  231. // save the index into the DeviceExtension[] for later retrieval based
  232. // on APIC Id.
  233. //
  234. apicId = Globals.ProcInfo.ProcIdToApicId[DevExt->ProcObjInfo.PhysicalID];
  235. Globals.ProcInfo.ApicIdToDevExtIndex[apicId] = DevExtIndex;
  236. index = DevExtIndex++;
  237. }
  238. //
  239. // save Device Extension pointer
  240. //
  241. DeviceExtensions[index] = DevExt;
  242. //
  243. // This processor driver only supports I/O Space based Cstates.
  244. // InitializeAcpi2IoSpaceCstates() will fail if it finds Cstates with
  245. // non AcpiGenericSpaceIO type addresses.
  246. //
  247. return InitializeAcpi2IoSpaceCstates(DevExt);
  248. }
  249. NTSTATUS
  250. MergePerformanceStates (
  251. IN PFDO_DATA DeviceExtension
  252. )
  253. /*++
  254. Routine Description:
  255. This routine looks at the performance states stored in the device extension.
  256. Arguments:
  257. DeviceExtension
  258. Return Value:
  259. A NTSTATUS code to indicate the result of the initialization.
  260. NOTE:
  261. - The caller must hold PerfStateLock.
  262. - This is called during START_DEVICE, and after recieving a Notify(0x80)
  263. on the processor.
  264. --*/
  265. {
  266. DebugEnter();
  267. PAGED_CODE();
  268. //
  269. // Use the generic method to merge our perf states with stop clock states
  270. //
  271. return MergePerformanceStatesGeneric(DeviceExtension);
  272. }
  273. NTSTATUS
  274. Acpi2PerfStateTransition(
  275. IN PFDO_DATA DevExt,
  276. IN ULONG NewState
  277. )
  278. /*++
  279. Routine Description:
  280. This routine changes the performance state of the processor
  281. based on ACPI 2.0 performance state objects.
  282. Arguments:
  283. State - Index into _PSS object
  284. Return Value:
  285. none
  286. --*/
  287. {
  288. ULONG lowerBound;
  289. ULONG uppperBound;
  290. NTSTATUS status = STATUS_SUCCESS;
  291. STATE_INFO stateInfo;
  292. CRUSOE_PSS_VALUE pssControl;
  293. CRUSOE_PSS_VALUE pssStatus;
  294. ULARGE_INTEGER longRunRange;
  295. DebugEnter();
  296. //
  297. // The only type of Acpi 2.0 implementation this driver supports is FFH
  298. //
  299. DebugAssert(DevExt);
  300. DebugAssert(DevExt->PctPackage.Control.AddressSpaceID == AcpiGenericSpaceFixedFunction);
  301. DebugAssert(DevExt->PctPackage.Status.AddressSpaceID == AcpiGenericSpaceFixedFunction);
  302. pssControl.AsDWord = DevExt->PssPackage->State[NewState].Control;
  303. pssStatus.AsDWord = DevExt->PssPackage->State[NewState].Status;
  304. //
  305. // Sanity Check illeagal conditions
  306. //
  307. if (pssControl.Min > MAX_LONGRUN_VALUE) {
  308. DebugPrint((ERROR, "ERROR: illegal LongRun value: Min=0x%x\n", pssControl.Min));
  309. pssControl.Min = MAX_LONGRUN_VALUE;
  310. }
  311. if (pssControl.Max > MAX_LONGRUN_VALUE) {
  312. DebugPrint((ERROR, "ERROR: illegal LongRun value: Max=0x%x\n", pssControl.Max));
  313. pssControl.Max = MAX_LONGRUN_VALUE;
  314. }
  315. if (pssControl.Min > pssControl.Max) {
  316. DebugPrint((ERROR, "ERROR: illegal LongRun Range: Min: 0x%x, Max: 0x%x\n",
  317. pssControl.Min,
  318. pssControl.Max));
  319. pssControl.Min = pssControl.Max;
  320. }
  321. //
  322. // Transition to new performance state
  323. //
  324. DebugPrint((ERROR, "Setting Long Run Range: l=0x%x, u=0x%x\n", pssControl.Min, pssControl.Max));
  325. SetCurrentPerformanceRange(pssControl.Min, pssControl.Max);
  326. //
  327. // Check to see if the transition was successful
  328. // NOTE: we have to check the LongRun Range rather than a specific state as
  329. // there is no way to know which state within a given range the cpu
  330. // will be in.
  331. //
  332. longRunRange.QuadPart = GetCurrentPerformanceRange();
  333. if ((longRunRange.HighPart == pssStatus.Max) &&
  334. (longRunRange.LowPart == pssStatus.Min)) {
  335. DevExt->CurrentPssState = NewState;
  336. } else {
  337. DebugPrint((ERROR, "ERROR! Expected: l=0x%x, h=0x%x Recieved: l=0x%x, h=0x%x\n",
  338. pssStatus.Min,
  339. pssStatus.Max,
  340. longRunRange.LowPart,
  341. longRunRange.HighPart));
  342. status = STATUS_UNSUCCESSFUL;
  343. }
  344. return status;
  345. }
  346. NTSTATUS
  347. ProcessResumeFromSleepState(
  348. SYSTEM_POWER_STATE PreviousState,
  349. PFDO_DATA DeviceExtension
  350. )
  351. /*++
  352. Routine Description:
  353. Arguments:
  354. Return Value:
  355. --*/
  356. {
  357. DebugEnter();
  358. //
  359. // if we are resuming from Hibernate, and this is an Acpi 2.0 system,
  360. // we must re-claim perf state and cstate control from the bios.
  361. //
  362. if (PreviousState == PowerSystemHibernate) {
  363. if (DeviceExtension->PssPackage) {
  364. AssumeProcessorPerformanceControl();
  365. }
  366. if (DeviceExtension->CstPresent) {
  367. AssumeCStateControl();
  368. }
  369. }
  370. //
  371. // restore previous state
  372. //
  373. return RestoreToSavedPerformanceState(DeviceExtension);
  374. }
  375. NTSTATUS
  376. ProcessSuspendToSleepState(
  377. SYSTEM_POWER_STATE TargetState,
  378. PFDO_DATA DeviceExtension
  379. )
  380. /*++
  381. Routine Description:
  382. Arguments:
  383. Return Value:
  384. --*/
  385. {
  386. DebugEnter();
  387. //
  388. // save current state, transition to lowest non-throttled perf state
  389. //
  390. return SaveCurrentStateGoToLowVolts(DeviceExtension);
  391. }
  392. NTSTATUS
  393. GetLegacyMaxProcFrequency(
  394. OUT PULONG CpuSpeed
  395. )
  396. /*++
  397. Description:
  398. Arguments:
  399. Return Value:
  400. NTSTATUS
  401. --*/
  402. {
  403. PAGED_CODE();
  404. return GetMaxCpuSpeed(CpuSpeed);
  405. }
  406. NTSTATUS
  407. AdjustLegacyProcessorPerformanceStates(
  408. IN OUT PPROCESSOR_PERFORMANCE_STATES PerfStates
  409. )
  410. /*++
  411. Routine Description:
  412. Arguments:
  413. Return Value:
  414. --*/
  415. {
  416. PAGED_CODE();
  417. return STATUS_SUCCESS;
  418. }
  419. NTSTATUS
  420. GetProcessorBrandString (
  421. PUCHAR BrandString,
  422. PULONG Size
  423. )
  424. /*++
  425. Routine Description:
  426. Arguments:
  427. Return Value:
  428. --*/
  429. {
  430. PAGED_CODE();
  431. //
  432. // This processor family supports CPUID Brand String
  433. //
  434. return GetCPUIDProcessorBrandString(BrandString, Size);
  435. }