Windows NT 4.0 source code leak
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.

302 lines
5.9 KiB

4 years ago
  1. // #pragma comment(exestr, "@(#) xxcalstl.c 1.1 95/09/28 18:40:42 nec")
  2. /*++
  3. Copyright (c) 1991-1993 Microsoft Corporation
  4. Module Name:
  5. xxcalstl.c
  6. Abstract:
  7. This module implements the calibration of the stall execution HAL
  8. service, computes the count rate for the profile clock, and connects
  9. the clock and profile interrupts for a MIPS R3000 or R4000 system.
  10. Author:
  11. David N. Cutler (davec) 26-Apr-1991
  12. Environment:
  13. Kernel mode only.
  14. Revision History:
  15. Modification History:
  16. H001 Fri Aug 25 14:21:02 1995 kbnes!kisimoto
  17. - change scale factor down range. for 250MHz.
  18. --*/
  19. #include "halp.h"
  20. #include "stdio.h"
  21. //
  22. // Put all code for HAL initialization in the INIT section. It will be
  23. // deallocated by memory management when phase 1 initialization is
  24. // completed.
  25. //
  26. #if defined(ALLOC_PRAGMA)
  27. #pragma alloc_text(INIT, HalpCalibrateStall)
  28. #pragma alloc_text(INIT, HalpStallInterrupt)
  29. #endif
  30. //
  31. // Define global data used to calibrate and stall processor execution.
  32. //
  33. ULONG HalpProfileCountRate;
  34. ULONG volatile HalpStallEnd;
  35. ULONG HalpStallScaleFactor;
  36. ULONG volatile HalpStallStart;
  37. BOOLEAN
  38. HalpCalibrateStall (
  39. VOID
  40. )
  41. /*++
  42. Routine Description:
  43. This function calibrates the stall execution HAL service and connects
  44. the clock and profile interrupts to the appropriate NT service routines.
  45. N.B. This routine is only called during phase 1 initialization.
  46. Arguments:
  47. None.
  48. Return Value:
  49. A value of TRUE is returned if the calibration is successfully
  50. completed. Otherwise a value of FALSE is returned.
  51. --*/
  52. {
  53. ULONG Index;
  54. KIRQL OldIrql;
  55. //
  56. // Use a range of scale factors from 50ns down to 10ns assuming a
  57. // five instruction stall loop.
  58. //
  59. for (Index = 50; Index > 0; Index -= (Index < 20 ? 1 : 10)) {
  60. //
  61. // Disable all interrupts and establish calibration parameters.
  62. //
  63. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  64. //
  65. // Set the scale factor, stall count, starting stall count, and
  66. // ending stall count values.
  67. //
  68. PCR->StallScaleFactor = 1000 / (Index * 5);
  69. PCR->StallExecutionCount = 0;
  70. HalpStallStart = 0;
  71. HalpStallEnd = 0;
  72. //
  73. // Enable interrupts and stall execution.
  74. //
  75. KeLowerIrql(OldIrql);
  76. //
  77. // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
  78. //
  79. KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
  80. //
  81. // If both the starting and ending stall counts have been captured,
  82. // then break out of loop.
  83. //
  84. if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
  85. break;
  86. }
  87. }
  88. //
  89. // Compute the profile interrupt rate.
  90. //
  91. #if defined(R3000)
  92. HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT;
  93. #endif
  94. #if defined(R4000)
  95. HalpProfileCountRate =
  96. HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
  97. #endif
  98. //
  99. // Compute the stall execution scale factor.
  100. //
  101. HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
  102. ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
  103. if (HalpStallScaleFactor <= 0) {
  104. HalpStallScaleFactor = 1;
  105. }
  106. PCR->StallScaleFactor = HalpStallScaleFactor;
  107. //
  108. // Connect the real clock interrupt routine.
  109. //
  110. PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt0;
  111. //
  112. // Write the compare register and clear the count register, and
  113. // connect the profile interrupt.
  114. //
  115. #if defined(R4000)
  116. HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
  117. PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
  118. #endif
  119. return TRUE;
  120. }
  121. VOID
  122. KeStallExecutionProcessor (
  123. IN ULONG MicroSeconds
  124. )
  125. /*++
  126. Routine Description:
  127. This function stalls execution of the current processor for the specified
  128. number of microseconds.
  129. Arguments:
  130. MicroSeconds - Supplies the number of microseconds that execution is to
  131. be stalled.
  132. Return Value:
  133. None.
  134. --*/
  135. {
  136. ULONG Index;
  137. //
  138. // Use the stall scale factor to determine the number of iterations
  139. // the wait loop must be executed to stall the processor for the
  140. // specified number of microseconds.
  141. //
  142. Index = MicroSeconds * PCR->StallScaleFactor;
  143. do {
  144. PCR->StallExecutionCount += 1;
  145. Index -= 1;
  146. } while (Index > 0);
  147. return;
  148. }
  149. VOID
  150. HalpStallInterrupt (
  151. VOID
  152. )
  153. /*++
  154. Routine Description:
  155. This function serves as the stall calibration interrupt service
  156. routine. It is executed in response to system clock interrupts
  157. during the initialization of the HAL layer.
  158. Arguments:
  159. None.
  160. Return Value:
  161. None.
  162. --*/
  163. {
  164. //
  165. // Acknowledge the interval timer interrupt.
  166. //
  167. #if defined(_DUO_)
  168. READ_REGISTER_ULONG(&DMA_CONTROL->TimerInterruptAcknowledge.Long);
  169. #else
  170. READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long);
  171. #endif
  172. //
  173. // If this is the very first interrupt, then wait for the second
  174. // interrupt before starting the timing interval. Else, if this
  175. // the second interrupt, then capture the starting stall count
  176. // and clear the count register on R4000 processors. Else, if this
  177. // is the third interrupt, then capture the ending stall count and
  178. // the ending count register on R4000 processors. Else, if this is
  179. // the fourth or subsequent interrupt, then simply dismiss it.
  180. //
  181. if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
  182. HalpStallEnd = 1;
  183. } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
  184. HalpStallStart = PCR->StallExecutionCount;
  185. HalpStallEnd = 0;
  186. #if defined(R4000)
  187. HalpWriteCompareRegisterAndClear(0);
  188. #endif
  189. } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
  190. HalpStallEnd = PCR->StallExecutionCount;
  191. #if defined(R4000)
  192. HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
  193. #endif
  194. }
  195. return;
  196. }