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.

231 lines
7.4 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1996
  3. Module Name:
  4. hardware.c
  5. Abstract:
  6. Hardware I/O.
  7. --*/
  8. #include "common.h"
  9. VOID
  10. HwCancelRoutine(
  11. IN PDEVICE_OBJECT DeviceObject,
  12. IN PIRP Irp
  13. )
  14. {
  15. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  16. Irp->IoStatus.Status = STATUS_CANCELLED;
  17. Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  18. IoReleaseCancelSpinLock(Irp->CancelIrql);
  19. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  20. }
  21. BOOLEAN
  22. HwDeviceIsr(
  23. IN PKINTERRUPT Interrupt,
  24. IN PDEVICE_OBJECT DeviceObject
  25. )
  26. {
  27. PDEVICE_INSTANCE DeviceInstance;
  28. DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
  29. if (READ_STATUS_PORT(DeviceInstance) & MPU401_DSR)
  30. return FALSE;
  31. if (IoRequestDpc(DeviceObject, NULL, NULL))
  32. InterlockedIncrement(&DeviceInstance->DpcCount);
  33. return TRUE;
  34. }
  35. static
  36. VOID
  37. CompletePendingIrp(
  38. IN PIRP Irp,
  39. IN OUT PKIRQL IrqlOld
  40. )
  41. {
  42. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  43. IoSetCancelRoutine(Irp, NULL);
  44. Irp->IoStatus.Status = STATUS_SUCCESS;
  45. Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  46. IoReleaseCancelSpinLock(*IrqlOld);
  47. IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
  48. IoAcquireCancelSpinLock(IrqlOld);
  49. }
  50. VOID
  51. HwDeferredRead(
  52. IN PKDPC Dpc,
  53. IN PDEVICE_OBJECT DeviceObject,
  54. IN ULONGLONG SystemTime
  55. )
  56. {
  57. PDEVICE_INSTANCE DeviceInstance;
  58. PPIN_INSTANCE PinInstance;
  59. BOOLEAN FifoEmpty;
  60. FifoEmpty = FALSE;
  61. DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
  62. PinInstance = (PPIN_INSTANCE)DeviceInstance->PinFileObjects[ID_MUSICCAPTURE_PIN]->FsContext;
  63. if (PinInstance && (PinInstance->State == KSSTATE_RUN)) {
  64. ULONG TimeStamp;
  65. PLIST_ENTRY IrpListEntry;
  66. KIRQL IrqlOld;
  67. TimeStamp = (ULONG)((KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase) * 1000 / PinInstance->Frequency);
  68. IoAcquireCancelSpinLock(&IrqlOld);
  69. for (IrpListEntry = PinInstance->IoQueue.Flink; IrpListEntry != &PinInstance->IoQueue; IrpListEntry = PinInstance->IoQueue.Flink) {
  70. PIO_STACK_LOCATION IrpStack;
  71. PIRP Irp;
  72. PCHAR ReadParam;
  73. PCHAR Buffer;
  74. ULONG ReadSize;
  75. PKSSTREAM_HEADER StreamHdr;
  76. Irp = (PIRP)CONTAINING_RECORD(IrpListEntry->Flink, IRP, Tail.Overlay.ListEntry);
  77. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  78. ReadParam = MmGetSystemAddressForMdl(Irp->MdlAddress);
  79. StreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
  80. Buffer = ReadParam + StreamHdr->DataSize;
  81. if (!StreamHdr->DataSize || (StreamHdr->PresentationTime.Time / 10000 + *(PULONG)Irp->Tail.Overlay.AuxiliaryBuffer != TimeStamp)) {
  82. PCHAR NextChunk;
  83. NextChunk = (PCHAR)(((ULONG)Buffer + FILE_LONG_ALIGNMENT) & ~FILE_LONG_ALIGNMENT);
  84. if (!StreamHdr->DataSize) {
  85. StreamHdr->PresentationTime.Time = TimeStamp * 10000;
  86. *(PULONG)NextChunk = 0;
  87. } else if ((ULONG)(NextChunk + 2 * sizeof(ULONG) - ReadParam) >= IrpStack->Parameters.DeviceIoControl.InputBufferLength) {
  88. CompletePendingIrp(Irp, &IrqlOld);
  89. continue;
  90. } else
  91. *(PULONG)NextChunk = (ULONG)(TimeStamp - StreamHdr->PresentationTime.Time / 10000);
  92. *((PULONG)NextChunk + 1) = 0;
  93. Irp->Tail.Overlay.AuxiliaryBuffer = NextChunk;
  94. NextChunk += (2 * sizeof(ULONG));
  95. PinInstance->ByteIo += NextChunk - Buffer;
  96. Buffer = NextChunk;
  97. }
  98. ReadSize = 0;
  99. do {
  100. *Buffer++ = READ_DATA_PORT(DeviceInstance);
  101. ReadSize++;
  102. if (READ_STATUS_PORT(DeviceInstance) & MPU401_DSR) {
  103. FifoEmpty = TRUE;
  104. break;
  105. }
  106. } while ((ULONG)(Buffer - ReadParam) < IrpStack->Parameters.DeviceIoControl.InputBufferLength);
  107. *((PULONG)Irp->Tail.Overlay.AuxiliaryBuffer + 1) += ReadSize;
  108. PinInstance->ByteIo += ReadSize;
  109. StreamHdr->DataSize = Buffer - ReadParam;
  110. if ((ULONG)(Buffer - ReadParam) == IrpStack->Parameters.DeviceIoControl.InputBufferLength)
  111. CompletePendingIrp(Irp, &IrqlOld);
  112. if (FifoEmpty)
  113. break;
  114. }
  115. IoReleaseCancelSpinLock(IrqlOld);
  116. PinGenerateEvent(PinInstance, &KSEVENTSETID_Connection, KSEVENT_CONNECTION_POSITIONUPDATE);
  117. }
  118. if (!FifoEmpty) {
  119. KIRQL IrqlOld;
  120. IoAcquireCancelSpinLock(&IrqlOld);
  121. do
  122. READ_DATA_PORT(DeviceInstance);
  123. while (!(READ_STATUS_PORT(DeviceInstance) & MPU401_DSR));
  124. IoReleaseCancelSpinLock(IrqlOld);
  125. }
  126. InterlockedDecrement(&DeviceInstance->DpcCount);
  127. }
  128. VOID
  129. HwDeferredWrite(
  130. IN PKDPC Dpc,
  131. IN PDEVICE_OBJECT DeviceObject,
  132. IN ULONGLONG SystemTime
  133. )
  134. {
  135. PDEVICE_INSTANCE DeviceInstance;
  136. PPIN_INSTANCE PinInstance;
  137. DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
  138. PinInstance = (PPIN_INSTANCE)DeviceInstance->PinFileObjects[ID_MUSICCAPTURE_PIN]->FsContext;
  139. if (PinInstance->State == KSSTATE_RUN) {
  140. ULONG TimeStamp;
  141. PLIST_ENTRY IrpListEntry;
  142. KIRQL IrqlOld;
  143. TimeStamp = (ULONG)((KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase) * 1000 / PinInstance->Frequency);
  144. IoAcquireCancelSpinLock(&IrqlOld);
  145. for (IrpListEntry = PinInstance->IoQueue.Flink; IrpListEntry != &PinInstance->IoQueue; IrpListEntry = PinInstance->IoQueue.Flink) {
  146. PIRP Irp;
  147. PCHAR ReadParam;
  148. PKSSTREAM_HEADER StreamHdr;
  149. ULONG Continue;
  150. Irp = (PIRP)CONTAINING_RECORD(IrpListEntry->Flink, IRP, Tail.Overlay.ListEntry);
  151. StreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
  152. ReadParam = MmGetSystemAddressForMdl(Irp->MdlAddress);
  153. Continue = TRUE;
  154. for (;;) {
  155. PCHAR Buffer;
  156. ULONG WriteSize;
  157. ULONG WrittenSize;
  158. if (StreamHdr->PresentationTime.Time / 10000 + *(PULONG)Irp->Tail.Overlay.AuxiliaryBuffer > TimeStamp) {
  159. LARGE_INTEGER liTime;
  160. liTime.QuadPart = -(LONG)(StreamHdr->PresentationTime.Time / 10000 + *(PULONG)Irp->Tail.Overlay.AuxiliaryBuffer - TimeStamp);
  161. if (!PinInstance->QueueTimer.Header.Inserted && !KeSetTimerEx(&PinInstance->QueueTimer, liTime, 0, &PinInstance->QueueDpc))
  162. InterlockedIncrement(&PinInstance->TimerCount);
  163. Continue = FALSE;
  164. break;
  165. }
  166. WriteSize = *(((PULONG)Irp->Tail.Overlay.AuxiliaryBuffer) + 1);
  167. WrittenSize = Irp->IoStatus.Information;
  168. WriteSize -= (WrittenSize - (Irp->Tail.Overlay.AuxiliaryBuffer - ReadParam));
  169. if (WriteSize > StreamHdr->DataSize - WrittenSize)
  170. WriteSize = StreamHdr->DataSize - WrittenSize;
  171. for (; WriteSize; WriteSize--) {
  172. for (Continue = MPU_TIMEOUT; Continue && (READ_STATUS_PORT(DeviceInstance) & MPU401_DRR); Continue--)
  173. KeStallExecutionProcessor(1);
  174. if (!Continue)
  175. break;
  176. WRITE_DATA_PORT(DeviceInstance, ReadParam[WrittenSize++]);
  177. }
  178. if (!WriteSize || (WrittenSize - Irp->IoStatus.Information)) {
  179. if (Irp->IoStatus.Information == Irp->Tail.Overlay.AuxiliaryBuffer - ReadParam + 2 * sizeof(ULONG))
  180. PinInstance->ByteIo += 2 * sizeof(ULONG);
  181. PinInstance->ByteIo += (WrittenSize - Irp->IoStatus.Information);
  182. if (!WriteSize) {
  183. PCHAR NextChunk;
  184. NextChunk = (PCHAR)(((ULONG)Irp->Tail.Overlay.AuxiliaryBuffer + FILE_LONG_ALIGNMENT) & ~FILE_LONG_ALIGNMENT);
  185. Irp->IoStatus.Information = NextChunk - ReadParam + 2 * sizeof(ULONG);
  186. if (Irp->IoStatus.Information >= StreamHdr->DataSize) {
  187. Irp->IoStatus.Information = StreamHdr->DataSize;
  188. CompletePendingIrp(Irp, &IrqlOld);
  189. break;
  190. }
  191. PinInstance->ByteIo += (NextChunk - Irp->Tail.Overlay.AuxiliaryBuffer);
  192. Irp->Tail.Overlay.AuxiliaryBuffer = NextChunk;
  193. } else {
  194. Irp->IoStatus.Information = WrittenSize;
  195. if (!Continue)
  196. break;
  197. }
  198. }
  199. }
  200. if (!Continue)
  201. break;
  202. }
  203. IoReleaseCancelSpinLock(IrqlOld);
  204. PinGenerateEvent(PinInstance, &KSEVENTSETID_Connection, KSEVENT_CONNECTION_POSITIONUPDATE);
  205. }
  206. InterlockedDecrement(&PinInstance->TimerCount);
  207. }