ULONG seglen= length;
if (seglen > pdx->maxtransfer)
{
seglen = pdx->maxtransfer;
KdPrint((DRIVERNAME " - Read/write of %d bytes will be done in segments of %d\n",
length,
seglen));
}
//---------------------------------------------------------------------------
// Allocate an MDL for each segment of the transfer. The parameters are chosen so
// that the MDL will have room for a maximum-sized buffer in the worst case where
// it starts just before a page boundary. (Note that the virtual address argument to
// IoAllocateMdl is not actually used as an address.)
//---------------------------------------------------------------------------
PMDL mdl = IoAllocateMdl((PVOID) (PAGE_SIZE - 1), seglen, FALSE, FALSE, NULL);
if (!mdl) // can't allocate MDL
{
KdPrint((DRIVERNAME " - Can't allocate memory for MDL\n"));
ExFreePool(ctx);
StartNextPacket(&pdx->dqReadWrite, fdo);
CompleteRequest(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
}
//---------------------------------------------------------------------------
// Initialize the (partial) MDL to describe the first segment's subset of the user buffer.
//---------------------------------------------------------------------------
IoBuildPartialMdl(Irp->MdlAddress, mdl, (PVOID) va, seglen);
//---------------------------------------------------------------------------
// Reader Peter Diaconesco ran across an apparent bug in the Win2K version of
// UHCD.SYS. Under heavy load conditions, UHCD was bug-checking because its
// internal call to MmGetSystemAddressForMdl was apparently returning NULL
// (even though it's not supposed to). We can prevent that problem by mapping
// the pages in the following "safe" manner:
//---------------------------------------------------------------------------
if (!GenericGetSystemAddressForMdl(mdl)) // can't map transfer segment
{
KdPrint((DRIVERNAME " - Can't map memory for read or write\n"));
ExFreePool(ctx);
StartNextPacket(&pdx->dqReadWrite, fdo);
CompleteRequest(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return;
}
UsbBuildInterruptOrBulkTransferRequest(ctx,
sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
hpipe,
NULL,
mdl,
seglen,
urbflags,
NULL);
//---------------------------------------------------------------------------
// Set context structure parameters to pick up where we just left off
//---------------------------------------------------------------------------
ctx->va = va + seglen;
ctx->length = length - seglen;
ctx->mdl = mdl;
ctx->numxfer = 0;
//---------------------------------------------------------------------------
// Use the original Read or Write IRP as a container for the URB
//---------------------------------------------------------------------------
stack = IoGetNextIrpStackLocation(Irp);
stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
stack->Parameters.Others.Argument1 = (PVOID) (PURB) ctx;
stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
//KdPrint((" \n TransferBufferMDL: %x \n", ctx->UrbBulkOrInterruptTransfer.TransferBufferMDL));
if (NT_SUCCESS(status) && ctx->length && !Irp->Cancel) // start next stage
{ // start next stage
...
//数据包比较大需多次传输时使用的,没有执行过
} //end:if (NT_SUCCESS(status) && ctx->length && !Irp->Cancel) // start next stage
//---------------------------------------------------------------------------
// The request is complete now
//---------------------------------------------------------------------------
FinishCompletion: // label reached if MDL locking fails
if (NT_SUCCESS(status))
Irp->IoStatus.Information = ctx->numxfer;
else
{ // had an error
....