Leaked source code of windows server 2003
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.

230 lines
3.6 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Copyright (c) 1998 Intel Corporation
  4. Module Name:
  5. intsupc.c
  6. Abstract:
  7. This module implements ruotines for interrupt support.
  8. Author:
  9. Bernard Lint 5-May-1998
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. __inline
  16. VOID
  17. KiLowerIrqlSpecial(KIRQL NewIrql)
  18. {
  19. __setReg( CV_IA64_SaTPR, (NewIrql << TPR_IRQL_SHIFT));
  20. KeGetPcr()->CurrentIrql = NewIrql;
  21. }
  22. VOID
  23. KiDispatchSoftwareInterrupt (
  24. KIRQL Irql
  25. )
  26. /*++
  27. Routine Description:
  28. Dispatch pending software interrupt
  29. Arguments:
  30. Irql (a0) - Software interrupt to dispatch
  31. Return Value:
  32. None.
  33. Notes:
  34. Interrupts disabled on entry/return.
  35. The function is only called by KiCheckForSoftwareInterrupt that passes an
  36. Irql value of APC_LEVEL or DISPATCH_LEVEL.
  37. --*/
  38. {
  39. KiLowerIrqlSpecial(Irql); // set IRQL
  40. if (Irql == APC_LEVEL) {
  41. PCR->ApcInterrupt = 0;
  42. _enable();
  43. //
  44. // Dispatch APC Interrupt via direct call to KiDeliverApc
  45. //
  46. KiDeliverApc(KernelMode,NULL,NULL);
  47. _disable();
  48. } else {
  49. PCR->DispatchInterrupt = 0;
  50. _enable();
  51. //
  52. // Dispatch DPC Interrupt
  53. //
  54. KiDispatchInterrupt();
  55. _disable();
  56. }
  57. }
  58. VOID
  59. KiCheckForSoftwareInterrupt (
  60. KIRQL RequestIrql
  61. )
  62. /*++
  63. Routine Description:
  64. Check for and dispatch pending software interrupts
  65. Arguments:
  66. Irql (a0) - New, lower IRQL
  67. Return Value:
  68. None.
  69. Notes:
  70. Caller must check IRQL has dropped below s/w IRQL level
  71. --*/
  72. {
  73. BOOLEAN InterruptState;
  74. InterruptState = KeDisableInterrupts();
  75. if (RequestIrql == APC_LEVEL) {
  76. //
  77. // Dispatch only DPC requests
  78. //
  79. while (PCR->DispatchInterrupt) {
  80. KiDispatchSoftwareInterrupt(DISPATCH_LEVEL);
  81. }
  82. } else {
  83. //
  84. // Dispatch either APC or DPC
  85. //
  86. while (PCR->SoftwareInterruptPending) {
  87. KIRQL Irql;
  88. if (PCR->DispatchInterrupt) {
  89. Irql = DISPATCH_LEVEL;
  90. } else {
  91. Irql = APC_LEVEL;
  92. }
  93. KiDispatchSoftwareInterrupt(Irql);
  94. }
  95. }
  96. //
  97. // Lower IRQL to the requested level, restore interrupts and
  98. // return.
  99. //
  100. KiLowerIrqlSpecial(RequestIrql);
  101. KeEnableInterrupts(InterruptState);
  102. }
  103. VOID
  104. KiRequestSoftwareInterrupt (
  105. KIRQL RequestIrql
  106. )
  107. /*++
  108. Routine Description:
  109. This function requests a software interrupt at the specified IRQL
  110. level.
  111. Arguments:
  112. RequestIrql (a0) - Supplies the request IRQL value.
  113. Return Value:
  114. None.
  115. --*/
  116. {
  117. KIRQL Irql;
  118. #if DEBUG
  119. if ((RequestIrql < APC_LEVEL) || (RequestIrql > DISPATCH_LEVEL))
  120. KeBugCheckEx(INVALID_SOFTWARE_INTERRUPT, RequestIrql, 0, 0, 0);
  121. #endif
  122. ((PUCHAR)&PCR->SoftwareInterruptPending)[RequestIrql-APC_LEVEL] = 1;
  123. Irql = KeGetCurrentIrql();
  124. if (Irql < RequestIrql) {
  125. KeLowerIrql (Irql);
  126. }
  127. }
  128. #undef KeRaiseIrql
  129. VOID
  130. KeRaiseIrql (
  131. IN KIRQL NewIrql,
  132. OUT PKIRQL OldIrql
  133. )
  134. /*++
  135. Routine Description:
  136. This function raises the current IRQL to the specified value and returns
  137. the previous IRQL.
  138. Arguments:
  139. NewIrql - Supplies the new IRQL value.
  140. OldIrql - Supplies a pointer to the location where the old IRQL is stored.
  141. Return Value:
  142. None.
  143. --*/
  144. {
  145. *OldIrql = KfRaiseIrql(NewIrql);
  146. }