Implemented request-splitting.

svn path=/trunk/; revision=2866
This commit is contained in:
Eric Kohl 2002-04-24 22:20:50 +00:00
parent c1e3c3d7fe
commit 8c136a909a

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: class2.c,v 1.15 2002/04/01 23:51:09 ekohl Exp $ /* $Id: class2.c,v 1.16 2002/04/24 22:20:50 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -882,12 +882,14 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
#if 0 #if 0
if (!NT_SUCCESS(Status) && if (!NT_SUCCESS(Status))
IoIsErrorUserInduced(Status)) {
Irp->IoStatus.Information = 0;
if (IoIsErrorUserInduced(Status))
{ {
IoSetHardErrorOrVerifyDevice(Irp, IoSetHardErrorOrVerifyDevice(Irp,
DeviceObject); DeviceObject);
Irp->IoStatus.Information = 0; }
} }
if (Irp->PendingReturned) if (Irp->PendingReturned)
@ -916,7 +918,97 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
PIRP Irp, PIRP Irp,
PVOID Context) PVOID Context)
{ {
UNIMPLEMENTED; PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
PIRP MasterIrp;
BOOLEAN Retry;
LONG RequestCount;
NTSTATUS Status;
DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n",
DeviceObject, Irp, Context);
MasterIrp = Irp->AssociatedIrp.MasterIrp;
DeviceExtension = DeviceObject->DeviceExtension;
Srb = (PSCSI_REQUEST_BLOCK)Context;
DPRINT("Srb %p\n", Srb);
IrpStack = IoGetCurrentIrpStackLocation(Irp);
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
{
Status = STATUS_SUCCESS;
}
else
{
/* Get more detailed status information */
Retry = ScsiClassInterpretSenseInfo(DeviceObject,
Srb,
IrpStack->MajorFunction,
0,
MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
&Status);
DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
if ((Retry == TRUE) &&
((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
{
((ULONG)IrpStack->Parameters.Others.Argument4)--;
DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
DPRINT1("Should try again!\n");
#ifdef ENABLE_RETRY
ScsiClassRetryRequest(DeviceObject,
Irp,
Srb);
return(STATUS_MORE_PROCESSING_REQUIRED);
#else
return(Status);
#endif
}
}
/* FIXME: use lookaside list instead */
DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
ExFreePool(IrpStack->Parameters.Scsi.Srb);
Irp->IoStatus.Status = Status;
IrpStack = IoGetNextIrpStackLocation(MasterIrp);
if (!NT_SUCCESS(Status))
{
MasterIrp->IoStatus.Status = Status;
MasterIrp->IoStatus.Information = 0;
if (IoIsErrorUserInduced(Status))
{
IoSetHardErrorOrVerifyDevice(MasterIrp,
DeviceObject);
}
}
/* Decrement the request counter in the Master IRP */
RequestCount = InterlockedDecrement((PLONG)&IrpStack->Parameters.Others.Argument1);
if (RequestCount == 0)
{
/* Complete the Master IRP */
IoCompleteRequest(MasterIrp,
IO_DISK_INCREMENT);
if (DeviceExtension->ClassStartIo)
{
IoStartNextPacket(DeviceObject,
FALSE);
}
}
/* Free the current IRP */
IoFreeIrp(Irp);
return(STATUS_MORE_PROCESSING_REQUIRED);
} }
@ -1069,7 +1161,7 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
ULONG RequestType; ULONG RequestType;
BOOLEAN Retry; BOOLEAN Retry;
ULONG RetryCount; ULONG RetryCount;
KEVENT Event; PKEVENT Event;
PIRP Irp; PIRP Irp;
NTSTATUS Status; NTSTATUS Status;
@ -1116,8 +1208,9 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
Srb->DataTransferLength = BufferLength; Srb->DataTransferLength = BufferLength;
Srb->DataBuffer = BufferAddress; Srb->DataBuffer = BufferAddress;
Event = ExAllocatePool(NonPagedPool,
KeInitializeEvent(&Event, sizeof(KEVENT));
KeInitializeEvent(Event,
NotificationEvent, NotificationEvent,
FALSE); FALSE);
@ -1128,12 +1221,13 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
BufferAddress, BufferAddress,
BufferLength, BufferLength,
TRUE, TRUE,
&Event, Event,
&IoStatusBlock); &IoStatusBlock);
if (Irp == NULL) if (Irp == NULL)
{ {
DPRINT1("IoBuildDeviceIoControlRequest() failed\n"); DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
ExFreePool(Srb->SenseInfoBuffer); ExFreePool(Srb->SenseInfoBuffer);
ExFreePool(Event);
return(STATUS_INSUFFICIENT_RESOURCES); return(STATUS_INSUFFICIENT_RESOURCES);
} }
@ -1151,7 +1245,7 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
Irp); Irp);
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
{ {
KeWaitForSingleObject(&Event, KeWaitForSingleObject(Event,
Suspended, Suspended,
KernelMode, KernelMode,
FALSE, FALSE,
@ -1179,6 +1273,7 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
} }
ExFreePool(Srb->SenseInfoBuffer); ExFreePool(Srb->SenseInfoBuffer);
ExFreePool(Event);
DPRINT("ScsiClassSendSrbSynchronous() done\n"); DPRINT("ScsiClassSendSrbSynchronous() done\n");
@ -1191,7 +1286,92 @@ ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
PIRP Irp, PIRP Irp,
ULONG MaximumBytes) ULONG MaximumBytes)
{ {
UNIMPLEMENTED; PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION CurrentStack;
PIO_STACK_LOCATION NextStack;
PIO_STACK_LOCATION NewStack;
PSCSI_REQUEST_BLOCK Srb;
LARGE_INTEGER Offset;
PIRP NewIrp;
PVOID DataBuffer;
ULONG TransferLength;
ULONG RequestCount;
ULONG DataLength;
ULONG i;
DPRINT1("ScsiClassSplitRequest(DeviceObject %lx Irp %lx MaximumBytes %lu)\n",
DeviceObject, Irp, MaximumBytes);
DeviceExtension = DeviceObject->DeviceExtension;
CurrentStack = IoGetCurrentIrpStackLocation(Irp);
NextStack = IoGetNextIrpStackLocation(Irp);
DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
/* Initialize transfer data for first request */
Offset = CurrentStack->Parameters.Read.ByteOffset;
TransferLength = CurrentStack->Parameters.Read.Length;
DataLength = MaximumBytes;
RequestCount = ROUND_UP(TransferLength, MaximumBytes) / MaximumBytes;
/* Save request count in the original IRP */
NextStack->Parameters.Others.Argument1 = (PVOID)RequestCount;
DPRINT1("RequestCount %lu\n", RequestCount);
for (i = 0; i < RequestCount; i++)
{
/* Create a new IRP */
NewIrp = IoAllocateIrp(DeviceObject->StackSize,
FALSE);
if (NewIrp == NULL)
{
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
if (i == 0)
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
return;
}
/* Initialize the new IRP */
NewIrp->MdlAddress = Irp->MdlAddress;
IoSetNextIrpStackLocation(NewIrp);
NewStack = IoGetCurrentIrpStackLocation(NewIrp);
NewStack->MajorFunction = CurrentStack->MajorFunction;
NewStack->Parameters.Read.ByteOffset = Offset;
NewStack->Parameters.Read.Length = DataLength;
NewStack->DeviceObject = DeviceObject;
ScsiClassBuildRequest(DeviceObject,
NewIrp);
NewStack = IoGetNextIrpStackLocation(NewIrp);
Srb = NewStack->Parameters.Others.Argument1;
Srb->DataBuffer = DataBuffer;
NewIrp->AssociatedIrp.MasterIrp = Irp;
/* Initialize completion routine */
IoSetCompletionRoutine(NewIrp,
ScsiClassIoCompleteAssociated,
Srb,
TRUE,
TRUE,
TRUE);
/* Send the new IRP down to the port driver */
IoCallDriver(DeviceExtension->PortDeviceObject,
NewIrp);
/* Adjust transfer data for next request */
DataBuffer = (PCHAR)DataBuffer + MaximumBytes;
TransferLength -= MaximumBytes;
DataLength = (TransferLength > MaximumBytes) ? MaximumBytes : TransferLength;
Offset.QuadPart = Offset.QuadPart + MaximumBytes;
}
} }
@ -1225,8 +1405,10 @@ ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
{ {
PDEVICE_EXTENSION DeviceExtension; PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack; PIO_STACK_LOCATION IrpStack;
ULONG TransferLength; ULONG MaximumTransferLength;
ULONG TransferPages; ULONG CurrentTransferLength;
ULONG MaximumTransferPages;
ULONG CurrentTransferPages;
NTSTATUS Status; NTSTATUS Status;
DPRINT("ScsiClassReadWrite() called\n"); DPRINT("ScsiClassReadWrite() called\n");
@ -1238,7 +1420,12 @@ ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
IrpStack->Parameters.Read.ByteOffset.QuadPart, IrpStack->Parameters.Read.ByteOffset.QuadPart,
IrpStack->Parameters.Read.Length); IrpStack->Parameters.Read.Length);
TransferLength = IrpStack->Parameters.Read.Length; // MaximumTransferLength = DeviceExtension->PortCapabilities->MaximumTransferLength;
// MaximumTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages;
MaximumTransferLength = 0x10000; /* 64 kbytes */
MaximumTransferPages = MaximumTransferLength / PAGESIZE;
CurrentTransferLength = IrpStack->Parameters.Read.Length;
if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && if ((DeviceObject->Flags & DO_VERIFY_VOLUME) &&
!(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) !(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
@ -1270,7 +1457,7 @@ ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
} }
/* Finish a zero-byte transfer */ /* Finish a zero-byte transfer */
if (TransferLength == 0) if (CurrentTransferLength == 0)
{ {
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
@ -1298,16 +1485,34 @@ ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart; IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart;
/* Calculate number of pages in this transfer */ /* Calculate number of pages in this transfer */
TransferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), CurrentTransferPages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
IrpStack->Parameters.Read.Length); IrpStack->Parameters.Read.Length);
#if 0 if (CurrentTransferLength > MaximumTransferLength ||
if (TransferLength > maximumTransferLength || CurrentTransferPages > MaximumTransferPages)
TransferPages > DeviceExtension->PortCapabilities->MaximumPhysicalPages)
{ {
/* FIXME: split request */ DPRINT1("Split current request: MaximumTransferLength %lu CurrentTransferLength %lu\n",
MaximumTransferLength, CurrentTransferLength);
/* Adjust the maximum transfer length */
CurrentTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
if (MaximumTransferLength > CurrentTransferPages * PAGESIZE)
MaximumTransferLength = CurrentTransferPages * PAGESIZE;
if (MaximumTransferLength == 0)
MaximumTransferLength = PAGESIZE;
IoMarkIrpPending(Irp);
/* Split current request */
ScsiClassSplitRequest(DeviceObject,
Irp,
MaximumTransferLength);
return(STATUS_PENDING);
} }
#endif
ScsiClassBuildRequest(DeviceObject, ScsiClassBuildRequest(DeviceObject,
Irp); Irp);