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.

295 lines
7.1 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. xxinitnt.c
  5. Abstract:
  6. This module implements the interrupt initialization for a MIPS R3000
  7. or R4000 system.
  8. Author:
  9. David N. Cutler (davec) 26-Apr-1991
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "halp.h"
  15. //
  16. // Define forward referenced prototypes.
  17. //
  18. VOID
  19. HalpCountInterrupt (
  20. VOID
  21. );
  22. //
  23. // Put all code for HAL initialization in the INIT section. It will be
  24. // deallocated by memory management when phase 1 initialization is
  25. // completed.
  26. //
  27. #if defined(ALLOC_PRAGMA)
  28. #pragma alloc_text(INIT, HalpInitializeInterrupts)
  29. #pragma alloc_text(INIT, HalpCountInterrupt)
  30. #endif
  31. //
  32. // Define global data for builtin device interrupt enables.
  33. //
  34. USHORT HalpBuiltinInterruptEnable;
  35. //
  36. // Define the IRQL mask and level mapping table.
  37. //
  38. // These tables are transfered to the PCR and determine the priority of
  39. // interrupts.
  40. //
  41. // N.B. The two software interrupt levels MUST be the lowest levels.
  42. //
  43. UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
  44. 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
  45. 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
  46. 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
  47. UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
  48. 0xfe, // IRQL 1
  49. 0xfc, // IRQL 2
  50. 0xf8, // IRQL 3
  51. 0xf0, // IRQL 4
  52. 0xe0, // IRQL 5
  53. 0xc0, // IRQL 6
  54. 0x80, // IRQL 7
  55. 0x00}; // IRQL 8
  56. VOID
  57. HalpCountInterrupt (
  58. VOID
  59. )
  60. /*++
  61. Routine Description:
  62. This function serves as the count/compare interrupt service routine
  63. early in the system initialization. Its only function is to field
  64. and acknowledge count/compare interrupts during the system boot process.
  65. Arguments:
  66. None.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. //
  72. // Acknowledge the count/compare interrupt.
  73. //
  74. HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
  75. return;
  76. }
  77. BOOLEAN
  78. HalpInitializeInterrupts (
  79. VOID
  80. )
  81. /*++
  82. Routine Description:
  83. This function initializes interrupts for a Jazz or Duo MIPS system.
  84. N.B. This function is only called during phase 0 initialization.
  85. Arguments:
  86. None.
  87. Return Value:
  88. A value of TRUE is returned if the initialization is successfully
  89. completed. Otherwise a value of FALSE is returned.
  90. --*/
  91. {
  92. USHORT DataShort;
  93. ULONG DataLong;
  94. ULONG Index;
  95. PKPRCB Prcb;
  96. //
  97. // Get the address of the processor control block for the current
  98. // processor.
  99. //
  100. Prcb = PCR->Prcb;
  101. //
  102. // Initialize the IRQL translation tables in the PCR. These tables are
  103. // used by the interrupt dispatcher to determine the new IRQL and the
  104. // mask value that is to be loaded into the PSR. They are also used by
  105. // the routines that raise and lower IRQL to load a new mask value into
  106. // the PSR.
  107. //
  108. for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
  109. PCR->IrqlMask[Index] = HalpIrqlMask[Index];
  110. }
  111. for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
  112. PCR->IrqlTable[Index] = HalpIrqlTable[Index];
  113. }
  114. //
  115. // Clear interprocessor, timer, EISA, local device, and DMA interrupt
  116. // enables.
  117. //
  118. #if defined(_DUO_)
  119. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
  120. 0);
  121. #endif
  122. //
  123. // If processor 0 is being initialized, then clear all builtin device
  124. // interrupt enables.
  125. //
  126. if (Prcb->Number == 0) {
  127. HalpBuiltinInterruptEnable = 0;
  128. }
  129. //
  130. // Disable individual device interrupts and make sure no device interrupts
  131. // are pending.
  132. //
  133. WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
  134. 0);
  135. #if defined(_DUO_)
  136. do {
  137. DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->LocalInterruptAcknowledge.Long) & 0x3ff;
  138. } while (DataLong != 0);
  139. //
  140. // If processor 0 is being initialized, then enable device interrupts.
  141. //
  142. if (Prcb->Number == 0) {
  143. DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
  144. DataLong |= ENABLE_DEVICE_INTERRUPTS;
  145. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
  146. DataLong);
  147. }
  148. #endif
  149. #if defined(_JAZZ_)
  150. do {
  151. DataShort = READ_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Source) & 0x3ff;
  152. } while (DataShort != 0);
  153. #endif
  154. //
  155. // If processor 0 is being initialized, then connect the interval timer
  156. // interrupt to the stall interrupt routine so the stall execution count
  157. // can be computed during phase 1 initialization. Otherwise, connect the
  158. // interval timer interrupt to the appropriate interrupt service routine
  159. // and set stall execution count from the computation made on processor
  160. // 0.
  161. //
  162. if (Prcb->Number == 0) {
  163. PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt;
  164. } else {
  165. PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt1;
  166. PCR->StallScaleFactor = HalpStallScaleFactor;
  167. }
  168. //
  169. // Initialize the interval timer to interrupt at the specified interval.
  170. //
  171. WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptInterval.Long, CLOCK_INTERVAL);
  172. //
  173. // Enable the interval timer interrupt on the current processor.
  174. //
  175. #if defined(_DUO_)
  176. DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
  177. DataLong |= ENABLE_TIMER_INTERRUPTS;
  178. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
  179. DataLong);
  180. #endif
  181. //
  182. // If processor 0 is being initialized, then connect the count/compare
  183. // interrupt to the count interrupt routine to handle early count/compare
  184. // interrupts during phase 1 initialization. Otherwise, connect the
  185. // count\comapre interrupt to the appropriate interrupt service routine.
  186. //
  187. if (Prcb->Number == 0) {
  188. PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
  189. } else {
  190. PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
  191. }
  192. //
  193. // Connect the interprocessor interrupt service routine and enable
  194. // interprocessor interrupts.
  195. //
  196. #if defined(_DUO_)
  197. PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt;
  198. DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
  199. DataLong |= ENABLE_IP_INTERRUPTS;
  200. WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
  201. DataLong);
  202. #endif
  203. //
  204. // Reserve the local device interrupt vector for exclusive use by the HAL.
  205. //
  206. PCR->ReservedVectors |= ((1 << DEVICE_LEVEL) | (1 << EISA_DEVICE_LEVEL));
  207. return TRUE;
  208. }