?? ocrwblk.c
字號:
/*++
Copyright (c) 1997-1998 Microsoft Corporation
Module Name:
OcrwBulk.c
Abstract:
Bulk USB device driver for Intel 82930 USB test board
Read/write io test code
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1997-1998 Microsoft Corporation. All Rights Reserved.
Revision History:
11/17/97 : created
--*/
#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#define DRIVER
#include "usbdi.h"
#include "usbdlib.h"
#include "Blk82930.h"
NTSTATUS
BulkUsb_StagedReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN BOOLEAN Read
)
/*++
Routine Description:
This routine is called by BulkUsb_Read() for IRP_MJ_READ.
This routine is called by BulkUsb_Write() for IRP_MJ_WRITE.
Breaks up a read or write in to specified sized chunks,
as specified by deviceExtension->MaximumTransferSize
Arguments:
DeviceObject - pointer to our FDO ( Functional Device Object )
Irp - pointer to the IRP_MJ_READ or IRP_MJ_WRITE
Read - TRUE for read, FALSE for write
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
NTSTATUS resetPipeStatus;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack, nextStack;
PURB urb;
PIRP irp;
PMDL mdl;
PVOID va;
CHAR stackSize;
KIRQL OldIrql;
BOOLEAN fRes;
NTSTATUS waitStatus;
ULONG i, nIrps = 0, totalLength = 0, totalIrpsNeeded, used;
PUSBD_PIPE_INFORMATION pipeHandle = NULL;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PUCHAR pCon = NULL;
ULONG ChunkSize = deviceExtension->MaximumTransferSize;
ULONG arraySize;
PBULKUSB_RW_CONTEXT context = NULL;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("enter BulkUsb_StagedReadWrite()\n"));
Irp->IoStatus.Information = 0;
// Can't accept a new io request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending
if ( !BulkUsb_CanAcceptIoRequests( DeviceObject ) ) {
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() can't accept requests, returning STATUS_INSUFFICIENT_RESOURCES\n"));
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
pipeHandle = fileObject->FsContext;
if (!pipeHandle)
{
ntStatus = STATUS_INVALID_HANDLE;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() Rejecting on invalid pipeHandle 0x%x decimal %d\n",pipeHandle, pipeHandle ));
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
//
// submit the request to USB
//
BULKUSB_ASSERT( UsbdPipeTypeBulk == pipeHandle->PipeType );
if ( Irp->MdlAddress )
totalLength = MmGetMdlByteCount(Irp->MdlAddress);
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() totalLength = decimal %d, Irp->MdlAddress = 0x%x\n",totalLength, Irp->MdlAddress ));
if ( 0 == totalLength ) {
// allow 0-len read or write; just return success
ntStatus = STATUS_SUCCESS;
Irp->IoStatus.Status = ntStatus;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() returning quick success on zero-len read/write request\n"));
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
// more memory than is on our test device?
if ( totalLength > BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE )
{
ntStatus = STATUS_INVALID_PARAMETER;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() Rejecting on too large request 0x%x decimal %d\n",totalLength, totalLength ));
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
// calculate total # of staged irps that will be needed
totalIrpsNeeded = totalLength / deviceExtension->MaximumTransferSize ;
if ( totalLength % deviceExtension->MaximumTransferSize )
totalIrpsNeeded++;
BULKUSB_ASSERT( !deviceExtension->PendingIoIrps ); // this should have been cleaned up last time
BULKUSB_ASSERT( !deviceExtension->BaseIrp ); // this should have been cleaned up last time
used = 0;
// alloc one extra for termination
arraySize = ( totalIrpsNeeded +1 ) * sizeof(BULKUSB_RW_CONTEXT);
// allocate space for an array of BULKUSB_RW_CONTEXT structs for the staged irps
deviceExtension->PendingIoIrps = BULKUSB_ExAllocatePool(NonPagedPool, arraySize );
if ( !deviceExtension->PendingIoIrps ) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() !deviceExtension->PendingIoIrps STATUS_INSUFFICIENT_RESOURCES\n"));
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
RtlZeroMemory(deviceExtension->PendingIoIrps, arraySize );
// init ptr to 1st BULKUSB_RW_CONTEXT struct in array
pCon = (PUCHAR) deviceExtension->PendingIoIrps;
deviceExtension->BaseIrp = Irp; // this is the original user's irp
deviceExtension->StagedBytesTransferred = 0;
deviceExtension->StagedPendingIrpCount = totalIrpsNeeded;
// we need to build a series of irps & urbs to represent
// this request.
while (NT_SUCCESS(ntStatus) ) {
context = (PBULKUSB_RW_CONTEXT) pCon;
irp = NULL;
urb = NULL;
mdl = NULL;
if ( !BulkUsb_CanAcceptIoRequests( DeviceObject ) ) {
// got sudden remove! ( i.e. plug was yanked )
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
BULKUSB_KdPrint ( DBGLVL_MAXIMUM, ("BulkUsb_StagedReadWrite() got sudden remove, breaking out of URB-building loop\n"));
break;
}
stackSize = (CCHAR)(deviceExtension->TopOfStackDeviceObject->StackSize + 1);
irp = IoAllocateIrp(stackSize, FALSE);
// Get the virtual address for the buffer described by
// our original input Irp's MDL.
va = MmGetMdlVirtualAddress(Irp->MdlAddress);
if (irp) {
// Each new Irp will 'see' the entire buffer, but map it's IO location
// to a single ChunkSize section within it via IoBuildPartialMdl()
mdl = IoAllocateMdl(va,
totalLength,
FALSE,
FALSE,
irp);
}
if (mdl) {
// see if we're done yet
if( ( used + ChunkSize ) > totalLength ) {
// make sure to truncate last transfer if neccy
ChunkSize = totalLength - used;
}
// Map the sub-area of the full user buffer this staged Irp will be using for IO
IoBuildPartialMdl(Irp->MdlAddress, // Points to an MDL describing the original buffer,
// of which a subrange is to be mapped
mdl, // our allocated target mdl
(PUCHAR)va + used, // base virtual address of area to be mapped
ChunkSize); // size of area to be mapped
used+=ChunkSize;
urb = BulkUsb_BuildAsyncRequest(DeviceObject,
irp,
pipeHandle,
Read);
}
if (urb && irp && mdl) {
context->Urb = urb;
context->DeviceObject = DeviceObject;
context->Irp = irp;
nIrps++;
// IoGetNextIrpStackLocation gives a higher level driver access to the next-lower
// driver's I/O stack location in an IRP so the caller can set it up for the lower driver.
nextStack = IoGetNextIrpStackLocation(irp);
BULKUSB_ASSERT(nextStack != NULL);
BULKUSB_ASSERT(DeviceObject->StackSize>1);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(irp,
BulkUsb_AsyncReadWrite_Complete,
context, // pass the context array element to completion routine
TRUE, // invoke on success
TRUE, // invoke on error
TRUE); // invoke on cancellation of the Irp
BULKUSB_KdPrint ( DBGLVL_MAXIMUM, ("BulkUsb_StagedReadWrite() created staged irp #%d %x\n", nIrps, irp));
// We keep an array of all pending read/write Irps; we may have to cancel
// them explicitly on sudden device removal or other error
(( PBULKUSB_RW_CONTEXT) pCon)->Irp = irp;
BulkUsb_IncrementIoCount(DeviceObject);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
(( PBULKUSB_RW_CONTEXT) pCon)->Irp);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() Dumped from irp loop on failed Irp or urb allocate\n"));
break;
}
if (used >= totalLength) {
break; // we're done
}
// point to next BULKUSB_RW_CONTEXT struct
pCon += sizeof(BULKUSB_RW_CONTEXT);
} // end while
Irp->IoStatus.Status = ntStatus;
if (!NT_SUCCESS(ntStatus)) {
BULKUSB_KdPrint ( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() FAILED, ntStatus = 0x%x\n", ntStatus));
// try to reset the pipe on error ( unless device has been suddenly removed )
if ( pipeHandle && BulkUsb_CanAcceptIoRequests( DeviceObject ) ) {
resetPipeStatus = BulkUsb_ResetPipe(DeviceObject, pipeHandle );
BULKUSB_KdPrint( DBGLVL_DEFAULT, ("BulkUsb_StagedReadWrite() Tried to reset pipe 0x%x, Status = 0x%x\n", pipeHandle, resetPipeStatus));
BULKUSB_KdPrintCond ( DBGLVL_DEFAULT, (!NT_SUCCESS(resetPipeStatus)), ("BulkUsb_StagedReadWrite() BulkUsb_ResetPipe() FAILED\n"));
if( !NT_SUCCESS(resetPipeStatus) ) {
// if can't reset pipe, try to reset device ( parent port )
BULKUSB_KdPrint( DBGLVL_DEFAULT, ("Will try to reset device \n"));
resetPipeStatus = BulkUsb_ResetDevice(DeviceObject);
BULKUSB_KdPrintCond ( DBGLVL_DEFAULT, (!NT_SUCCESS(resetPipeStatus)), ("BulkUsb_StagedReadWrite() BulkUsb_ResetDevice() FAILED\n"));
}
}
} // end, if !NT_SUCCESS( ntStatus )
if ( 0 == nIrps ) {
// only complete the request here if we created no staged irps
BULKUSB_KdPrint ( DBGLVL_HIGH, ("BulkUsb_StagedReadWrite() 0 irps staged, completing base IRP now!\n"));
IoCompleteRequest (Irp, IO_NO_INCREMENT );
} else {
BULKUSB_KdPrint ( DBGLVL_HIGH, ("BulkUsb_StagedReadWrite() %d irps staged\n", nIrps));
if ( deviceExtension->BaseIrp ) {
//
// Mark the original input Irp pending; it will be completed when the last staged irp
// is handled ( in BulkUsb_AsyncReadWrite_Complete() ).
//
BULKUSB_KdPrint ( DBGLVL_HIGH, ("BulkUsb_StagedReadWrite(),marking base IRP 0x%x pending!\n", Irp));
BULKUSB_ASSERT( Irp == deviceExtension->BaseIrp );
ntStatus = STATUS_PENDING;
Irp->IoStatus.Status = ntStatus;
IoMarkIrpPending(Irp);
} else {
// It is possible for BulkUsb_AsyncReadWrite_Complete() to have completed the
// original irp before we even get here!
// If this happens, it will have NULLED-out deviceExtension->BaseIrp.
ntStatus = STATUS_SUCCESS;
}
}
BULKUSB_KdPrint ( DBGLVL_HIGH, ("BulkUsb_StagedReadWrite() StagedReadWrite ntStatus = 0x%x decimal %d\n", ntStatus, ntStatus));
BULKUSB_KdPrint ( DBGLVL_HIGH, ("EXIT BulkUsb_StagedReadWrite() gExAllocCount = dec %d\n", gExAllocCount ));
return ntStatus;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -