readwrite.c
资源名称:虚拟串口驱动程序.rar [点击查看]
上传用户:zanmei2
上传日期:2010-03-06
资源大小:775k
文件大小:6k
源码类别:
通讯编程文档
开发平台:
C/C++
- /*++
- Copyright (c) 2005 Changzhi Zhou All Rights Reserved
- Module Name:
- readwrite.c
- Abstract:
- This module contains Read/Write routines.
- Environment:
- Kernel mode
- Revision History:
- Changzhi Zhou Dec 20 2004
- --*/
- #include <ntddk.h>
- #include <initguid.h>
- #include "main.h"
- #include "..incwdmioctl.h"
- NTSTATUS
- SampleRead(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- Read I/O request.
- If deviceExtension->SerialStatus.AmountInInQueue, which means there are some data in RxBuffer,
- we call CopyFromRingBuffer to copy data in RxBuffer to Irp->MdlAddress.
- Else mark the Irp pending , return STATUS_PENDING and start a timer. The timeout is set by
- IOCTL_SERIAL_SET_TIMEOUTS.
- Arguments:
- DeviceObject - pointer to device object
- Irp - pointer to Read I/O request.
- Return Value:
- NT status code.
- --*/
- {
- PDEVICE_EXTENSION deviceExtension;
- NTSTATUS status;
- PIO_STACK_LOCATION IrpStack;
- ULONG OutputLength;
- ULONG info;
- KIRQL oldIrql;
- PAGED_CODE();
- DbgPrint("--- SampleRead routine...n");
- deviceExtension = DeviceObject->DeviceExtension;
- if ( deviceExtension->DevicePnPState != Working )
- return CompleteRequest ( Irp, STATUS_INVALID_DEVICE_STATE, 0 );
- IrpStack = IoGetCurrentIrpStackLocation(Irp);
- OutputLength = IrpStack->Parameters.Read.Length;
- if( OutputLength == 0 )
- return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
- status = STATUS_SUCCESS;
- info = 0;
- KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql );
- if ( deviceExtension->PendingReadIrp == NULL )
- {
- if( deviceExtension->SerialStatus.AmountInInQueue )
- {
- info = CopyFromRingBuffer ( deviceExtension, Irp );
- }else
- { // set timeout simply.
- LARGE_INTEGER Timeout;
- ULONG tmp;
- tmp = ( deviceExtension->Timeouts.ReadIntervalTimeout > READINTERVAL_TIMEOUT )
- ? READINTERVAL_TIMEOUT : deviceExtension->Timeouts.ReadIntervalTimeout;
- if ( tmp > 0 )
- {
- Timeout.LowPart = ( -1 ) * tmp;
- Timeout.HighPart = -1;
- DebugPrint(("Irp (%x) Set ReadTimer %d (100 nanosecond )n", Irp, tmp ));
- SampleIoIncrement( deviceExtension );
- deviceExtension->PendingReadIrp = Irp;
- IoMarkIrpPending ( Irp );
- status = STATUS_PENDING;
- KeSetTimer ( &deviceExtension->ReadTimer, Timeout, &deviceExtension->ReadDpc );
- }
- }
- }else
- {
- status = STATUS_INVALID_DEVICE_REQUEST;
- }
- KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql );
- if ( status != STATUS_PENDING )
- CompleteRequest( Irp, status, info );
- return status;
- }
- VOID
- ReadDpcRoutine(
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2
- )
- /*++
- Routine Description:
- DPC routine.
- It will be called by the trigger of ReadIrp timer. If there are some data, it copies the data
- to Irp->MdlAddress and then complete the Irp. If not, it complete thr Irp directly.
- The deviceExtension->PendingReadIrp is the Read I/O request saved by SampleRead.
- Arguments:
- DeferredContext - pointer to deviceExtension
- --*/
- {
- KIRQL oldIrql;
- PDEVICE_EXTENSION deviceExtension;
- PIRP Irp;
- ULONG info;
- deviceExtension = ( PDEVICE_EXTENSION )DeferredContext;
- info = 0;
- KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql );
- if ( deviceExtension->PendingReadIrp )
- {
- Irp = deviceExtension->PendingReadIrp;
- DebugPrint(("Irp (%x) DpcRoutine...n", Irp ));
- if ( deviceExtension->SerialStatus.AmountInInQueue )
- {
- info = CopyFromRingBuffer ( deviceExtension, Irp );
- }
- CompleteRequest( Irp, STATUS_SUCCESS, info );
- SampleIoDecrement ( deviceExtension );
- deviceExtension->PendingReadIrp = NULL;
- }
- KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql );
- }
- ULONG CopyFromRingBuffer(
- PDEVICE_EXTENSION deviceExtension,
- PIRP Irp )
- /*++
- Routine Description:
- It copies RingBuffer, that is RxBuffer, to Irp->MdlAddress.
- It must be running at IRQL = DISPATCH_LEVEL within the scope of Spinlock.
- Arguments:
- deviceExtension - pointer to device object extension
- Irp - Read I/O request packet
- Return Value:
- the actual number of data copied from ringbuffer.
- --*/
- {
- PIO_STACK_LOCATION IrpStack;
- ULONG OutputLength;
- ULONG BytesToCopy;
- PUCHAR buf;
- ULONG stageSize;
- ASSERT ( deviceExtension->SerialStatus.AmountInInQueue );
- IrpStack = IoGetCurrentIrpStackLocation(Irp);
- OutputLength = IrpStack->Parameters.Read.Length;
- buf = (PUCHAR)MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
- ASSERT ( buf );
- BytesToCopy = ( deviceExtension->SerialStatus.AmountInInQueue > OutputLength ) ? OutputLength : deviceExtension->SerialStatus.AmountInInQueue;
- stageSize = deviceExtension->RxBuffer + RINGBUFFER_SIZE - deviceExtension->lpRead;
- if ( BytesToCopy <= stageSize )
- RtlCopyMemory ( buf, deviceExtension->lpRead, BytesToCopy );
- else
- {
- RtlCopyMemory ( buf, deviceExtension->lpRead, stageSize );
- RtlCopyMemory ( buf + stageSize, deviceExtension->RxBuffer, ( BytesToCopy - stageSize ) );
- }
- deviceExtension->lpRead = deviceExtension->RxBuffer +
- ( ( deviceExtension->lpRead + BytesToCopy - deviceExtension->RxBuffer ) % RINGBUFFER_SIZE );
- deviceExtension->SerialStatus.AmountInInQueue -= BytesToCopy;
- return BytesToCopy;
- }
- NTSTATUS
- SampleWrite(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- It calls TdiSendDatagram to send data to remote peer, which is indicated
- by deviceExtension->RemoteAddress and deviceExtension->RemotePort.
- Arguments:
- DeviceObject - pointer to device object.
- Irp - Read I/O request packet
- Return Value:
- NT status code.
- --*/
- {
- PIO_STACK_LOCATION IrpStack;
- PDEVICE_EXTENSION deviceExtension;
- NTSTATUS status;
- ULONG InputLength;
- ULONG info;
- PAGED_CODE();
- DbgPrint("--- SampleWrite routine...n");
- deviceExtension = DeviceObject->DeviceExtension;
- if ( deviceExtension->DevicePnPState != Working )
- return CompleteRequest ( Irp, STATUS_INVALID_DEVICE_STATE, 0 );
- IrpStack = IoGetCurrentIrpStackLocation(Irp);
- InputLength = IrpStack->Parameters.Write.Length;
- if( InputLength == 0 )
- return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
- SampleIoIncrement( deviceExtension );
- status = TDISendDatagram( DeviceObject, Irp );
- info = Irp->IoStatus.Information;
- status = CompleteRequest( Irp, status, info );
- SampleIoDecrement( deviceExtension );
- return status;
- }