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.

309 lines
5.5 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. mcsysint.c
  5. Abstract:
  6. This module implements the HAL routines to enable/disable system
  7. interrupts.
  8. Author:
  9. John Vert (jvert) 22-Jul-1991
  10. Revision History:
  11. Forrest Foltz (forrestf) 27-Oct-2000
  12. Ported from mcsysint.asm to mcsysint.c
  13. Revision History:
  14. --*/
  15. #include "halcmn.h"
  16. BOOLEAN
  17. HalBeginSystemInterrupt (
  18. IN KIRQL Irql,
  19. IN ULONG Vector,
  20. OUT PKIRQL OldIrql
  21. )
  22. /*++
  23. Routine Description:
  24. This routine is used to dismiss the specified vector number. It is called
  25. before any interrupt service routine code is executed.
  26. N.B. This routine does NOT preserve EAX or EBX
  27. On a UP machine the interrupt dismissed at BeginSystemInterrupt time.
  28. This is fine since the irql is being raise to mask it off.
  29. HalEndSystemInterrupt is simply a LowerIrql request.
  30. Arguments:
  31. Irql - Supplies the IRQL to raise to
  32. Vector - Supplies the vector of the interrupt to be processed
  33. OldIrql- Location to return OldIrql
  34. Return Value:
  35. FALSE - Interrupt is spurious and should be ignored
  36. TRUE - Interrupt successfully dismissed and Irql raised.
  37. --*/
  38. {
  39. UCHAR irq;
  40. UCHAR isr;
  41. PCHAR picPort;
  42. ULONG mask;
  43. PKPCR pcr;
  44. irq = (UCHAR)(Vector - PRIMARY_VECTOR_BASE);
  45. if (irq == 0x07) {
  46. //
  47. // Check to see if this is a spurious interrupt
  48. //
  49. WRITE_PORT_UCHAR(PIC1_PORT0,OCW3_READ_ISR);
  50. IO_DELAY();
  51. isr = READ_PORT_UCHAR(PIC1_PORT0);
  52. IO_DELAY();
  53. if ((isr & 0x8000) == 0) {
  54. //
  55. // This is a spurious interrupt
  56. //
  57. HalpEnableInterrupts();
  58. return FALSE;
  59. }
  60. //
  61. // Non-spurious interrupt, fall through to normal processing
  62. //
  63. } else if (irq == 0x0F) {
  64. //
  65. // Check to see if this is a spurious interrupt
  66. //
  67. WRITE_PORT_UCHAR(PIC2_PORT0,OCW3_READ_ISR);
  68. IO_DELAY();
  69. isr = READ_PORT_UCHAR(PIC2_PORT0);
  70. IO_DELAY();
  71. if ((isr & 0x8000) == 0) {
  72. //
  73. // This is a spurious interrupt. Dismiss the master PIC's
  74. // irq2.
  75. //
  76. WRITE_PORT_UCHAR(PIC1_PORT0,PIC2_EOI);
  77. IO_DELAY();
  78. HalpEnableInterrupts();
  79. return FALSE;
  80. }
  81. //
  82. // Non-spurious interrupt, fall through to normal processing
  83. //
  84. }
  85. //
  86. // Store the old IRQL, raise IRQL to the requested level
  87. //
  88. pcr = KeGetPcr();
  89. *OldIrql = pcr->Irql;
  90. pcr->Irql = Irql;
  91. //
  92. // Mask off interrupts according to the supplied IRQL
  93. //
  94. mask = Halp8259MaskTable[Irql];
  95. mask |= pcr->Idr;
  96. SET_8259_MASK((USHORT)mask);
  97. //
  98. // Dismiss the interrupt
  99. //
  100. if (irq < 8) {
  101. //
  102. // Interrupt came from the master, send it a specific eoi.
  103. //
  104. WRITE_PORT_UCHAR(PIC1_PORT0,PIC1_EOI_MASK | irq);
  105. IO_DELAY();
  106. } else {
  107. //
  108. // Interrupt came from the slave, send the slave a non-specific EOI
  109. // and send the master an irq-2 specific EOI
  110. //
  111. WRITE_PORT_UCHAR(PIC2_PORT0,OCW2_NON_SPECIFIC_EOI);
  112. IO_DELAY();
  113. WRITE_PORT_UCHAR(PIC1_PORT0,PIC2_EOI);
  114. IO_DELAY();
  115. }
  116. PIC1DELAY();
  117. HalpEnableInterrupts();
  118. return TRUE;
  119. }
  120. VOID
  121. HalDisableSystemInterrupt(
  122. IN ULONG Vector,
  123. IN KIRQL Irql
  124. )
  125. /*++
  126. Routine Description:
  127. Disables a system interrupt.
  128. Arguments:
  129. Vector - Supplies the vector of the interrupt to be disabled
  130. Irql - Supplies the interrupt level of the interrupt to be disabled
  131. Return Value:
  132. None.
  133. --*/
  134. {
  135. USHORT mask;
  136. UCHAR irq;
  137. ULONG flags;
  138. PKPCR pcr;
  139. USHORT imr;
  140. PUCHAR picPort;
  141. irq = (UCHAR)(Vector - PRIMARY_VECTOR_BASE);
  142. mask = 1 << irq;
  143. flags = HalpDisableInterrupts();
  144. pcr = KeGetPcr();
  145. pcr->Idr |= mask;
  146. //
  147. // Mask the irq in the 8259.
  148. //
  149. mask |= GET_8259_MASK();
  150. SET_8259_MASK(mask);
  151. HalpRestoreInterrupts(flags);
  152. }
  153. BOOLEAN
  154. HalEnableSystemInterrupt(
  155. IN ULONG Vector,
  156. IN KIRQL Irql,
  157. IN KINTERRUPT_MODE InterruptMode
  158. )
  159. /*++
  160. Routine Description:
  161. Enables a system interrupt
  162. Arguments:
  163. Vector - Supplies the vector of the interrupt to be enabled
  164. Irql - Supplies the interrupt level of the interrupt to be enabled.
  165. Return Value:
  166. FALSE in the case of an invalid parameter, TRUE otherwise.
  167. --*/
  168. {
  169. UCHAR irq;
  170. ULONG mask;
  171. USHORT edgeLevel;
  172. ULONG flags;
  173. PKPCR pcr;
  174. irq = (UCHAR)(Vector - PRIMARY_VECTOR_BASE);
  175. if (Vector < PRIMARY_VECTOR_BASE || irq > HIGH_LEVEL) {
  176. return FALSE;
  177. }
  178. mask = 1 << irq;
  179. //
  180. // Set the edge/level bit in the interrupt controller
  181. //
  182. edgeLevel = READ_PORT_USHORT_PAIR (EISA_EDGE_LEVEL0, EISA_EDGE_LEVEL1);
  183. edgeLevel |= mask;
  184. WRITE_PORT_USHORT_PAIR (EISA_EDGE_LEVEL0,
  185. EISA_EDGE_LEVEL1,
  186. (USHORT)edgeLevel);
  187. IO_DELAY();
  188. //
  189. // Disable interrupts and mask off the corresponding bit in the Idr.
  190. //
  191. HalpDisableInterrupts();
  192. pcr = KeGetPcr();
  193. mask = ~mask & pcr->Idr;
  194. pcr->Idr = mask;
  195. //
  196. // Get the PIC masks for the current Irql
  197. //
  198. mask |= Halp8259MaskTable[Irql];
  199. SET_8259_MASK((USHORT)mask);
  200. //
  201. // Enable interrupts and return success
  202. //
  203. HalpEnableInterrupts();
  204. return TRUE;
  205. }