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.

296 lines
5.7 KiB

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