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.

515 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. viac3.c
  5. Abstract:
  6. This module implements code that works on Cyrix processors with LongHaul power management support.
  7. Author:
  8. Tom Brown (t-tbrown) 07-Jun-2001
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. DeviceInst = "ACPI\CentaurHauls_-_x86_Family_6_Model_7"
  13. DeviceInst = "ACPI\CentaurHauls_-_x86_Family_6_Model_8"
  14. ServiceName = "viac3"
  15. Revision History:
  16. --*/
  17. #include "..\lib\processor.h"
  18. #include "legacy.h"
  19. #include "viac3.h"
  20. //
  21. // Must define for debug output
  22. //
  23. #if DBG
  24. PUCHAR DebugName = "viac3.sys";
  25. #endif
  26. PFDO_DATA DeviceExtensions[MAX_SUPPORTED_PROCESSORS];
  27. UCHAR DevExtIndex;
  28. extern GLOBALS Globals;
  29. #ifdef ALLOC_PRAGMA
  30. #pragma alloc_text (PAGE, InitializeNonAcpiPerformanceStates)
  31. #pragma alloc_text (PAGE, InitializeAcpi2PStates)
  32. #pragma alloc_text (PAGE, InitializeAcpi2Cstates)
  33. #pragma alloc_text (PAGE, MergePerformanceStates)
  34. #endif
  35. NTSTATUS
  36. InitializeDriver(
  37. IN PUNICODE_STRING ServiceKeyRegPath
  38. )
  39. /*++
  40. Routine Description:
  41. Initializes the LongHaul flags be getting information from the CPU and reading
  42. the HackFlagsOn and HackFlagsOff keys.
  43. Arguments:
  44. ServiceKeyRegPath - This proc drivers key in the registry
  45. Return Value:
  46. NTSTATUS - STATUS_SUCCESS or an error
  47. --*/
  48. {
  49. ULONG flags;
  50. LongHaulFlags = 0x0;
  51. // This driver is not MP safe, and most likely never will
  52. if ( Globals.SingleProcessorProfile == FALSE ) {
  53. return STATUS_DRIVER_UNABLE_TO_LOAD; // Lib ignores this return value
  54. }
  55. // Just loaded, there are no queued work items
  56. NextTransitionThrottle = INVALID_THROTTLE;
  57. IdentifyCPUVersion();
  58. // Add and remove flags according to registry
  59. // HackFlagsOn will be set, then
  60. // HackFlagsOff will be cleared
  61. GetRegistryDwordValue((PWCHAR) VIAC3_PARAMETERS_KEY,
  62. L"HackFlags",
  63. &flags);
  64. if( flags & DISABLE_ALL_HACK_FLAG ) {
  65. DebugPrint((WARN, "All legacy functionality disabled by DISABLE_ALL_HACK_FLAG.\n"));
  66. LongHaulFlags = 0x0;
  67. } else if( flags & NO_SOFTVID_HACK_FLAG ) {
  68. DebugPrint((WARN, "softVID disabled by NO_SOFTVID_HACK_FLAG.\n"));
  69. LongHaulFlags &= ~SUPPORTS_SOFTVID_FLAG;
  70. } else if( flags & NO_VOLTAGE_STEPPING_HACK_FLAG ) {
  71. DebugPrint((WARN, "Will not transition voltage in steps. Can cause crashes. Set by NO_VOLTAGE_STEPPING_HACK_FLAG.\n"));
  72. LongHaulFlags &= ~NEEDS_VOLTAGE_STEPPING_FLAG;
  73. }
  74. InitializeCPU();
  75. #ifdef DBG
  76. DebugShowCurrent();
  77. #endif
  78. return STATUS_SUCCESS;
  79. }
  80. NTSTATUS
  81. FASTCALL
  82. SetPerfLevel(
  83. IN UCHAR Throttle
  84. )
  85. /*++
  86. Routine Description:
  87. Arguments:
  88. Return Value:
  89. --*/
  90. {
  91. PFDO_DATA DeviceExtension;
  92. ULONG apicId;
  93. ULONG index = 0;
  94. DebugEnter();
  95. //
  96. // Get APIC Id and retrieve Device Extension index
  97. //
  98. if (!Globals.SingleProcessorProfile) {
  99. apicId = GetApicId();
  100. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  101. }
  102. //
  103. // Get the DeviceExtension.
  104. //
  105. DeviceExtension = DeviceExtensions[index];
  106. return SetPerfLevelGeneric(Throttle, DeviceExtension);
  107. }
  108. NTSTATUS
  109. FASTCALL
  110. SetThrottleLevel(
  111. IN UCHAR Throttle
  112. )
  113. /*++
  114. Routine Description:
  115. Arguments:
  116. Return Value:
  117. --*/
  118. {
  119. PFDO_DATA DeviceExtension;
  120. ULONG apicId;
  121. ULONG index = 0;
  122. DebugEnter();
  123. //
  124. // Get APIC Id and retrieve Device Extension index
  125. //
  126. if (!Globals.SingleProcessorProfile) {
  127. apicId = GetApicId();
  128. index = Globals.ProcInfo.ApicIdToDevExtIndex[apicId];
  129. }
  130. //
  131. // Get the DeviceExtension.
  132. //
  133. DeviceExtension = DeviceExtensions[index];
  134. //
  135. // Since this driver does not support Functional Fixed Hardware, we
  136. // use generic method.
  137. //
  138. return SetThrottleLevelGeneric(Throttle, DeviceExtension);
  139. }
  140. NTSTATUS
  141. GetProcessorBrandString (
  142. PUCHAR BrandString,
  143. PULONG Size
  144. )
  145. /*++
  146. Routine Description:
  147. Arguments:
  148. Return Value:
  149. --*/
  150. {
  151. //
  152. // With the generic driver we only try to find the Processor Brand String
  153. // via the CPUID
  154. //
  155. return GetCPUIDProcessorBrandString(BrandString, Size);
  156. }
  157. NTSTATUS
  158. InitializeAcpi2PStates(
  159. IN PFDO_DATA DevExt
  160. )
  161. /*++
  162. Routine Description:
  163. Arguments:
  164. Return Value:
  165. --*/
  166. {
  167. NTSTATUS status;
  168. status = InitializeAcpi2PStatesGeneric(DevExt);
  169. //
  170. // Check that we only access FFH
  171. //
  172. if (NT_SUCCESS(status)) {
  173. if ((DevExt->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceFixedFunction) ||
  174. (DevExt->PctPackage.Status.AddressSpaceID != AcpiGenericSpaceFixedFunction)) {
  175. DebugPrint((ERROR, "This driver ONLY supports FFH addresses for Acpi 2.0\n"));
  176. status = STATUS_NOT_FOUND;
  177. goto InitializeAcpi2PStatesExit;
  178. }
  179. //
  180. // Walk through _PSS states to calculate latency values
  181. //
  182. ValidatePssLatencyValues(DevExt);
  183. //
  184. // Need to merge this new data with our perfstates
  185. //
  186. MergePerformanceStates(DevExt);
  187. }
  188. InitializeAcpi2PStatesExit:
  189. return status;
  190. }
  191. NTSTATUS
  192. InitializeAcpi2Cstates(
  193. PFDO_DATA DevExt
  194. )
  195. /*++
  196. Routine Description:
  197. This function looks to see if there is an ACPI 2.0 _CST object in the
  198. namespace, and, if there is, it replaces the functions found by
  199. InitializeAcpi1Cstates.
  200. Further note: This function leaves the filling in of throttling functions
  201. to the InitializePerformanceStates functions.
  202. Arguments:
  203. DeviceExtension
  204. Return Value:
  205. A NTSTATUS code to indicate the result of the initialization.
  206. --*/
  207. {
  208. ULONG apicId;
  209. ULONG index = 0;
  210. DebugEnter();
  211. //
  212. // Record the address of this processor's DeviceExtension, as the
  213. // throttling API doesn't give it to us.
  214. //
  215. if (!Globals.SingleProcessorProfile) {
  216. //
  217. // save the index into the DeviceExtension[] for later retrieval based
  218. // on APIC Id.
  219. //
  220. apicId = Globals.ProcInfo.ProcIdToApicId[DevExt->ProcObjInfo.PhysicalID];
  221. Globals.ProcInfo.ApicIdToDevExtIndex[apicId] = DevExtIndex;
  222. index = DevExtIndex++;
  223. }
  224. //
  225. // save Device Extension pointer
  226. //
  227. DeviceExtensions[index] = DevExt;
  228. //
  229. // This processor driver only supports I/O Space based Cstates.
  230. // InitializeAcpi2IoSpaceCstates() will fail if it finds Cstates with
  231. // non AcpiGenericSpaceIO type addresses.
  232. //
  233. return InitializeAcpi2IoSpaceCstates(DevExt);
  234. }
  235. NTSTATUS
  236. MergePerformanceStates(
  237. IN PFDO_DATA DeviceExtension
  238. )
  239. /*++
  240. Routine Description:
  241. This routine looks at the performance states stored in the device extension.
  242. Arguments:
  243. DeviceExtension
  244. Return Value:
  245. A NTSTATUS code to indicate the result of the initialization.
  246. NOTE:
  247. - The caller must hold PerfStateLock.
  248. - This is called during START_DEVICE, and after recieving a Notify(0x80)
  249. on the processor.
  250. --*/
  251. {
  252. DebugEnter();
  253. return MergePerformanceStatesGeneric(DeviceExtension);
  254. }
  255. NTSTATUS
  256. Acpi2PerfStateTransition(
  257. IN PFDO_DATA DeviceExtension,
  258. IN ULONG NewState
  259. )
  260. /*++
  261. Routine Description:
  262. This routine changes the performance state of the processor
  263. based on ACPI 2.0 performance state objects.
  264. Arguments:
  265. DeviceExtension - The device extension for this object
  266. NewState - Index into _PSS object
  267. Return Value:
  268. None
  269. --*/
  270. {
  271. NTSTATUS status = STATUS_SUCCESS;
  272. DebugEnter();
  273. DebugAssert(DeviceExtension->PssPackage)
  274. DebugAssert(NewState >= DeviceExtension->PpcResult);
  275. DebugAssert(NewState < DeviceExtension->PssPackage->NumPStates);
  276. DebugAssert(DeviceExtension->PssPackage->State[NewState].CoreFrequency);
  277. if (DeviceExtension->PctPackage.Control.AddressSpaceID != AcpiGenericSpaceFixedFunction) {
  278. DebugAssert(!"Acpi2PerfStateTransition ONLY understands FFH addresses");
  279. status = STATUS_UNSUCCESSFUL;
  280. goto Acpi2PerfStateTransitionExit;
  281. }
  282. if (NewState == DeviceExtension->CurrentPssState) {
  283. DebugPrint((WARN, "Acpi2PerfStateTransition() CurrentState == TargetState, exiting...\n"));
  284. goto Acpi2PerfStateTransitionExit;
  285. }
  286. // Queue the transition so it always run at PASSIVE irql
  287. status = QueueTransition( DeviceExtension, NewState);
  288. if( NT_SUCCESS(status) ) {
  289. DeviceExtension->CurrentPssState = NewState;
  290. }
  291. Acpi2PerfStateTransitionExit:
  292. DebugExitStatus(status);
  293. return status;
  294. }
  295. NTSTATUS
  296. ProcessResumeFromSleepState(
  297. SYSTEM_POWER_STATE PreviousState,
  298. PFDO_DATA DeviceExtension
  299. )
  300. /*++
  301. Routine Description:
  302. Arguments:
  303. Return Value:
  304. --*/
  305. {
  306. DebugEnter();
  307. //
  308. // if we are resuming from Hibernate, and this is an Acpi 2.0 system,
  309. // we must re-claim perf state and cstate control from the bios.
  310. //
  311. if (PreviousState == PowerSystemHibernate) {
  312. if (DeviceExtension->PssPackage) {
  313. AssumeProcessorPerformanceControl();
  314. }
  315. if (DeviceExtension->CstPresent) {
  316. AssumeCStateControl();
  317. }
  318. }
  319. //
  320. // restore previous state
  321. //
  322. return RestoreToSavedPerformanceState(DeviceExtension);
  323. }
  324. NTSTATUS
  325. ProcessSuspendToSleepState(
  326. SYSTEM_POWER_STATE TargetState,
  327. PFDO_DATA DeviceExtension
  328. )
  329. /*++
  330. Routine Description:
  331. Arguments:
  332. Return Value:
  333. --*/
  334. {
  335. DebugEnter();
  336. //
  337. // save current state, transition to lowest non-throttled perf state
  338. //
  339. return SaveCurrentStateGoToLowVolts(DeviceExtension);
  340. }