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.

289 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. interupt.c
  5. Abstract:
  6. This module contains code to support events generated by the
  7. sd controller.
  8. Author:
  9. Neil Sandlin (neilsa) 1-Jan-2002
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "pch.h"
  15. VOID
  16. SdbusEventWorkItemProc(
  17. IN PDEVICE_OBJECT Fdo,
  18. IN PVOID Context
  19. );
  20. VOID
  21. SdbusReflectCardInterrupt(
  22. IN PDEVICE_OBJECT Fdo
  23. );
  24. BOOLEAN
  25. SdbusInterrupt(
  26. IN PKINTERRUPT InterruptObject,
  27. PVOID Context
  28. )
  29. /*++
  30. Routine Description:
  31. interrupt handler
  32. Arguments:
  33. InterruptObject - Pointer to the interrupt object.
  34. Context - Pointer to the device context.
  35. Return Value:
  36. Status
  37. --*/
  38. {
  39. PFDO_EXTENSION fdoExtension;
  40. ULONG eventMask;
  41. fdoExtension=((PDEVICE_OBJECT)Context)->DeviceExtension;
  42. if (fdoExtension->Flags & SDBUS_FDO_OFFLINE) {
  43. return FALSE;
  44. }
  45. eventMask = (*(fdoExtension->FunctionBlock->GetPendingEvents))(fdoExtension);
  46. if (eventMask) {
  47. fdoExtension->IsrEventStatus |= eventMask;
  48. (*(fdoExtension->FunctionBlock->DisableEvent))(fdoExtension, eventMask);
  49. //
  50. // Something changed out there.. could be
  51. // a card insertion/removal.
  52. // Request a DPC to check it out.
  53. //
  54. IoRequestDpc((PDEVICE_OBJECT) Context, NULL, NULL);
  55. }
  56. return (eventMask != 0);
  57. }
  58. BOOLEAN
  59. SdbusInterruptSynchronize(
  60. PFDO_EXTENSION fdoExtension
  61. )
  62. {
  63. fdoExtension->LatchedIsrEventStatus = fdoExtension->IsrEventStatus;
  64. fdoExtension->IsrEventStatus = 0;
  65. return TRUE;
  66. }
  67. VOID
  68. SdbusInterruptDpc(
  69. IN PKDPC Dpc,
  70. IN PDEVICE_OBJECT DeviceObject,
  71. IN PVOID SystemContext1,
  72. IN PVOID SystemContext2
  73. )
  74. /*++
  75. Routine Description:
  76. This DPC is just an intermediate step in getting to the main DPC
  77. handler. This is used to "debounce" hardware and give it some time after
  78. the physical interrupt has come in.
  79. Arguments:
  80. DeviceObject - Pointer to the device object.
  81. Return Value:
  82. --*/
  83. {
  84. PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  85. static ULONG IoWorkerEventTypes[] = {SDBUS_EVENT_CARD_RW_END,
  86. SDBUS_EVENT_BUFFER_EMPTY,
  87. SDBUS_EVENT_BUFFER_FULL,
  88. SDBUS_EVENT_CARD_RESPONSE,
  89. 0};
  90. UCHAR i;
  91. ULONG acknowledgedEvents;
  92. if (fdoExtension->Flags & SDBUS_FDO_OFFLINE) {
  93. return;
  94. }
  95. KeSynchronizeExecution(fdoExtension->SdbusInterruptObject, SdbusInterruptSynchronize, fdoExtension);
  96. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: Event Status %08x\n", fdoExtension->LatchedIsrEventStatus));
  97. if (fdoExtension->LatchedIsrEventStatus & SDBUS_EVENT_INSERTION) {
  98. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: Card Insertion\n"));
  99. (*(fdoExtension->FunctionBlock->AcknowledgeEvent))(fdoExtension, SDBUS_EVENT_INSERTION);
  100. fdoExtension->LatchedIsrEventStatus &= ~SDBUS_EVENT_INSERTION;
  101. SdbusActivateSocket(DeviceObject, NULL, NULL);
  102. }
  103. if (fdoExtension->LatchedIsrEventStatus & SDBUS_EVENT_REMOVAL) {
  104. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: Card Removal\n"));
  105. (*(fdoExtension->FunctionBlock->AcknowledgeEvent))(fdoExtension, SDBUS_EVENT_REMOVAL);
  106. fdoExtension->LatchedIsrEventStatus &= ~SDBUS_EVENT_REMOVAL;
  107. SdbusActivateSocket(DeviceObject, NULL, NULL);
  108. }
  109. acknowledgedEvents = 0;
  110. for(i = 0; IoWorkerEventTypes[i] != 0; i++) {
  111. if (fdoExtension->LatchedIsrEventStatus & IoWorkerEventTypes[i]) {
  112. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: received event %08x - %s\n",
  113. IoWorkerEventTypes[i], EVENT_STRING(IoWorkerEventTypes[i])));
  114. (*(fdoExtension->FunctionBlock->AcknowledgeEvent))(fdoExtension, IoWorkerEventTypes[i]);
  115. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: ack'd event %08x - %s\n",
  116. IoWorkerEventTypes[i], EVENT_STRING(IoWorkerEventTypes[i])));
  117. acknowledgedEvents |= IoWorkerEventTypes[i];
  118. fdoExtension->LatchedIsrEventStatus &= ~IoWorkerEventTypes[i];
  119. }
  120. }
  121. if (acknowledgedEvents) {
  122. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: dispatching event %08x\n", acknowledgedEvents));
  123. SdbusPushWorkerEvent(fdoExtension, acknowledgedEvents);
  124. }
  125. //
  126. // Now check to see if the card has interrupted, and call back to the function driver
  127. //
  128. if (fdoExtension->LatchedIsrEventStatus & SDBUS_EVENT_CARD_INTERRUPT) {
  129. DebugPrint((SDBUS_DEBUG_EVENT, "SdbusDpc: got CARD INTERRUPT\n"));
  130. SdbusReflectCardInterrupt(DeviceObject);
  131. fdoExtension->LatchedIsrEventStatus &= ~SDBUS_EVENT_CARD_INTERRUPT;
  132. }
  133. ASSERT(fdoExtension->LatchedIsrEventStatus == 0);
  134. return;
  135. }
  136. VOID
  137. SdbusReflectCardInterrupt(
  138. IN PDEVICE_OBJECT Fdo
  139. )
  140. {
  141. PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
  142. PDEVICE_OBJECT pdo;
  143. PPDO_EXTENSION pdoExtension;
  144. //
  145. // ISSUE: NEED TO IMPLEMENT:
  146. // need to queue an IoWorker packet to read the CCCR and find out which
  147. // function is interrupting. For now, assume there is only a single I/O function,
  148. // and use the first callback found.
  149. //
  150. for (pdo = fdoExtension->PdoList; pdo != NULL; pdo = pdoExtension->NextPdoInFdoChain) {
  151. pdoExtension = pdo->DeviceExtension;
  152. if (pdoExtension->Flags & SDBUS_PDO_GENERATES_IRQ) {
  153. if (pdoExtension->Flags & SDBUS_PDO_DPC_CALLBACK) {
  154. pdoExtension->Flags |= SDBUS_PDO_CALLBACK_IN_SERVICE;
  155. (pdoExtension->CallbackRoutine)(pdoExtension->CallbackRoutineContext, 0);
  156. } else {
  157. pdoExtension->Flags |= SDBUS_PDO_CALLBACK_REQUESTED;
  158. KeSetEvent(&fdoExtension->CardInterruptEvent, 0, FALSE);
  159. }
  160. }
  161. }
  162. }
  163. VOID
  164. SdbusEventWorkItemProc(
  165. IN PDEVICE_OBJECT Fdo,
  166. IN PVOID Context
  167. )
  168. {
  169. PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension;
  170. PKEVENT Events[2] = {&fdoExtension->CardInterruptEvent, &fdoExtension->WorkItemExitEvent};
  171. PDEVICE_OBJECT pdo;
  172. PPDO_EXTENSION pdoExtension;
  173. NTSTATUS status;
  174. while(TRUE){
  175. status = KeWaitForMultipleObjects(2, Events, WaitAny,
  176. Executive, KernelMode, FALSE,
  177. NULL, NULL);
  178. if ((fdoExtension->Flags & SDBUS_FDO_WORK_ITEM_ACTIVE) == 0) {
  179. break;
  180. }
  181. for (pdo = fdoExtension->PdoList; pdo != NULL; pdo = pdoExtension->NextPdoInFdoChain) {
  182. pdoExtension = pdo->DeviceExtension;
  183. if (pdoExtension->Flags & SDBUS_PDO_GENERATES_IRQ) {
  184. DebugPrint((SDBUS_DEBUG_CARD_EVT, "WorkItemProc: CallBack %08x %08x\n", pdoExtension->CallbackRoutine,
  185. pdoExtension->CallbackRoutineContext));
  186. ASSERT((pdoExtension->Flags & SDBUS_PDO_CALLBACK_IN_SERVICE) == 0);
  187. pdoExtension->Flags |= SDBUS_PDO_CALLBACK_IN_SERVICE;
  188. pdoExtension->Flags &= ~SDBUS_PDO_CALLBACK_REQUESTED;
  189. (pdoExtension->CallbackRoutine)(pdoExtension->CallbackRoutineContext, 0);
  190. }
  191. }
  192. }
  193. }