readwrite.c
上传用户:zanmei2
上传日期:2010-03-06
资源大小:775k
文件大小:6k
源码类别:

通讯编程文档

开发平台:

C/C++

  1. /*++
  2. Copyright (c) 2005  Changzhi Zhou All Rights Reserved
  3. Module Name:
  4.     readwrite.c
  5. Abstract:
  6.     This module contains Read/Write routines.
  7. Environment:
  8.     Kernel mode
  9. Revision History:
  10. Changzhi Zhou Dec 20  2004
  11. --*/
  12. #include <ntddk.h>
  13. #include <initguid.h>
  14. #include "main.h"
  15. #include "..incwdmioctl.h"
  16. NTSTATUS
  17. SampleRead(
  18.     IN PDEVICE_OBJECT DeviceObject,
  19.     IN PIRP Irp
  20. )
  21. /*++
  22. Routine Description:
  23. Read I/O request.
  24. If deviceExtension->SerialStatus.AmountInInQueue, which means there are some data in RxBuffer,
  25. we call CopyFromRingBuffer to copy data in RxBuffer to Irp->MdlAddress.
  26. Else mark the Irp pending , return STATUS_PENDING and start a timer. The timeout is set by 
  27. IOCTL_SERIAL_SET_TIMEOUTS.
  28. Arguments:
  29.   DeviceObject - pointer to device object
  30.   Irp - pointer to Read I/O request.
  31. Return Value:
  32.     NT status code.
  33. --*/
  34. {
  35. PDEVICE_EXTENSION deviceExtension;
  36. NTSTATUS status;
  37. PIO_STACK_LOCATION IrpStack;
  38. ULONG OutputLength;
  39. ULONG info;
  40. KIRQL oldIrql;
  41. PAGED_CODE();
  42. DbgPrint("--- SampleRead routine...n");
  43. deviceExtension = DeviceObject->DeviceExtension;
  44. if ( deviceExtension->DevicePnPState != Working )
  45. return CompleteRequest ( Irp, STATUS_INVALID_DEVICE_STATE, 0 );
  46. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  47. OutputLength = IrpStack->Parameters.Read.Length;
  48. if( OutputLength == 0 )
  49. return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
  50. status = STATUS_SUCCESS;
  51. info = 0;
  52. KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql );
  53. if ( deviceExtension->PendingReadIrp == NULL )
  54. {
  55. if( deviceExtension->SerialStatus.AmountInInQueue )
  56. {
  57. info = CopyFromRingBuffer ( deviceExtension, Irp );
  58. }else
  59. { // set timeout simply.
  60. LARGE_INTEGER Timeout;
  61. ULONG tmp;
  62. tmp = ( deviceExtension->Timeouts.ReadIntervalTimeout > READINTERVAL_TIMEOUT )
  63. ? READINTERVAL_TIMEOUT : deviceExtension->Timeouts.ReadIntervalTimeout;
  64. if ( tmp > 0 )
  65. {
  66. Timeout.LowPart = ( -1 ) * tmp;
  67. Timeout.HighPart = -1;
  68. DebugPrint(("Irp (%x) Set ReadTimer %d (100 nanosecond )n", Irp, tmp ));
  69. SampleIoIncrement( deviceExtension );
  70. deviceExtension->PendingReadIrp = Irp;
  71. IoMarkIrpPending ( Irp );
  72. status = STATUS_PENDING;
  73. KeSetTimer ( &deviceExtension->ReadTimer, Timeout, &deviceExtension->ReadDpc );
  74. }
  75. }
  76. }else
  77. {
  78. status = STATUS_INVALID_DEVICE_REQUEST;
  79. }
  80. KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql );
  81. if ( status != STATUS_PENDING )
  82. CompleteRequest( Irp, status, info );
  83. return status;
  84. }
  85. VOID
  86. ReadDpcRoutine(
  87.     IN PKDPC Dpc,
  88.     IN PVOID DeferredContext,
  89.     IN PVOID SystemArgument1,
  90.     IN PVOID SystemArgument2
  91.     )
  92. /*++
  93. Routine Description:
  94.   DPC routine.
  95.   It will be called by the trigger of ReadIrp timer. If there are some data, it copies the data
  96.   to Irp->MdlAddress and then complete the Irp. If not, it complete thr Irp directly.
  97.   The deviceExtension->PendingReadIrp is the Read I/O request saved by SampleRead.
  98. Arguments:
  99. DeferredContext - pointer to deviceExtension
  100. --*/
  101. {
  102. KIRQL oldIrql;
  103. PDEVICE_EXTENSION deviceExtension;
  104. PIRP Irp;
  105. ULONG info;
  106. deviceExtension = ( PDEVICE_EXTENSION )DeferredContext;
  107. info = 0;
  108. KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql );
  109. if ( deviceExtension->PendingReadIrp )
  110. {
  111. Irp = deviceExtension->PendingReadIrp;
  112. DebugPrint(("Irp (%x) DpcRoutine...n", Irp ));
  113. if ( deviceExtension->SerialStatus.AmountInInQueue )
  114. {
  115. info = CopyFromRingBuffer ( deviceExtension, Irp );
  116. }
  117. CompleteRequest( Irp, STATUS_SUCCESS, info );
  118. SampleIoDecrement ( deviceExtension );
  119. deviceExtension->PendingReadIrp = NULL;
  120. }
  121. KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql );
  122. }
  123. ULONG CopyFromRingBuffer(
  124. PDEVICE_EXTENSION deviceExtension,
  125. PIRP Irp )
  126. /*++
  127. Routine Description:
  128. It copies RingBuffer, that is RxBuffer, to Irp->MdlAddress.
  129. It must be running at IRQL = DISPATCH_LEVEL within the scope of Spinlock.
  130. Arguments:
  131. deviceExtension - pointer to device object extension
  132. Irp - Read I/O request packet
  133. Return Value:
  134.     the actual number of data copied from ringbuffer.
  135. --*/
  136. {
  137. PIO_STACK_LOCATION IrpStack;
  138. ULONG OutputLength;
  139. ULONG BytesToCopy;
  140. PUCHAR buf;
  141. ULONG stageSize;
  142. ASSERT ( deviceExtension->SerialStatus.AmountInInQueue );
  143. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  144. OutputLength = IrpStack->Parameters.Read.Length;
  145. buf = (PUCHAR)MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  146. ASSERT ( buf );
  147. BytesToCopy = ( deviceExtension->SerialStatus.AmountInInQueue > OutputLength ) ? OutputLength : deviceExtension->SerialStatus.AmountInInQueue;
  148. stageSize = deviceExtension->RxBuffer + RINGBUFFER_SIZE - deviceExtension->lpRead;
  149. if ( BytesToCopy <= stageSize )
  150. RtlCopyMemory ( buf, deviceExtension->lpRead, BytesToCopy );
  151. else
  152. {
  153. RtlCopyMemory ( buf, deviceExtension->lpRead, stageSize );
  154. RtlCopyMemory ( buf + stageSize, deviceExtension->RxBuffer, ( BytesToCopy - stageSize ) );
  155. }
  156. deviceExtension->lpRead = deviceExtension->RxBuffer +
  157. ( ( deviceExtension->lpRead + BytesToCopy - deviceExtension->RxBuffer ) % RINGBUFFER_SIZE );
  158. deviceExtension->SerialStatus.AmountInInQueue -= BytesToCopy;
  159. return BytesToCopy;
  160. }
  161. NTSTATUS
  162. SampleWrite(
  163.     IN PDEVICE_OBJECT DeviceObject,
  164.     IN PIRP Irp
  165. )
  166. /*++
  167. Routine Description:
  168. It calls TdiSendDatagram to send data to remote peer, which is indicated 
  169. by deviceExtension->RemoteAddress and deviceExtension->RemotePort.
  170. Arguments:
  171. DeviceObject - pointer to device object.
  172. Irp - Read I/O request packet
  173. Return Value:
  174.     NT status code.
  175. --*/
  176. {
  177. PIO_STACK_LOCATION IrpStack;
  178. PDEVICE_EXTENSION deviceExtension;
  179. NTSTATUS status;
  180. ULONG InputLength;
  181. ULONG info;
  182. PAGED_CODE();
  183. DbgPrint("--- SampleWrite routine...n");
  184. deviceExtension = DeviceObject->DeviceExtension;
  185. if ( deviceExtension->DevicePnPState != Working )
  186. return CompleteRequest ( Irp, STATUS_INVALID_DEVICE_STATE, 0 );
  187. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  188. InputLength = IrpStack->Parameters.Write.Length;
  189. if( InputLength == 0 )
  190. return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
  191. SampleIoIncrement( deviceExtension );
  192. status = TDISendDatagram( DeviceObject, Irp );
  193. info = Irp->IoStatus.Information;
  194. status = CompleteRequest( Irp, status, info );
  195. SampleIoDecrement( deviceExtension );
  196. return status;
  197. }