mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 12:29:56 +00:00
Implemented request-splitting.
svn path=/trunk/; revision=2866
This commit is contained in:
parent
c1e3c3d7fe
commit
8c136a909a
1 changed files with 228 additions and 23 deletions
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue