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.

236 lines
4.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. pmtimer.c
  5. Abstract:
  6. This module implements the code for ACPI-related timer
  7. functions.
  8. Author:
  9. Jake Oshins (jakeo) March 28, 1997
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. Split from pmclock.asm due to PIIX4 bugs.
  14. Forrest Foltz (forrestf) 23-Oct-2000
  15. Ported from pmtimer.asm to pmtimer.c
  16. --*/
  17. #include <halp.h>
  18. #include <ntacpi.h>
  19. //
  20. // HalpCurrentTime is the value of the hardware timer. It is updated at
  21. // every timer tick.
  22. //
  23. volatile ULONG64 HalpCurrentTime;
  24. //
  25. // HalpHardwareTimeRollover represents the maximum count + 1 of the
  26. // hardware timer.
  27. //
  28. // The hardware is either 24- or 32-bits. HalpHardwareTimeRollover will
  29. // therefore have a vale of either 0x1000000 or 0x100000000.
  30. //
  31. // ACPI generates an interrupt whenever the MSb of the hardware timer
  32. // changes.
  33. //
  34. ULONG64 HalpHardwareTimeRollover;
  35. ULONG64 HalpTimeBias;
  36. //
  37. // HalpCurrentTimePort is the port number of the 32-bit hardware timer.
  38. //
  39. ULONG HalpCurrentTimePort;
  40. #if DBG
  41. UCHAR TimerPerf[4096];
  42. ULONG TimerPerfIndex = 0;
  43. #endif
  44. #define MSBMASK24 0x00800000
  45. #define MSBMASK32 0x80000000
  46. ULONG TimerInfo[] = {
  47. 0,
  48. 0,
  49. 0,
  50. 0,
  51. MSBMASK24,
  52. 0,
  53. 0,
  54. 0,
  55. 2,
  56. 2 };
  57. ULONG64
  58. HalpQueryPerformanceCounter (
  59. VOID
  60. )
  61. {
  62. ULONG64 currentTime;
  63. ULONG hardwareTime;
  64. ULONG lastHardwareTime;
  65. //
  66. // Get a local copy of HalpCurrentTime and the value of the hardware
  67. // timer, in that order.
  68. //
  69. currentTime = HalpCurrentTime;
  70. hardwareTime = READ_PORT_ULONG(UlongToPtr(HalpCurrentTimePort));
  71. //
  72. // Extract the hardware portion of the currentTime.
  73. //
  74. lastHardwareTime = (ULONG)(currentTime & (HalpHardwareTimeRollover - 1));
  75. //
  76. // Replace the lastHardwareTime component of currentTime with the
  77. // current hardware time.
  78. //
  79. currentTime ^= lastHardwareTime;
  80. currentTime |= hardwareTime;
  81. //
  82. // Check and compensate for hardware timer rollover
  83. //
  84. if (lastHardwareTime > hardwareTime) {
  85. currentTime += HalpHardwareTimeRollover;
  86. }
  87. return currentTime;
  88. }
  89. LARGE_INTEGER
  90. HalpAcpiTimerQueryPerfCount (
  91. OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
  92. )
  93. /*++
  94. Routine Description:
  95. This routine returns current 64-bit performance counter and,
  96. optionally, the Performance Frequency.
  97. N.B. The performace counter returned by this routine is
  98. not necessary the value when this routine is just entered.
  99. The value returned is actually the counter value at any point
  100. between the routine is entered and is exited.
  101. Arguments:
  102. PerformanceFrequency - optionally, supplies the address of a variable
  103. variable to receive the performance counter frequency.
  104. Return Value:
  105. Current value of the performance counter will be returned.
  106. --*/
  107. {
  108. LARGE_INTEGER time;
  109. if (PerformanceFrequency != NULL) {
  110. PerformanceFrequency->QuadPart = PM_TMR_FREQ;
  111. }
  112. time.QuadPart = HalpQueryPerformanceCounter() + HalpTimeBias;
  113. return time;
  114. }
  115. VOID
  116. HalAcpiTimerCarry (
  117. VOID
  118. )
  119. /*++
  120. Routine Description:
  121. This routine is called to service the PM timer carry interrupt
  122. N.B. This function is called at interrupt time and assumes the
  123. caller clears the interrupt
  124. Arguments:
  125. None
  126. Return Value:
  127. None
  128. --*/
  129. {
  130. ULONG hardwareTime;
  131. ULONG64 currentTime;
  132. ULONG64 halfRollover;
  133. currentTime = HalpCurrentTime;
  134. hardwareTime = READ_PORT_ULONG(UlongToPtr(HalpCurrentTimePort));
  135. //
  136. // ACPI generates an interrupt whenever the MSb of the hardware timer
  137. // changes. Each interrupt represents, therefore, half a rollover.
  138. //
  139. halfRollover = HalpHardwareTimeRollover / 2;
  140. currentTime += halfRollover;
  141. //
  142. // Make sure the MSb of the hardware matches the software MSb. Breaking
  143. // into the debugger might have gotten these out of sync.
  144. //
  145. currentTime += halfRollover & (currentTime ^ hardwareTime);
  146. //
  147. // Finally, store the new current time back into the global
  148. //
  149. HalpCurrentTime = currentTime;
  150. }
  151. #if 0
  152. VOID
  153. HalaAcpiTimerInit(
  154. IN ULONG TimerPort,
  155. IN BOOLEAN TimerValExt
  156. )
  157. {
  158. HalpCurrentTimePort = TimerPort;
  159. if (TimerValExt) {
  160. HalpHardwareTimeRollover = 0x100000000;
  161. } else {
  162. HalpHardwareTimeRollover = 0x1000000;
  163. }
  164. }
  165. #endif