www.pudn.com > 2004-01-16_SimSerial.rar > ReadWrite.c


#include  
#include  
#include "main.h" 
 
extern DEVICE_ARRAY	gDeviceArray[ MAX_NUM_DEV ]; 
extern KSPIN_LOCK		gSpinLock; 
extern KSPIN_LOCK		gPoolSpinLock; 
extern LIST_ENTRY		gIdleQueue; 
 
NTSTATUS 
DispatchRead( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp 
	) 
{ 
	NTSTATUS			status; 
	PDEVICE_EXTENSION	deviceExtension; 
	KIRQL				OldIrql; 
	BOOLEAN				bIsEmpty; 
 
	status = STATUS_SUCCESS; 
	DebugPrint(("Enter Read routine\n")); 
	deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension; 
 
 
/* 
	IrpStack = IoGetCurrentIrpStackLocation(Irp); 
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; 
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; 
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength ); 
 
	pOutBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; 
	*/ 
	/* 
	DebugPrint(("pOutBuf:   0x%x\n", pOutBuf )); 
	*pOutBuf = 0x32; 
 
	DebugPrint(("Exit read routine\n")); 
 
  return CompleteRequest(Irp, status, info); 
	*/ 
	// 创建两个队列,一个是Irp队列,一个是Packet队列。 
	// 当packet队列为空时,将Irp放入队列 
	// 否则从packet队列里边取出数据,返回ReadIrp 
	KeAcquireSpinLock( &deviceExtension->ReadQueueSpinLock, &OldIrql ); 
	bIsEmpty = IsListEmpty( &deviceExtension->ReadDataQueue ); 
	KeReleaseSpinLock( &deviceExtension->ReadQueueSpinLock, OldIrql ); 
	if( bIsEmpty ){ 
		IoMarkIrpPending( Irp ); 
		IoSetCancelRoutine( Irp, RequestCancelReadRoutine); 
		ExInterlockedInsertTailList( &deviceExtension->ReadIrpQueue, &Irp->Tail.Overlay.ListEntry, &deviceExtension->CancelSpinLock ); 
		status = STATUS_PENDING; 
		return status; 
	}else{ 
		return CompleteReadIrp( deviceExtension, Irp ); 
	} 
	 
} 
/* 
 
*/ 
NTSTATUS 
DispatchWrite( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp 
	) 
{ 
	PIO_STACK_LOCATION IrpStack; 
	ULONG				ControlCode; 
	ULONG				InputLength,OutputLength; 
	NTSTATUS			status; 
	PDEVICE_EXTENSION	deviceExtension; 
	ULONG				info; 
	PUCHAR				pInBuf; 
	PLIST_ENTRY			link; 
	ULONG				nTx; 
	PPACKET				lpPacket; 
 
	KIRQL				OldIrql; 
	KIRQL				remoteOldIrql; 
	PDEVICE_EXTENSION	remoteDev; 
	PIRP				pendingMaskIrp; 
	 
	ULONG				i; 
	PLIST_ENTRY			linkIrp; 
 
	status = STATUS_SUCCESS; 
	info = 0; 
	DebugPrint(("---------      Enter Write routine    -------\n")); 
	deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension; 
 
	IrpStack=IoGetCurrentIrpStackLocation(Irp); 
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; 
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; 
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength ); 
 
	pInBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; 
	DebugPrint(("Data to write: \n")); 
	for( i = 0; i < OutputLength; i++) 
	{ 
		//*( pInBuf++ ) = i % 256; 
		DbgPrint("%2x ", pInBuf[ i ] ); 
	} 
	DbgPrint("\n"); 
	KeAcquireSpinLock( &gSpinLock, &OldIrql ); 
	if( deviceExtension->bIsConnected ){ 
		// 将数据打包成packet, 
		// 检查接收端有无ReadIrp在队列中 
		// 若有,完成该ReadIrp 
		// 若无,则直接放入接收端的接收packet队列中 
		nTx = 0; 
		remoteDev = gDeviceArray[ deviceExtension->remoteInstance ].deviceExtension; 
		while( nTx < OutputLength ){ 
			if( link = ExInterlockedRemoveHeadList( &gIdleQueue, &gPoolSpinLock ) ){ 
				lpPacket = CONTAINING_RECORD( link, PACKET, ListEntry ); 
				DebugPrint(("lpPacket: %x\n", lpPacket )); 
				lpPacket->nTotalNum = ( ( OutputLength - nTx ) > PACKET_SIZE  ) ? PACKET_SIZE : ( OutputLength - nTx ); 
				lpPacket->nReadBytes = 0; 
				RtlCopyMemory( lpPacket->Buffer, &pInBuf[ nTx ], lpPacket->nTotalNum ); 
				ExInterlockedInsertTailList( &( remoteDev->ReadDataQueue ), link, &remoteDev->ReadQueueSpinLock ); 
				nTx += lpPacket->nTotalNum; 
 
				// 察看remoteInstance是否有ReadIrp 
				linkIrp = ExInterlockedRemoveHeadList( &remoteDev->ReadIrpQueue, &remoteDev->CancelSpinLock ); 
				if( linkIrp ){ 
					// 若远方端口已经有ReadIrp在pending,则完成该ReadIrp 
					pendingMaskIrp = CONTAINING_RECORD( linkIrp, IRP, Tail.Overlay.ListEntry ); 
					ASSERT( pendingMaskIrp ); 
					CompleteReadIrp( remoteDev, pendingMaskIrp ); 
				} 
			}else{ 
				DebugPrint(("IdleQueue is empty!!!!\n")); 
				break; 
			} 
		} 
		info = nTx; 
	}else{ 
		info = OutputLength; 
	} 
	KeReleaseSpinLock( &gSpinLock, OldIrql ); 
	DebugPrint(("Totally wrote %d\n---------      Exit Write routine    -------\n", info )); 
 
	return CompleteRequest(Irp, status, info); 
} 
 
NTSTATUS 
CompleteReadIrp( 
	IN PDEVICE_EXTENSION	deviceExtension, 
	IN PIRP					Irp 
	) 
{ 
	PIO_STACK_LOCATION	IrpStack; 
	NTSTATUS			status; 
	ULONG				ControlCode; 
	ULONG				InputLength,OutputLength; 
	PUCHAR				pOutBuf; 
	ULONG				info; 
	ULONG				nToReadBytes; 
	PLIST_ENTRY			link; 
	PPACKET				lpPacket; 
 
 
	DebugPrint(("------  Enter CompleteReadIrp routine ( 0x%x )  --------\n", Irp)); 
	IrpStack = IoGetCurrentIrpStackLocation(Irp); 
 
	DebugPrint(("GetCurrentIrpStackLocation OK\n")); 
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; 
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; 
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength ); 
 
	pOutBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; 
 
	link = ExInterlockedRemoveHeadList( &deviceExtension->ReadDataQueue, &deviceExtension->ReadQueueSpinLock ); 
	ASSERT( link ); 
	lpPacket = CONTAINING_RECORD( link, PACKET, ListEntry ); 
	DebugPrint(("lpPacket: %x!\n", lpPacket )); 
	nToReadBytes = ( lpPacket->nTotalNum - lpPacket->nReadBytes ); 
	ASSERT( nToReadBytes > 0); 
	nToReadBytes = ( nToReadBytes > OutputLength ) ? OutputLength : nToReadBytes; 
	RtlCopyMemory( pOutBuf, &( lpPacket->Buffer[ lpPacket->nReadBytes ] ), nToReadBytes ); 
	lpPacket->nReadBytes += nToReadBytes; 
	if( lpPacket->nReadBytes == lpPacket->nTotalNum ){ 
		RtlZeroMemory( lpPacket, sizeof( PACKET ) ); 
		DebugPrint(("ZeroMemory lpPacket!\n")); 
		ExInterlockedInsertTailList( &gIdleQueue, &( lpPacket->ListEntry ), &gPoolSpinLock ); 
	}else{ 
		ExInterlockedInsertHeadList( &deviceExtension->ReadDataQueue, link, &deviceExtension->ReadQueueSpinLock ); 
	} 
	status = STATUS_SUCCESS; 
	DebugPrint(("--------      Exit ReadIrp routine   -----------\n")); 
	return CompleteRequest( Irp, status, nToReadBytes ); 
}