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.

199 lines
2.9 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. VOID
  16. KiLowerIrqlSpecial(KIRQL);
  17. VOID
  18. KiDispatchSoftwareInterrupt (
  19. KIRQL Irql
  20. )
  21. /*++
  22. Routine Description:
  23. Dispatch pending software interrupt
  24. Arguments:
  25. Irql (a0) - Software interrupt to dispatch
  26. Return Value:
  27. None.
  28. Notes:
  29. Interrupts disabled on entry/return.
  30. The function is only called by KiCheckForSoftwareInterrupt that passes an
  31. Irql value of APC_LEVEL or DISPATCH_LEVEL.
  32. --*/
  33. {
  34. PKPRCB Prcb = KeGetCurrentPrcb();
  35. KiLowerIrqlSpecial(Irql); // set IRQL
  36. if (Irql == APC_LEVEL) {
  37. PCR->ApcInterrupt = 0;
  38. _enable();
  39. //
  40. // Dispatch APC Interrupt via direct call to KiDeliverApc
  41. //
  42. KiDeliverApc(KernelMode,NULL,NULL);
  43. _disable();
  44. } else {
  45. PCR->DispatchInterrupt = 0;
  46. _enable();
  47. //
  48. // Dispatch DPC Interrupt
  49. //
  50. KiDispatchInterrupt();
  51. _disable();
  52. }
  53. }
  54. VOID
  55. KiCheckForSoftwareInterrupt (
  56. KIRQL RequestIrql
  57. )
  58. /*++
  59. Routine Description:
  60. Check for and dispatch pending software interrupts
  61. Arguments:
  62. Irql (a0) - New, lower IRQL
  63. Return Value:
  64. None.
  65. Notes:
  66. Caller must check IRQL has dropped below s/w IRQL level
  67. --*/
  68. {
  69. BOOLEAN InterruptState;
  70. InterruptState = KeDisableInterrupts();
  71. if (RequestIrql == APC_LEVEL) {
  72. //
  73. // Dispatch only DPC requests
  74. //
  75. while (PCR->DispatchInterrupt) {
  76. KiDispatchSoftwareInterrupt(DISPATCH_LEVEL);
  77. }
  78. } else {
  79. //
  80. // Dispatch either APC or DPC
  81. //
  82. while (PCR->SoftwareInterruptPending) {
  83. KIRQL Irql;
  84. if (PCR->DispatchInterrupt) {
  85. Irql = DISPATCH_LEVEL;
  86. } else {
  87. Irql = APC_LEVEL;
  88. }
  89. KiDispatchSoftwareInterrupt(Irql);
  90. }
  91. }
  92. //
  93. // Lower IRQL to the requested level, restore interrupts and
  94. // return.
  95. //
  96. KiLowerIrqlSpecial(RequestIrql);
  97. KeEnableInterrupts(InterruptState);
  98. }
  99. VOID
  100. KiRequestSoftwareInterrupt (
  101. KIRQL RequestIrql
  102. )
  103. /*++
  104. Routine Description:
  105. This function requests a software interrupt at the specified IRQL
  106. level.
  107. Arguments:
  108. RequestIrql (a0) - Supplies the request IRQL value.
  109. Return Value:
  110. None.
  111. --*/
  112. {
  113. KIRQL Irql;
  114. #if DEBUG
  115. if ((RequestIrql < APC_LEVEL) || (RequestIrql > DISPATCH_LEVEL))
  116. KeBugCheckEx(INVALID_SOFTWARE_INTERRUPT, RequestIrql, 0, 0, 0);
  117. #endif
  118. ((PUCHAR)&PCR->SoftwareInterruptPending)[RequestIrql-APC_LEVEL] = 1;
  119. Irql = KeGetCurrentIrql();
  120. if (Irql < RequestIrql) {
  121. KeLowerIrql (Irql);
  122. }
  123. }