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.

372 lines
6.6 KiB

  1. /*++
  2. Module Name:
  3. waitmask.c
  4. Environment:
  5. Kernel mode
  6. Revision History :
  7. --*/
  8. #include "precomp.h"
  9. NTSTATUS
  10. MoxaStartMask(
  11. IN PMOXA_DEVICE_EXTENSION Extension
  12. )
  13. {
  14. PIO_STACK_LOCATION irpSp;
  15. PIRP newIrp;
  16. BOOLEAN setFirstStatus = FALSE;
  17. NTSTATUS firstStatus;
  18. do {
  19. irpSp = IoGetCurrentIrpStackLocation(Extension->CurrentMaskIrp);
  20. if (irpSp->Parameters.DeviceIoControl.IoControlCode ==
  21. IOCTL_SERIAL_SET_WAIT_MASK) {
  22. KeSynchronizeExecution(
  23. Extension->Interrupt,
  24. MoxaFinishOldWait,
  25. Extension
  26. );
  27. Extension->CurrentMaskIrp->IoStatus.Status = STATUS_SUCCESS;
  28. if (!setFirstStatus) {
  29. firstStatus = STATUS_SUCCESS;
  30. setFirstStatus = TRUE;
  31. }
  32. MoxaGetNextIrp(
  33. &Extension->CurrentMaskIrp,
  34. &Extension->MaskQueue,
  35. &newIrp,
  36. TRUE,
  37. Extension
  38. );
  39. }
  40. else {
  41. //
  42. // IOCTL_SERIAL_WAIT_ON_MASK
  43. //
  44. // First make sure that we have a non-zero mask.
  45. // If the app queues a wait on a zero mask it can't
  46. // be statisfied so it makes no sense to start it.
  47. //
  48. if ((!Extension->IsrWaitMask) || (Extension->CurrentWaitIrp)) {
  49. Extension->CurrentMaskIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  50. if (!setFirstStatus) {
  51. firstStatus = STATUS_INVALID_PARAMETER;
  52. setFirstStatus = TRUE;
  53. }
  54. MoxaGetNextIrp(
  55. &Extension->CurrentMaskIrp,
  56. &Extension->MaskQueue,
  57. &newIrp,
  58. TRUE,
  59. Extension
  60. );
  61. }
  62. else {
  63. KIRQL oldIrql;
  64. IoAcquireCancelSpinLock(&oldIrql);
  65. if (Extension->CurrentMaskIrp->Cancel) {
  66. Extension->CurrentMaskIrp->IoStatus.Status = STATUS_CANCELLED;
  67. IoReleaseCancelSpinLock(oldIrql);
  68. if (!setFirstStatus) {
  69. firstStatus = STATUS_CANCELLED;
  70. setFirstStatus = TRUE;
  71. }
  72. MoxaGetNextIrp(
  73. &Extension->CurrentMaskIrp,
  74. &Extension->MaskQueue,
  75. &newIrp,
  76. TRUE,
  77. Extension
  78. );
  79. }
  80. else {
  81. if (!setFirstStatus) {
  82. firstStatus = STATUS_PENDING;
  83. setFirstStatus = TRUE;
  84. IoMarkIrpPending(Extension->CurrentMaskIrp);
  85. }
  86. Extension->CurrentWaitIrp = Extension->CurrentMaskIrp;
  87. MOXA_INIT_REFERENCE(Extension->CurrentWaitIrp);
  88. IoSetCancelRoutine(
  89. Extension->CurrentWaitIrp,
  90. MoxaCancelWait
  91. );
  92. //
  93. // Since the cancel routine has a reference to
  94. // the irp we need to update the reference
  95. // count.
  96. //
  97. MOXA_INC_REFERENCE(Extension->CurrentWaitIrp);
  98. KeSynchronizeExecution(
  99. Extension->Interrupt,
  100. MoxaGiveWaitToIsr,
  101. Extension
  102. );
  103. IoReleaseCancelSpinLock(oldIrql);
  104. MoxaGetNextIrp(
  105. &Extension->CurrentMaskIrp,
  106. &Extension->MaskQueue,
  107. &newIrp,
  108. FALSE,
  109. Extension
  110. );
  111. }
  112. }
  113. }
  114. } while (newIrp);
  115. return firstStatus;
  116. }
  117. BOOLEAN
  118. MoxaFinishOldWait(
  119. IN PVOID Context
  120. )
  121. {
  122. PMOXA_DEVICE_EXTENSION extension = Context;
  123. PUCHAR ofs;
  124. if (extension->IrpMaskLocation) {
  125. //
  126. // The isr still "owns" the irp.
  127. //
  128. *extension->IrpMaskLocation = 0;
  129. extension->IrpMaskLocation = NULL;
  130. extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG);
  131. //
  132. // We don't decrement the reference since the completion routine
  133. // will do that.
  134. //
  135. MoxaInsertQueueDpc(
  136. &extension->CommWaitDpc,
  137. NULL,
  138. NULL,
  139. extension
  140. );
  141. }
  142. //
  143. // Don't wipe out any historical data we are still interested in.
  144. //
  145. extension->HistoryMask &= *((ULONG *)extension->CurrentMaskIrp->
  146. AssociatedIrp.SystemBuffer);
  147. extension->IsrWaitMask = *((ULONG *)extension->CurrentMaskIrp->
  148. AssociatedIrp.SystemBuffer);
  149. ofs = extension->PortOfs;
  150. if (extension->IsrWaitMask & SERIAL_EV_RXCHAR)
  151. *(PUSHORT)(ofs + HostStat) |= WakeupRx;
  152. else
  153. *(PUSHORT)(ofs + HostStat) &= ~WakeupRx;
  154. if (extension->IsrWaitMask & SERIAL_EV_RXFLAG)
  155. *(PUSHORT)(ofs + HostStat) |= WakeupEvent;
  156. else
  157. *(PUSHORT)(ofs + HostStat) &= ~WakeupEvent;
  158. if (extension->IsrWaitMask & SERIAL_EV_RX80FULL)
  159. *(PUSHORT)(ofs + HostStat) |= WakeupRx80Full;
  160. else
  161. *(PUSHORT)(ofs + HostStat) &= ~WakeupRx80Full;
  162. if (extension->IsrWaitMask & SERIAL_EV_ERR) {
  163. *(PUSHORT)(ofs + HostStat) |= WakeupError;
  164. }
  165. else {
  166. *(PUSHORT)(ofs + HostStat) &= ~WakeupError;
  167. }
  168. if (extension->IsrWaitMask & SERIAL_EV_BREAK) {
  169. *(PUSHORT)(ofs + HostStat) |= WakeupBreak;
  170. }
  171. else {
  172. *(PUSHORT)(ofs + HostStat) &= ~WakeupBreak;
  173. }
  174. return FALSE;
  175. }
  176. VOID
  177. MoxaCancelWait(
  178. IN PDEVICE_OBJECT DeviceObject,
  179. IN PIRP Irp
  180. )
  181. {
  182. PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  183. MoxaTryToCompleteCurrent(
  184. extension,
  185. MoxaGrabWaitFromIsr,
  186. Irp->CancelIrql,
  187. STATUS_CANCELLED,
  188. &extension->CurrentWaitIrp,
  189. NULL,
  190. NULL,
  191. NULL,
  192. NULL,
  193. NULL
  194. );
  195. }
  196. BOOLEAN
  197. MoxaGrabWaitFromIsr(
  198. IN PVOID Context
  199. )
  200. {
  201. PMOXA_DEVICE_EXTENSION extension = Context;
  202. if (extension->IrpMaskLocation) {
  203. //
  204. // The isr still "owns" the irp.
  205. //
  206. *extension->IrpMaskLocation = 0;
  207. extension->IrpMaskLocation = NULL;
  208. extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG);
  209. //
  210. // Since the isr no longer references the irp we need to
  211. // decrement the reference count.
  212. //
  213. MOXA_DEC_REFERENCE(extension->CurrentWaitIrp);
  214. }
  215. return FALSE;
  216. }
  217. BOOLEAN
  218. MoxaGiveWaitToIsr(
  219. IN PVOID Context
  220. )
  221. {
  222. PMOXA_DEVICE_EXTENSION extension = Context;
  223. MOXA_INC_REFERENCE(extension->CurrentWaitIrp);
  224. if (!extension->HistoryMask)
  225. extension->IrpMaskLocation =
  226. extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer;
  227. else {
  228. *((ULONG *)extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer) =
  229. extension->HistoryMask;
  230. extension->HistoryMask = 0;
  231. extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG);
  232. extension->CurrentWaitIrp->IoStatus.Status = STATUS_SUCCESS;
  233. MoxaInsertQueueDpc(
  234. &extension->CommWaitDpc,
  235. NULL,
  236. NULL,
  237. extension
  238. );
  239. }
  240. return FALSE;
  241. }
  242. VOID
  243. MoxaCompleteWait(
  244. IN PKDPC Dpc,
  245. IN PVOID DeferredContext,
  246. IN PVOID SystemContext1,
  247. IN PVOID SystemContext2
  248. )
  249. {
  250. PMOXA_DEVICE_EXTENSION extension = DeferredContext;
  251. KIRQL oldIrql;
  252. IoAcquireCancelSpinLock(&oldIrql);
  253. MoxaTryToCompleteCurrent(
  254. extension,
  255. NULL,
  256. oldIrql,
  257. STATUS_SUCCESS,
  258. &extension->CurrentWaitIrp,
  259. NULL,
  260. NULL,
  261. NULL,
  262. NULL,
  263. NULL
  264. );
  265. MoxaDpcEpilogue(extension, Dpc);
  266. }
  267.