Windows NT 4.0 source code leak
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.

308 lines
9.2 KiB

4 years ago
  1. /*
  2. * vcisr.c
  3. *
  4. *
  5. * 32-bit Video Capture driver
  6. * kernel-mode support library - interrupt dispatch
  7. *
  8. * Geraint Davies, Feb 93
  9. */
  10. #include <vckernel.h>
  11. #include "vckpriv.h"
  12. #include "profile.h"
  13. #if DBG
  14. extern profiling looptime;
  15. #endif
  16. /* interrupt service routine - returns TRUE if interrupt handled.
  17. * all interrupts come in here and are then dispatched to hw ack routine
  18. * the Context pointer is a pointer to DEVICE_INFO.
  19. */
  20. BOOLEAN
  21. VC_InterruptService(
  22. IN PKINTERRUPT pInterruptObject,
  23. IN PVOID Context
  24. )
  25. {
  26. PDEVICE_INFO pDevInfo;
  27. pDevInfo = (PDEVICE_INFO)Context;
  28. /*
  29. * make sure that the hardware-specific code has installed
  30. * an ack routine
  31. */
  32. if (pDevInfo->Callback.InterruptAcknowledge == NULL) {
  33. /* no isr - and yet we are getting interrupts -
  34. * we should disconnect the interrupt
  35. */
  36. dprintf(("interrupt occured without h/w isr"));
  37. //IoDisconnectInterrupt(pDevInfo->InterruptObject);
  38. return(FALSE);
  39. }
  40. /*
  41. * call the acknowledge. this will not do any service, but will
  42. * return TRUE if the service routine is to be called.
  43. */
  44. if (!pDevInfo->Callback.InterruptAcknowledge(pDevInfo)) {
  45. return(FALSE);
  46. }
  47. /* the isr reckons that it is time to schedule the service
  48. * routine. This is done on a DPC.
  49. */
  50. if (pDevInfo->DpcRequested) {
  51. //dprintf5(("dpc overrun"));
  52. } else {
  53. pDevInfo->DpcRequested = TRUE;
  54. IoRequestDpc(pDevInfo->pDeviceObject, NULL, pDevInfo);
  55. }
  56. /* everything else is done in dpc routine */
  57. return(TRUE);
  58. }
  59. /*
  60. * DPC routine to do work for interrupt service. Scheduled because
  61. * hardware acknowledge routine said that it was time to call its
  62. * service routine.
  63. *
  64. * If there is an outstanding buffer, pass this to the h/w service
  65. * routine to fill, and then complete the irp.
  66. *
  67. * if there is no buffer, then we have to miss a frame. if there is an
  68. * outstanding wait-error request, then we can complete that to report
  69. * the overrun. If not, we just count one more unreported overrun
  70. * to save up for the next wait-error.
  71. *
  72. * If we have no buffer, we must still call the hardware capture routine,
  73. * with a NULL buffer pointer, so it can discard any data and re-arm for
  74. * capture.
  75. *
  76. * Note that the pIrpNotUsed is an arg passed from the IoRequestDpc call.
  77. * We don't work out which Irp to complete until this function, so
  78. * we ignore that. The context argument is a PDEVICE_INFO.
  79. *
  80. * The buffered parameter to the add-buffer irp is the CAPTUREBUFFER structure.
  81. * We need to store the bytes written, and the timestamp there. The
  82. * virtual address for the buffer has been locked down and is
  83. * represented by the Irp->MdlAddress. We mapped this ourselves but
  84. * we don't need to free it ourselves since we added it to the irp. the i/o
  85. * subsystem will unlock and free it when freeing the irp.
  86. *
  87. * Contention: see comment at top of vcdisp.c. We use the cancel spinlock
  88. * to protect accesses to the irp queues against contention from
  89. * passive-level requests, but we do not hold it for the entire
  90. * service routine.
  91. */
  92. VOID
  93. VC_Deferred(
  94. PKDPC pDpc,
  95. PDEVICE_OBJECT pDeviceObject,
  96. PIRP pIrpNotUsed,
  97. PVOID Context
  98. )
  99. {
  100. PDEVICE_INFO pDevInfo;
  101. PIRP pIrp = NULL;
  102. PUCHAR pData;
  103. ULONG ulLength;
  104. PCAPTUREBUFFER pCapBuf;
  105. pDevInfo = (PDEVICE_INFO)Context;
  106. pDevInfo->DpcRequested = FALSE;
  107. /*
  108. * check that the h/w specific code has installed a service handler
  109. * some kind of internal error otherwise.
  110. */
  111. if (pDevInfo->Callback.CaptureService == NULL) {
  112. dprintf(("dpc requested but no service routine"));
  113. return;
  114. }
  115. /*
  116. * if there is a system buffer and it is in use, then
  117. * we should fail to capture anything else
  118. */
  119. if ((pDevInfo->pSystemBuffer != NULL) && (pDevInfo->SysBufInUse != 0)) {
  120. /* report overrun, same as for no-buffer cases */
  121. /*
  122. * notify the hardware portion that there is no buffer, so
  123. * he must throw away everything and re-arm.
  124. */
  125. pDevInfo->Callback.CaptureService(pDevInfo, NULL, NULL, 0);
  126. /*
  127. * access to the skip count needs to be locked together
  128. * with access to the queue of wait-error requests. This function
  129. * increments the skip-count and completes a wait-error request
  130. * if there is one.
  131. */
  132. VC_ReportSkip(pDevInfo);
  133. }
  134. /*
  135. * We need to interlock access to the queue using the Cancel
  136. * spinlock (see vcqueue.c) - but we don't need to interlock
  137. * the whole of this function.
  138. *
  139. * Any further contention between this code and the
  140. * passive-level code will be resolved by the h/wspecific code.
  141. */
  142. /*
  143. * get the next irp from the queue
  144. */
  145. pIrp = VC_ExtractNextIrp(&pDevInfo->BufferHead, FALSE);
  146. if (pIrp) {
  147. PIO_STACK_LOCATION pIoStack;
  148. ULONG IoCode;
  149. /*
  150. * is this cap_to_sysbuf or a real one ?
  151. */
  152. pIoStack = IoGetCurrentIrpStackLocation(pIrp);
  153. IoCode = pIoStack->Parameters.DeviceIoControl.IoControlCode;
  154. if(IoCode == IOCTL_VIDC_ADD_BUFFER) {
  155. /* get the address of the callers buffer, mapped into
  156. * system memory
  157. */
  158. pData = (PUCHAR) MmGetSystemAddressForMdl(pIrp->MdlAddress);
  159. if (pData == NULL) {
  160. dprintf(("MmGetSystemAddressforMdl failed in dpc"));
  161. pIrp->IoStatus.Information = 0;
  162. pIrp->IoStatus.Status = STATUS_NO_MEMORY;
  163. } else {
  164. /* get a pointer to the (buffered) CAPTUREBUFFER header */
  165. pCapBuf = (PCAPTUREBUFFER) pIrp->AssociatedIrp.SystemBuffer;
  166. /*
  167. * find the length of the data buffer
  168. */
  169. ulLength = pCapBuf->BufferLength;
  170. //profile this call
  171. START_PROFILING(&looptime);
  172. pCapBuf->BytesUsed = (DWORD)
  173. pDevInfo->Callback.CaptureService(pDevInfo,
  174. pData,
  175. (PULONG) &pCapBuf->TimeCaptured,
  176. ulLength);
  177. STOP_PROFILING(&looptime);
  178. /* if a capture service routine returns 0, it means
  179. * that it has not completed this capture, and would like
  180. * the same buffer back for the next field if possible
  181. * - in this case, return the buffer to the start of the
  182. * queue
  183. */
  184. if (pCapBuf->BytesUsed == 0) {
  185. if (VC_ReplaceRequest(pIrp, &pDevInfo->BufferHead, VC_Cancel)) {
  186. // nothing more to do till he gets another crack
  187. return;
  188. } else {
  189. // this irp has been cancelled
  190. pIrp->IoStatus.Status = STATUS_CANCELLED;
  191. pIrp->IoStatus.Information = 0;
  192. }
  193. } else {
  194. /* we copy back the CAPTUREBUFFER struct */
  195. pIrp->IoStatus.Information = sizeof(CAPTUREBUFFER);
  196. pIrp->IoStatus.Status = STATUS_SUCCESS;
  197. }
  198. }
  199. } else if (IoCode == IOCTL_VIDC_CAP_TO_SYSBUF) {
  200. if (pDevInfo->pSystemBuffer == NULL) {
  201. pIrp->IoStatus.Information = 0;
  202. pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
  203. } else {
  204. /*
  205. * capture to system buffer and complete request
  206. */
  207. pDevInfo->SysBufInUse = 1;
  208. if (pDevInfo->Callback.CaptureService(
  209. pDevInfo,
  210. pDevInfo->pSystemBuffer,
  211. &pDevInfo->SysBufTimeStamp,
  212. pDevInfo->ImageSize) == 0) {
  213. // 0 return means please give me another go at this request
  214. if (VC_ReplaceRequest(pIrp, &pDevInfo->BufferHead, VC_Cancel)) {
  215. // nothing more to do till he gets another crack
  216. return;
  217. } else {
  218. // this irp has been cancelled
  219. pIrp->IoStatus.Status = STATUS_CANCELLED;
  220. }
  221. } else {
  222. pIrp->IoStatus.Status = STATUS_SUCCESS;
  223. }
  224. pIrp->IoStatus.Information = 0;
  225. }
  226. } else {
  227. /* unexpected irp */
  228. pIrp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
  229. }
  230. IoCompleteRequest(pIrp, IO_SOUND_INCREMENT);
  231. } else {
  232. /*
  233. * notify the hardware portion that there is no buffer, so
  234. * he must throw away everything and re-arm.
  235. */
  236. pDevInfo->Callback.CaptureService(pDevInfo, NULL, NULL, 0);
  237. /*
  238. * access to the skip count needs to be locked together
  239. * with access to the queue of wait-error requests. This function
  240. * increments the skip-count and completes a wait-error request
  241. * if there is one.
  242. */
  243. VC_ReportSkip(pDevInfo);
  244. }
  245. }