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.

450 lines
10 KiB

  1. /*++
  2. Copyright(c) 1998 Microsoft Corporation
  3. Module Name:
  4. shared.c
  5. Abstract:
  6. routines shared outside of library
  7. Author:
  8. Todd Carpenter
  9. Environment:
  10. kernel mode
  11. Revision History:
  12. 03-28-01 : created, toddcar
  13. --*/
  14. #include "processor.h"
  15. NTSTATUS
  16. ValidatePssLatencyValues (
  17. IN PFDO_DATA DeviceExtension
  18. )
  19. /*++
  20. Routine Description:
  21. Arguments:
  22. Return Value:
  23. --*/
  24. {
  25. NTSTATUS status = STATUS_SUCCESS;
  26. ULONG savedState = INVALID_PERF_STATE;
  27. ULONG targetState;
  28. ULONG x;
  29. ULONG latency;
  30. LARGE_INTEGER start;
  31. LARGE_INTEGER end;
  32. LARGE_INTEGER freq;
  33. DebugEnter();
  34. DebugAssert(DeviceExtension);
  35. //
  36. // Save current state, go to highest perfstate available
  37. //
  38. if (DeviceExtension->CurrentPerfState != INVALID_PERF_STATE) {
  39. savedState = DeviceExtension->CurrentPerfState;
  40. }
  41. if (DeviceExtension->CurrentPerfState) {
  42. Acpi2PerfStateTransition(DeviceExtension, DeviceExtension->PpcResult);
  43. }
  44. //
  45. // Get Perf Counter Frequency
  46. //
  47. KeQueryPerformanceCounter(&freq);
  48. //
  49. // Walk though all available states, calulate transition latency
  50. //
  51. for (x = 0; x < DeviceExtension->PssPackage->NumPStates; x++) {
  52. targetState = DeviceExtension->PssPackage->NumPStates - x - 1;
  53. latency = 0;
  54. //
  55. // We should already be at PerfState == PpcResult,
  56. // and we can't go to a higher state
  57. //
  58. if (targetState < DeviceExtension->PpcResult) {
  59. continue;
  60. }
  61. start = KeQueryPerformanceCounter(NULL);
  62. status = Acpi2PerfStateTransition(DeviceExtension, targetState);
  63. end = KeQueryPerformanceCounter(NULL);
  64. //
  65. // Calculate transition latency.
  66. //
  67. if (NT_SUCCESS(status)) {
  68. latency = (ULONG)((end.QuadPart - start.QuadPart) * 1000000 / freq.QuadPart);
  69. }
  70. //
  71. // Record new latency value in unused BmLatency field
  72. //
  73. DeviceExtension->PssPackage->State[targetState].Latency = latency;
  74. }
  75. //
  76. // Restore saved Perf State
  77. //
  78. if (savedState != DeviceExtension->CurrentPerfState &&
  79. savedState != INVALID_PERF_STATE) {
  80. Acpi2PerfStateTransition(DeviceExtension, savedState);
  81. }
  82. return status;
  83. }
  84. ULONG
  85. ReadGenAddr(
  86. IN PGEN_ADDR GenAddr
  87. )
  88. {
  89. ULONG bitWidth;
  90. ULONG mask = 0;
  91. ULONG result = 0;
  92. DebugAssert(GenAddr);
  93. DebugAssert(GenAddr->BitWidth);
  94. DebugAssert(GenAddr->BitWidth <= 32);
  95. //
  96. // Figure out how wide our target register is.
  97. //
  98. bitWidth = GenAddr->BitWidth + GenAddr->BitOffset;
  99. if (bitWidth <= 8) {
  100. bitWidth = 8;
  101. } else if (bitWidth <= 16) {
  102. bitWidth = 16;
  103. } else {
  104. bitWidth = 32;
  105. }
  106. switch (GenAddr->AddressSpaceID) {
  107. case AcpiGenericSpaceIO:
  108. DebugAssert(!(GenAddr->Address.LowPart & 0Xffff0000));
  109. DebugAssert(GenAddr->Address.HighPart == 0);
  110. switch (bitWidth) {
  111. case 8:
  112. result = READ_PORT_UCHAR((PUCHAR)(UINT_PTR)GenAddr->Address.LowPart);
  113. break;
  114. case 16:
  115. result = READ_PORT_USHORT((PUSHORT)(UINT_PTR)GenAddr->Address.LowPart);
  116. break;
  117. case 32:
  118. result = READ_PORT_ULONG((PULONG)(UINT_PTR)GenAddr->Address.LowPart);
  119. break;
  120. default:
  121. return 0;
  122. }
  123. break;
  124. case AcpiGenericSpaceMemory:
  125. //
  126. // This code path depends on the fact that the addresses
  127. // in these structures have already been converted to
  128. // virtual addresses.
  129. //
  130. switch (bitWidth) {
  131. case 8:
  132. result = READ_REGISTER_UCHAR((PUCHAR)GenAddr->Address.QuadPart);
  133. break;
  134. case 16:
  135. result = READ_REGISTER_USHORT((PUSHORT)GenAddr->Address.QuadPart);
  136. break;
  137. case 32:
  138. result = READ_REGISTER_ULONG((PULONG)GenAddr->Address.QuadPart);
  139. break;
  140. default:
  141. return 0;
  142. }
  143. break;
  144. default:
  145. return 0;
  146. }
  147. //
  148. // If the register is not actually byte-aligned, correct for that.
  149. //
  150. if (result && (bitWidth != GenAddr->BitWidth)) {
  151. result >>= GenAddr->BitOffset;
  152. result &= ((0x1ul << GenAddr->BitWidth) - 1);
  153. }
  154. return result;
  155. }
  156. VOID
  157. WriteGenAddr(
  158. IN PGEN_ADDR GenAddr,
  159. IN ULONG Value
  160. )
  161. {
  162. ULONG bitWidth;
  163. ULONG data = 0;
  164. ULONG mask = 0;
  165. DebugAssert(GenAddr);
  166. DebugAssert(GenAddr->BitWidth);
  167. DebugAssert(GenAddr->BitWidth <= 32);
  168. //
  169. // Figure out how wide our target register is.
  170. //
  171. bitWidth = GenAddr->BitWidth + GenAddr->BitOffset;
  172. if (bitWidth <= 8) {
  173. bitWidth = 8;
  174. } else if (bitWidth <= 16) {
  175. bitWidth = 16;
  176. } else {
  177. bitWidth = 32;
  178. }
  179. switch (GenAddr->AddressSpaceID) {
  180. case AcpiGenericSpaceIO:
  181. DebugAssert(!(GenAddr->Address.LowPart & 0Xffff0000));
  182. DebugAssert(GenAddr->Address.HighPart == 0);
  183. switch(bitWidth) {
  184. case 8:
  185. DebugAssert(!(Value & 0xffffff00));
  186. if ((GenAddr->BitOffset != 0) || (GenAddr->BitWidth != bitWidth)) {
  187. data = READ_PORT_UCHAR((PUCHAR)(UINT_PTR)GenAddr->Address.LowPart);
  188. mask = (UCHAR)~0 >> (8 - GenAddr->BitWidth);
  189. mask = (UCHAR)~(mask << GenAddr->BitOffset);
  190. data &= mask;
  191. data |= (UCHAR)Value << GenAddr->BitOffset;
  192. } else {
  193. data = Value;
  194. }
  195. WRITE_PORT_UCHAR((PUCHAR)(UINT_PTR)GenAddr->Address.LowPart, (UCHAR)data);
  196. break;
  197. case 16:
  198. DebugAssert(!(Value & 0xffff0000));
  199. if ((GenAddr->BitOffset != 0) || (GenAddr->BitWidth != bitWidth)) {
  200. data = READ_PORT_USHORT((PUSHORT)(UINT_PTR)GenAddr->Address.LowPart);
  201. mask = (USHORT)~0 >> (16 - GenAddr->BitWidth);
  202. mask = (USHORT)~(mask << GenAddr->BitOffset);
  203. data &= mask;
  204. data |= (USHORT)Value << GenAddr->BitOffset;
  205. } else {
  206. data = Value;
  207. }
  208. WRITE_PORT_USHORT((PUSHORT)(UINT_PTR)GenAddr->Address.LowPart, (USHORT)data);
  209. break;
  210. case 32:
  211. if ((GenAddr->BitOffset != 0) || (GenAddr->BitWidth != bitWidth)) {
  212. data = READ_PORT_ULONG((PULONG)(UINT_PTR)GenAddr->Address.LowPart);
  213. mask = (ULONG)~0 >> (32 - GenAddr->BitWidth);
  214. mask = ~(mask << GenAddr->BitOffset);
  215. data &= mask;
  216. data |= Value << GenAddr->BitOffset;
  217. } else {
  218. data = Value;
  219. }
  220. WRITE_PORT_ULONG((PULONG)(UINT_PTR)GenAddr->Address.LowPart, data);
  221. break;
  222. default:
  223. return;
  224. }
  225. break;
  226. case AcpiGenericSpaceMemory:
  227. //
  228. // This code path depends on the fact that the addresses in these structures
  229. // have already been converted to virtual addresses.
  230. //
  231. switch (bitWidth) {
  232. case 8:
  233. DebugAssert(!(Value & 0xffffff00));
  234. if ((GenAddr->BitOffset != 0) || (GenAddr->BitWidth != bitWidth)) {
  235. data = READ_REGISTER_UCHAR((PUCHAR)GenAddr->Address.QuadPart);
  236. mask = (UCHAR)~0 >> (8 - GenAddr->BitWidth);
  237. mask = (UCHAR)~(mask << GenAddr->BitOffset);
  238. data &= mask;
  239. data |= (UCHAR)Value << GenAddr->BitOffset;
  240. } else {
  241. data = Value;
  242. }
  243. WRITE_REGISTER_UCHAR((PUCHAR)GenAddr->Address.QuadPart, (UCHAR)data);
  244. break;
  245. case 16:
  246. DebugAssert(!(Value & 0xffff0000));
  247. if ((GenAddr->BitOffset != 0) || (GenAddr->BitWidth != bitWidth)) {
  248. data = READ_REGISTER_USHORT((PUSHORT)GenAddr->Address.QuadPart);
  249. mask = (USHORT)~0 >> (16 - GenAddr->BitWidth);
  250. mask = (USHORT)~(mask << GenAddr->BitOffset);
  251. data &= mask;
  252. data |= (USHORT)Value << GenAddr->BitOffset;
  253. } else {
  254. data = Value;
  255. }
  256. WRITE_REGISTER_USHORT((PUSHORT)GenAddr->Address.QuadPart, (USHORT)data);
  257. break;
  258. case 32:
  259. if ((GenAddr->BitOffset != 0) || (GenAddr->BitWidth != bitWidth)) {
  260. data = READ_REGISTER_ULONG((PULONG)GenAddr->Address.QuadPart);
  261. mask = (ULONG)~0 >> (32 - GenAddr->BitWidth);
  262. mask = ~(mask << GenAddr->BitOffset);
  263. data &= mask;
  264. data |= Value << GenAddr->BitOffset;
  265. } else {
  266. data = Value;
  267. }
  268. WRITE_REGISTER_ULONG((PULONG)GenAddr->Address.QuadPart, data);
  269. break;
  270. default:
  271. return;
  272. }
  273. break;
  274. default:
  275. return;
  276. }
  277. }
  278. //
  279. // Misc Debug Routines
  280. //
  281. #if DBG
  282. VOID
  283. DumpPSS(
  284. IN PACPI_PSS_PACKAGE PStates
  285. )
  286. {
  287. ULONG x;
  288. PACPI_PSS_DESCRIPTOR pState;
  289. DebugAssert(PStates);
  290. DebugPrint((TRACE, "\n"));
  291. DebugPrint((TRACE, "_PSS:\n"));
  292. for (x = 0; x < PStates->NumPStates; x++) {
  293. pState = &PStates->State[x];
  294. DebugPrint((TRACE, "State: #%u\n", x));
  295. DebugPrint((TRACE, " Core Frequency %u mhz\n",pState->CoreFrequency));
  296. DebugPrint((TRACE, " Power %u mW\n", pState->Power));
  297. DebugPrint((TRACE, " Transition Latency %u us\n", pState->Latency));
  298. DebugPrint((TRACE, " Bus Master Latency %u us\n", pState->BmLatency));
  299. DebugPrint((TRACE, " Control value 0x%x\n", pState->Control));
  300. DebugPrint((TRACE, " Status value 0x%x\n", pState->Status));
  301. DebugPrint((TRACE, "\n"));
  302. }
  303. }
  304. #endif