3 * Copyright (C) 2001, 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/class2/class2.c
24 * PURPOSE: SCSI class driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
30 * - finish ScsiClassDeviceControl().
33 /* INCLUDES *****************************************************************/
35 #include <ddk/ntddk.h>
37 #include <ddk/class2.h>
43 #define VERSION "0.0.1"
45 #define TAG_SRBT TAG('S', 'r', 'b', 'T')
47 #define INQUIRY_DATA_SIZE 2048
50 static NTSTATUS STDCALL
51 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
54 static NTSTATUS STDCALL
55 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
58 static NTSTATUS STDCALL
59 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
62 static NTSTATUS STDCALL
63 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
66 static NTSTATUS STDCALL
67 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
71 ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
72 PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated);
74 /* FUNCTIONS ****************************************************************/
76 /**********************************************************************
81 * This function initializes the driver.
88 * System allocated Driver Object for this driver.
90 * Name of registry driver service key.
97 DriverEntry(IN PDRIVER_OBJECT DriverObject,
98 IN PUNICODE_STRING RegistryPath)
100 DPRINT("Class Driver %s\n", VERSION);
101 return(STATUS_SUCCESS);
106 ScsiClassDebugPrint(IN ULONG DebugPrintLevel,
107 IN PCHAR DebugMessage,
114 if (DebugPrintLevel > InternalDebugLevel)
118 va_start(ap, DebugMessage);
119 vsprintf(Buffer, DebugMessage, ap);
127 ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
136 ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
139 PDEVICE_EXTENSION DeviceExtension;
140 PIO_STACK_LOCATION CurrentIrpStack;
141 PIO_STACK_LOCATION NextIrpStack;
142 LARGE_INTEGER StartingOffset;
143 LARGE_INTEGER StartingBlock;
144 PSCSI_REQUEST_BLOCK Srb;
146 ULONG LogicalBlockAddress;
147 USHORT TransferBlocks;
149 DeviceExtension = DeviceObject->DeviceExtension;
150 CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
151 NextIrpStack = IoGetNextIrpStackLocation(Irp);
152 StartingOffset = CurrentIrpStack->Parameters.Read.ByteOffset;
154 /* Calculate logical block address */
155 StartingBlock.QuadPart = StartingOffset.QuadPart >> DeviceExtension->SectorShift;
156 LogicalBlockAddress = (ULONG)StartingBlock.u.LowPart;
158 DPRINT("Logical block address: %lu\n", LogicalBlockAddress);
160 /* Allocate and initialize an SRB */
161 Srb = ExAllocateFromNPagedLookasideList(&DeviceExtension->SrbLookasideListHead);
164 Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE;
165 Srb->OriginalRequest = Irp;
166 Srb->PathId = DeviceExtension->PathId;
167 Srb->TargetId = DeviceExtension->TargetId;
168 Srb->Lun = DeviceExtension->Lun;
169 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
170 //FIXME: NT4 DDK sample uses MmGetMdlVirtualAddress! Why shouldn't we?
171 Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
172 Srb->DataTransferLength = CurrentIrpStack->Parameters.Read.Length;
173 Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
174 Srb->QueueSortKey = LogicalBlockAddress;
176 Srb->SenseInfoBuffer = DeviceExtension->SenseData;
177 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
180 ((Srb->DataTransferLength + 0xFFFF) >> 16) * DeviceExtension->TimeOutValue;
182 Srb->SrbStatus = SRB_STATUS_SUCCESS;
187 Cdb = (PCDB)Srb->Cdb;
189 /* Initialize ATAPI packet (12 bytes) */
193 Cdb->CDB10.LogicalUnitNumber = DeviceExtension->Lun;
194 TransferBlocks = (USHORT)(CurrentIrpStack->Parameters.Read.Length >> DeviceExtension->SectorShift);
196 /* Copy little endian values into CDB in big endian format */
197 Cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte3;
198 Cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte2;
199 Cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte1;
200 Cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte0;
202 Cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&TransferBlocks)->Byte1;
203 Cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&TransferBlocks)->Byte0;
206 if (CurrentIrpStack->MajorFunction == IRP_MJ_READ)
208 DPRINT("ScsiClassBuildRequest: Read Command\n");
210 Srb->SrbFlags |= SRB_FLAGS_DATA_IN;
211 Cdb->CDB10.OperationCode = SCSIOP_READ;
215 DPRINT("ScsiClassBuildRequest: Write Command\n");
217 Srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
218 Cdb->CDB10.OperationCode = SCSIOP_WRITE;
222 /* if this is not a write-through request, then allow caching */
223 if (!(CurrentIrpStack->Flags & SL_WRITE_THROUGH))
225 Srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE;
227 else if (DeviceExtension->DeviceFlags & DEV_WRITE_CACHE)
229 /* if write caching is enable then force media access in the cdb */
230 Cdb->CDB10.ForceUnitAccess = TRUE;
234 /* Update srb flags */
235 Srb->SrbFlags |= DeviceExtension->SrbFlags;
237 /* Initialize next stack location */
238 NextIrpStack->MajorFunction = IRP_MJ_SCSI;
239 NextIrpStack->Parameters.Scsi.Srb = Srb;
241 /* Set retry count */
242 CurrentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
244 DPRINT("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp, Srb);
245 IoSetCompletionRoutine(Irp,
255 ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
256 PSCSI_INQUIRY_DATA LunInfo,
258 PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL)
260 PIO_STACK_LOCATION IoStack;
261 IO_STATUS_BLOCK IoStatusBlock;
262 SCSI_REQUEST_BLOCK Srb;
267 DPRINT("ScsiClassClaimDevice() called\n");
269 if (NewPortDeviceObject != NULL)
270 *NewPortDeviceObject = NULL;
272 /* initialize an SRB */
274 sizeof(SCSI_REQUEST_BLOCK));
275 Srb.Length = SCSI_REQUEST_BLOCK_SIZE;
276 Srb.PathId = LunInfo->PathId;
277 Srb.TargetId = LunInfo->TargetId;
278 Srb.Lun = LunInfo->Lun;
280 (Release == TRUE) ? SRB_FUNCTION_RELEASE_DEVICE : SRB_FUNCTION_CLAIM_DEVICE;
282 KeInitializeEvent(&Event,
286 Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE,
297 DPRINT("Failed to allocate Irp!\n");
298 return(STATUS_INSUFFICIENT_RESOURCES);
301 /* Link Srb and Irp */
302 IoStack = IoGetNextIrpStackLocation(Irp);
303 IoStack->Parameters.Scsi.Srb = &Srb;
304 Srb.OriginalRequest = Irp;
306 /* Call SCSI port driver */
307 Status = IoCallDriver(PortDeviceObject,
309 if (Status == STATUS_PENDING)
311 KeWaitForSingleObject(&Event,
316 Status = IoStatusBlock.Status;
321 ObDereferenceObject(PortDeviceObject);
322 return(STATUS_SUCCESS);
325 // Status = ObReferenceObjectByPointer(Srb.DataBuffer,
326 Status = ObReferenceObjectByPointer(PortDeviceObject,
331 if (NewPortDeviceObject != NULL)
333 // *NewPortDeviceObject = Srb.DataBuffer;
334 *NewPortDeviceObject = PortDeviceObject;
337 return(STATUS_SUCCESS);
342 ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
343 IN PCCHAR ObjectNameBuffer,
344 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
345 IN OUT PDEVICE_OBJECT *DeviceObject,
346 IN PCLASS_INIT_DATA InitializationData)
348 PDEVICE_OBJECT InternalDeviceObject;
349 PDEVICE_EXTENSION DeviceExtension;
350 ANSI_STRING AnsiName;
351 UNICODE_STRING DeviceName;
354 DPRINT("ScsiClassCreateDeviceObject() called\n");
356 *DeviceObject = NULL;
358 RtlInitAnsiString(&AnsiName,
361 Status = RtlAnsiStringToUnicodeString(&DeviceName,
364 if (!NT_SUCCESS(Status))
369 DPRINT("Device name: '%wZ'\n", &DeviceName);
371 Status = IoCreateDevice(DriverObject,
372 InitializationData->DeviceExtensionSize,
374 InitializationData->DeviceType,
375 InitializationData->DeviceCharacteristics,
377 &InternalDeviceObject);
378 if (NT_SUCCESS(Status))
380 DeviceExtension = InternalDeviceObject->DeviceExtension;
382 DeviceExtension->ClassError = InitializationData->ClassError;
383 DeviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification;
384 DeviceExtension->ClassFindDevices = InitializationData->ClassFindDevices;
385 DeviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl;
386 DeviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush;
387 DeviceExtension->ClassCreateClose = InitializationData->ClassCreateClose;
388 DeviceExtension->ClassStartIo = InitializationData->ClassStartIo;
390 DeviceExtension->MediaChangeCount = 0;
392 if (PhysicalDeviceObject != NULL)
394 DeviceExtension->PhysicalDevice = PhysicalDeviceObject;
398 DeviceExtension->PhysicalDevice = InternalDeviceObject;
401 *DeviceObject = InternalDeviceObject;
404 RtlFreeUnicodeString(&DeviceName);
411 ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
414 PDEVICE_EXTENSION DeviceExtension;
415 PIO_STACK_LOCATION Stack;
417 ULONG OutputBufferLength;
419 DPRINT("ScsiClassDeviceControl() called\n");
421 DeviceExtension = DeviceObject->DeviceExtension;
422 Stack = IoGetCurrentIrpStackLocation(Irp);
424 IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
425 OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
427 if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
429 PSCSI_ADDRESS ScsiAddress;
431 if (OutputBufferLength < sizeof(SCSI_ADDRESS))
433 Irp->IoStatus.Information = 0;
434 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
435 IoCompleteRequest(Irp, IO_NO_INCREMENT);
437 return(STATUS_BUFFER_TOO_SMALL);
440 ScsiAddress = Irp->AssociatedIrp.SystemBuffer;
441 ScsiAddress->Length = sizeof(SCSI_ADDRESS);
442 ScsiAddress->PortNumber = DeviceExtension->PortNumber;
443 ScsiAddress->PathId = DeviceExtension->PathId;
444 ScsiAddress->TargetId = DeviceExtension->TargetId;
445 ScsiAddress->Lun = DeviceExtension->Lun;
447 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
448 Irp->IoStatus.Status = STATUS_SUCCESS;
449 IoCompleteRequest(Irp, IO_NO_INCREMENT);
451 return(STATUS_SUCCESS);
454 if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
455 IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
457 DPRINT1("Fixme: IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
460 Irp->IoStatus.Information = 0;
461 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
462 IoCompleteRequest(Irp, IO_NO_INCREMENT);
464 return(STATUS_UNSUCCESSFUL);
467 DPRINT1("Fixme: unknown device io control code\n");
469 Irp->IoStatus.Information = 0;
470 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
471 IoCompleteRequest(Irp, IO_NO_INCREMENT);
473 return(STATUS_UNSUCCESSFUL);
478 ScsiClassFindModePage(PCHAR ModeSenseBuffer,
488 ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
489 PSCSI_ADAPTER_BUS_INFO AdapterInformation)
491 PSCSI_INQUIRY_DATA UnitInfo;
492 PINQUIRYDATA InquiryData;
495 ULONG UnclaimedDevices = 0;
498 DPRINT("ScsiClassFindUnclaimedDevices() called\n");
500 DPRINT("NumberOfBuses: %lu\n",AdapterInformation->NumberOfBuses);
501 Buffer = (PUCHAR)AdapterInformation;
502 for (Bus = 0; Bus < (ULONG)AdapterInformation->NumberOfBuses; Bus++)
504 DPRINT("Searching bus %lu\n", Bus);
506 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterInformation->BusData[Bus].InquiryDataOffset);
508 while (AdapterInformation->BusData[Bus].InquiryDataOffset)
510 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
512 DPRINT("Device: '%.8s'\n", InquiryData->VendorId);
514 if ((InitializationData->ClassFindDeviceCallBack(InquiryData) == TRUE) &&
515 (UnitInfo->DeviceClaimed == FALSE))
520 if (UnitInfo->NextInquiryDataOffset == 0)
523 UnitInfo = (PSCSI_INQUIRY_DATA) (Buffer + UnitInfo->NextInquiryDataOffset);
527 return(UnclaimedDevices);
532 ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
533 PIO_SCSI_CAPABILITIES *PortCapabilities)
535 IO_STATUS_BLOCK IoStatusBlock;
540 KeInitializeEvent(&Event,
544 Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES,
555 return(STATUS_INSUFFICIENT_RESOURCES);
558 Status = IoCallDriver(PortDeviceObject,
560 if (Status == STATUS_PENDING)
562 KeWaitForSingleObject(&Event,
567 Status = IoStatusBlock.Status;
570 DPRINT("PortCapabilities at %p\n", *PortCapabilities);
577 ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
578 PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
580 PSCSI_ADAPTER_BUS_INFO Buffer;
581 IO_STATUS_BLOCK IoStatusBlock;
586 DPRINT("ScsiClassGetInquiryData() called\n");
589 Buffer = ExAllocatePool(NonPagedPool,
593 return(STATUS_INSUFFICIENT_RESOURCES);
596 KeInitializeEvent(&Event,
600 Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA,
612 return(STATUS_INSUFFICIENT_RESOURCES);
615 Status = IoCallDriver(PortDeviceObject,
617 if (Status == STATUS_PENDING)
619 KeWaitForSingleObject(&Event,
624 Status = IoStatusBlock.Status;
627 if (!NT_SUCCESS(Status))
633 *ConfigInfo = Buffer;
636 DPRINT("ScsiClassGetInquiryData() done\n");
643 ScsiClassInitialize(PVOID Argument1,
645 PCLASS_INIT_DATA InitializationData)
647 PCONFIGURATION_INFORMATION ConfigInfo;
648 PDRIVER_OBJECT DriverObject = Argument1;
649 WCHAR NameBuffer[80];
650 UNICODE_STRING PortName;
652 PDEVICE_OBJECT PortDeviceObject;
653 PFILE_OBJECT FileObject;
654 BOOLEAN DiskFound = FALSE;
657 DPRINT("ScsiClassInitialize() called!\n");
659 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
660 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
661 DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
662 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
663 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassScsiDispatch;
664 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
665 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
666 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
667 if (InitializationData->ClassStartIo)
669 DriverObject->DriverStartIo = InitializationData->ClassStartIo;
672 ConfigInfo = IoGetConfigurationInformation();
674 DPRINT("ScsiPorts: %lu\n", ConfigInfo->ScsiPortCount);
676 /* look for ScsiPortX scsi port devices */
677 for (PortNumber = 0; PortNumber < ConfigInfo->ScsiPortCount; PortNumber++)
680 L"\\Device\\ScsiPort%lu",
682 RtlInitUnicodeString(&PortName,
684 DPRINT("Checking scsi port %ld\n", PortNumber);
685 Status = IoGetDeviceObjectPointer(&PortName,
686 FILE_READ_ATTRIBUTES,
689 DPRINT("Status 0x%08lX\n", Status);
690 if (NT_SUCCESS(Status))
692 DPRINT("ScsiPort%lu found.\n", PortNumber);
694 /* check scsi port for attached disk drives */
695 if (InitializationData->ClassFindDevices(DriverObject,
706 DbgPrint("Couldn't find ScsiPort%lu (Status %lx)\n", PortNumber, Status);
710 DPRINT("ScsiClassInitialize() done!\n");
712 return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE);
716 /**********************************************************************
718 * ScsiClassInitializeSrbLookasideList
721 * Initializes a lookaside list for SRBs.
728 * Class specific device extension.
731 * Maximum number of elements of the lookaside list.
738 ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension,
739 ULONG NumberElements)
741 ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
745 sizeof(SCSI_REQUEST_BLOCK),
747 (USHORT)NumberElements);
752 ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject,
760 ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
761 PSCSI_REQUEST_BLOCK Srb,
762 UCHAR MajorFunctionCode,
767 PDEVICE_EXTENSION DeviceExtension;
768 PSENSE_DATA SenseData;
771 DPRINT("ScsiClassInterpretSenseInfo() called\n");
773 DPRINT("Srb->SrbStatus %lx\n", Srb->SrbStatus);
775 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING)
777 *Status = STATUS_SUCCESS;
781 DeviceExtension = DeviceObject->DeviceExtension;
782 SenseData = Srb->SenseInfoBuffer;
785 if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
786 (Srb->SenseInfoBufferLength > 0))
788 /* Got valid sense data, interpret them */
790 DPRINT("ErrorCode: %x\n", SenseData->ErrorCode);
791 DPRINT("SenseKey: %x\n", SenseData->SenseKey);
792 DPRINT("SenseCode: %x\n", SenseData->AdditionalSenseCode);
794 switch (SenseData->SenseKey & 0xf)
796 /* FIXME: add more sense key codes */
798 case SCSI_SENSE_NOT_READY:
799 DPRINT("SCSI_SENSE_NOT_READY\n");
800 *Status = STATUS_DEVICE_NOT_READY;
803 case SCSI_SENSE_UNIT_ATTENTION:
804 DPRINT("SCSI_SENSE_UNIT_ATTENTION\n");
805 if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
806 (DeviceObject->Vpb->Flags & VPB_MOUNTED))
808 DeviceObject->Flags |= DO_VERIFY_VOLUME;
809 *Status = STATUS_VERIFY_REQUIRED;
814 *Status = STATUS_IO_DEVICE_ERROR;
818 case SCSI_SENSE_ILLEGAL_REQUEST:
819 DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
820 *Status = STATUS_INVALID_DEVICE_REQUEST;
826 DPRINT1("SCSI error (sense key: %x)\n",
827 SenseData->SenseKey & 0xf);
828 *Status = STATUS_IO_DEVICE_ERROR;
834 /* Got no or invalid sense data, return generic error codes */
835 switch (SRB_STATUS(Srb->SrbStatus))
837 /* FIXME: add more srb status codes */
839 case SRB_STATUS_INVALID_PATH_ID:
840 case SRB_STATUS_INVALID_TARGET_ID:
841 case SRB_STATUS_INVALID_LUN:
842 case SRB_STATUS_NO_DEVICE:
843 case SRB_STATUS_NO_HBA:
844 *Status = STATUS_NO_SUCH_DEVICE;
848 case SRB_STATUS_BUSY:
849 *Status = STATUS_DEVICE_BUSY;
853 case SRB_STATUS_DATA_OVERRUN:
854 *Status = STATUS_DATA_OVERRUN;
859 DPRINT1("SCSI error (SRB status: %x)\n",
860 SRB_STATUS(Srb->SrbStatus));
861 *Status = STATUS_IO_DEVICE_ERROR;
866 /* Call the class driver specific error function */
867 if (DeviceExtension->ClassError != NULL)
869 DeviceExtension->ClassError(DeviceObject,
875 /* FIXME: log severe errors */
877 DPRINT("ScsiClassInterpretSenseInfo() done\n");
884 ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
888 PDEVICE_EXTENSION DeviceExtension;
889 PIO_STACK_LOCATION IrpStack;
890 PSCSI_REQUEST_BLOCK Srb;
894 DPRINT("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n",
895 DeviceObject, Irp, Context);
897 DeviceExtension = DeviceObject->DeviceExtension;
899 IrpStack = IoGetCurrentIrpStackLocation(Irp);
901 //BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
902 //Must pass Srb as Context arg!! See comment about Completion routines in
903 //IofCallDriver for more info.
905 Srb = (PSCSI_REQUEST_BLOCK)Context;
907 DPRINT("Srb %p\n", Srb);
909 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
911 Status = STATUS_SUCCESS;
915 Retry = ScsiClassInterpretSenseInfo(DeviceObject,
917 IrpStack->MajorFunction,
919 MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
922 ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
924 ((ULONG)IrpStack->Parameters.Others.Argument4)--;
926 ScsiClassRetryRequest(
932 return(STATUS_MORE_PROCESSING_REQUIRED);
937 ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
940 Irp->IoStatus.Status = Status;
941 if (!NT_SUCCESS(Status))
943 Irp->IoStatus.Information = 0;
944 if (IoIsErrorUserInduced(Status))
946 IoSetHardErrorOrVerifyDevice(Irp,
951 if (DeviceExtension->ClassStartIo != NULL)
953 if (IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL)
955 IoStartNextPacket(DeviceObject,
960 DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status);
967 ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
971 PDEVICE_EXTENSION DeviceExtension;
972 PIO_STACK_LOCATION IrpStack;
973 PSCSI_REQUEST_BLOCK Srb;
979 DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n",
980 DeviceObject, Irp, Context);
982 MasterIrp = Irp->AssociatedIrp.MasterIrp;
983 DeviceExtension = DeviceObject->DeviceExtension;
985 IrpStack = IoGetCurrentIrpStackLocation(Irp);
987 //BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
988 //Must pass Srb as Context arg!! See comment about Completion routines in
989 //IofCallDriver for more info.
991 Srb = (PSCSI_REQUEST_BLOCK)Context;
993 DPRINT("Srb %p\n", Srb);
995 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
997 Status = STATUS_SUCCESS;
1001 /* Get more detailed status information */
1002 Retry = ScsiClassInterpretSenseInfo(DeviceObject,
1004 IrpStack->MajorFunction,
1006 MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
1010 ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
1012 ((ULONG)IrpStack->Parameters.Others.Argument4)--;
1014 ScsiClassRetryRequest(
1020 return(STATUS_MORE_PROCESSING_REQUIRED);
1025 ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
1028 Irp->IoStatus.Status = Status;
1030 IrpStack = IoGetNextIrpStackLocation(MasterIrp);
1031 if (!NT_SUCCESS(Status))
1033 MasterIrp->IoStatus.Status = Status;
1034 MasterIrp->IoStatus.Information = 0;
1036 if (IoIsErrorUserInduced(Status))
1038 IoSetHardErrorOrVerifyDevice(MasterIrp,
1043 /* Decrement the request counter in the Master IRP */
1044 RequestCount = InterlockedDecrement((PLONG)&IrpStack->Parameters.Others.Argument1);
1046 if (RequestCount == 0)
1048 /* Complete the Master IRP */
1049 IoCompleteRequest(MasterIrp,
1052 if (DeviceExtension->ClassStartIo)
1054 IoStartNextPacket(DeviceObject,
1059 /* Free the current IRP */
1062 return(STATUS_MORE_PROCESSING_REQUIRED);
1067 ScsiClassModeSense(PDEVICE_OBJECT DeviceObject,
1068 CHAR ModeSenseBuffer,
1077 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
1084 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
1086 PDEVICE_EXTENSION DeviceExtension;
1087 PREAD_CAPACITY_DATA CapacityBuffer;
1088 SCSI_REQUEST_BLOCK Srb;
1094 DPRINT("ScsiClassReadDriveCapacity() called\n");
1096 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1098 CapacityBuffer = ExAllocatePool(NonPagedPool,
1099 sizeof(READ_CAPACITY_DATA));
1100 if (CapacityBuffer == NULL)
1102 return(STATUS_INSUFFICIENT_RESOURCES);
1105 RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
1108 Srb.TimeOutValue = DeviceExtension->TimeOutValue;
1110 Cdb = (PCDB)Srb.Cdb;
1111 Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
1114 Status = ScsiClassSendSrbSynchronous(DeviceObject,
1117 sizeof(READ_CAPACITY_DATA),
1119 DPRINT("Status: %lx\n", Status);
1120 DPRINT("Srb: %p\n", &Srb);
1121 if (NT_SUCCESS(Status))
1123 SectorSize = (((PUCHAR)&CapacityBuffer->BytesPerBlock)[0] << 24) |
1124 (((PUCHAR)&CapacityBuffer->BytesPerBlock)[1] << 16) |
1125 (((PUCHAR)&CapacityBuffer->BytesPerBlock)[2] << 8) |
1126 ((PUCHAR)&CapacityBuffer->BytesPerBlock)[3];
1129 LastSector = (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[0] << 24) |
1130 (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[1] << 16) |
1131 (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[2] << 8) |
1132 ((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[3];
1134 DeviceExtension->DiskGeometry->BytesPerSector = SectorSize;
1136 DeviceExtension->PartitionLength.QuadPart = (LONGLONG)(LastSector + 1);
1137 WHICH_BIT(DeviceExtension->DiskGeometry->BytesPerSector,
1138 DeviceExtension->SectorShift);
1139 DeviceExtension->PartitionLength.QuadPart =
1140 (DeviceExtension->PartitionLength.QuadPart << DeviceExtension->SectorShift);
1142 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
1144 DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
1148 DeviceExtension->DiskGeometry->MediaType = FixedMedia;
1150 DeviceExtension->DiskGeometry->Cylinders.QuadPart = (LONGLONG)((LastSector + 1)/(32 * 64));
1151 DeviceExtension->DiskGeometry->SectorsPerTrack = 32;
1152 DeviceExtension->DiskGeometry->TracksPerCylinder = 64;
1154 DPRINT("SectorSize: %lu SectorCount: %lu\n", SectorSize, LastSector + 1);
1158 /* Use default values if disk geometry cannot be read */
1159 RtlZeroMemory(DeviceExtension->DiskGeometry,
1160 sizeof(DISK_GEOMETRY));
1161 DeviceExtension->DiskGeometry->BytesPerSector = 512;
1162 DeviceExtension->SectorShift = 9;
1163 DeviceExtension->PartitionLength.QuadPart = 0;
1165 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
1167 DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
1171 DeviceExtension->DiskGeometry->MediaType = FixedMedia;
1174 DPRINT("SectorSize: 512 SectorCount: 0\n");
1177 ExFreePool(CapacityBuffer);
1179 DPRINT("ScsiClassReadDriveCapacity() done\n");
1186 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
1193 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
1194 PSCSI_REQUEST_BLOCK Srb,
1196 PVOID BufferAddress,
1198 BOOLEAN WriteToDevice)
1205 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
1206 PSCSI_REQUEST_BLOCK Srb,
1207 PVOID BufferAddress,
1209 BOOLEAN WriteToDevice)
1211 PDEVICE_EXTENSION DeviceExtension;
1212 IO_STATUS_BLOCK IoStatusBlock;
1213 PIO_STACK_LOCATION IrpStack;
1221 DPRINT("ScsiClassSendSrbSynchronous() called\n");
1223 RetryCount = MAXIMUM_RETRIES;
1224 DeviceExtension = DeviceObject->DeviceExtension;
1226 Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1227 Srb->PathId = DeviceExtension->PathId;
1228 Srb->TargetId = DeviceExtension->TargetId;
1229 Srb->Lun = DeviceExtension->Lun;
1230 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1232 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1233 Srb->SenseInfoBuffer = ExAllocatePool(NonPagedPool,
1235 if (Srb->SenseInfoBuffer == NULL)
1236 return(STATUS_INSUFFICIENT_RESOURCES);
1238 if (BufferAddress == NULL)
1241 RequestType = IOCTL_SCSI_EXECUTE_NONE;
1242 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1246 if (WriteToDevice == TRUE)
1248 RequestType = IOCTL_SCSI_EXECUTE_OUT;
1249 Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1253 RequestType = IOCTL_SCSI_EXECUTE_IN;
1254 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
1258 Srb->DataTransferLength = BufferLength;
1259 Srb->DataBuffer = BufferAddress;
1261 Event = ExAllocatePool(NonPagedPool,
1264 KeInitializeEvent(Event,
1268 Irp = IoBuildDeviceIoControlRequest(RequestType,
1269 DeviceExtension->PortDeviceObject,
1279 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1280 ExFreePool(Srb->SenseInfoBuffer);
1282 return(STATUS_INSUFFICIENT_RESOURCES);
1285 /* Attach Srb to the Irp */
1286 IrpStack = IoGetNextIrpStackLocation(Irp);
1287 IrpStack->Parameters.Scsi.Srb = Srb;
1288 Srb->OriginalRequest = Irp;
1290 /* Call the SCSI port driver */
1291 Status = IoCallDriver(DeviceExtension->PortDeviceObject,
1293 if (Status == STATUS_PENDING)
1295 KeWaitForSingleObject(Event,
1302 if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS)
1304 Retry = ScsiClassInterpretSenseInfo(DeviceObject,
1308 MAXIMUM_RETRIES - RetryCount,
1312 DPRINT("Try again (RetryCount %lu)\n", RetryCount);
1314 /* FIXME: Wait a little if we got a timeout error */
1322 Status = STATUS_SUCCESS;
1325 ExFreePool(Srb->SenseInfoBuffer);
1328 DPRINT("ScsiClassSendSrbSynchronous() done\n");
1335 ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
1339 PDEVICE_EXTENSION DeviceExtension;
1340 PIO_STACK_LOCATION CurrentStack;
1341 PIO_STACK_LOCATION NextStack;
1342 PIO_STACK_LOCATION NewStack;
1343 PSCSI_REQUEST_BLOCK Srb;
1344 LARGE_INTEGER Offset;
1347 ULONG TransferLength;
1352 DPRINT("ScsiClassSplitRequest(DeviceObject %lx Irp %lx MaximumBytes %lu)\n",
1353 DeviceObject, Irp, MaximumBytes);
1355 DeviceExtension = DeviceObject->DeviceExtension;
1356 CurrentStack = IoGetCurrentIrpStackLocation(Irp);
1357 NextStack = IoGetNextIrpStackLocation(Irp);
1358 DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1360 /* Initialize transfer data for first request */
1361 Offset = CurrentStack->Parameters.Read.ByteOffset;
1362 TransferLength = CurrentStack->Parameters.Read.Length;
1363 DataLength = MaximumBytes;
1364 RequestCount = ROUND_UP(TransferLength, MaximumBytes) / MaximumBytes;
1366 /* Save request count in the original IRP */
1367 NextStack->Parameters.Others.Argument1 = (PVOID)RequestCount;
1369 DPRINT("RequestCount %lu\n", RequestCount);
1371 for (i = 0; i < RequestCount; i++)
1373 /* Create a new IRP */
1374 NewIrp = IoAllocateIrp(DeviceObject->StackSize,
1378 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1379 Irp->IoStatus.Information = 0;
1382 IoCompleteRequest(Irp,
1387 /* Initialize the new IRP */
1388 NewIrp->MdlAddress = Irp->MdlAddress;
1390 IoSetNextIrpStackLocation(NewIrp);
1391 NewStack = IoGetCurrentIrpStackLocation(NewIrp);
1393 NewStack->MajorFunction = CurrentStack->MajorFunction;
1394 NewStack->Parameters.Read.ByteOffset = Offset;
1395 NewStack->Parameters.Read.Length = DataLength;
1396 NewStack->DeviceObject = DeviceObject;
1398 ScsiClassBuildRequest(DeviceObject,
1401 NewStack = IoGetNextIrpStackLocation(NewIrp);
1402 Srb = NewStack->Parameters.Others.Argument1;
1403 Srb->DataBuffer = DataBuffer;
1405 NewIrp->AssociatedIrp.MasterIrp = Irp;
1407 /* Initialize completion routine */
1408 IoSetCompletionRoutine(NewIrp,
1409 ScsiClassIoCompleteAssociated,
1415 /* Send the new IRP down to the port driver */
1416 IoCallDriver(DeviceExtension->PortDeviceObject,
1419 /* Adjust transfer data for next request */
1420 DataBuffer = (PCHAR)DataBuffer + MaximumBytes;
1421 TransferLength -= MaximumBytes;
1422 DataLength = (TransferLength > MaximumBytes) ? MaximumBytes : TransferLength;
1423 Offset.QuadPart = Offset.QuadPart + MaximumBytes;
1428 /* INTERNAL FUNCTIONS *******************************************************/
1430 static NTSTATUS STDCALL
1431 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
1434 PDEVICE_EXTENSION DeviceExtension;
1436 DPRINT("ScsiClassCreateClose() called\n");
1438 DeviceExtension = DeviceObject->DeviceExtension;
1440 if (DeviceExtension->ClassCreateClose)
1441 return(DeviceExtension->ClassCreateClose(DeviceObject,
1444 Irp->IoStatus.Status = STATUS_SUCCESS;
1445 Irp->IoStatus.Information = 0;
1446 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1448 return(STATUS_SUCCESS);
1452 static NTSTATUS STDCALL
1453 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
1456 PDEVICE_EXTENSION DeviceExtension;
1457 PIO_STACK_LOCATION IrpStack;
1458 ULONG MaximumTransferLength;
1459 ULONG CurrentTransferLength;
1460 ULONG MaximumTransferPages;
1461 ULONG CurrentTransferPages;
1464 DPRINT("ScsiClassReadWrite() called\n");
1466 DeviceExtension = DeviceObject->DeviceExtension;
1467 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1469 DPRINT("Relative Offset: %I64u Length: %lu\n",
1470 IrpStack->Parameters.Read.ByteOffset.QuadPart,
1471 IrpStack->Parameters.Read.Length);
1473 MaximumTransferLength = DeviceExtension->PortCapabilities->MaximumTransferLength;
1474 MaximumTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages;
1476 CurrentTransferLength = IrpStack->Parameters.Read.Length;
1478 if ((DeviceObject->Flags & DO_VERIFY_VOLUME) &&
1479 !(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
1481 IoSetHardErrorOrVerifyDevice(Irp,
1484 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
1485 Irp->IoStatus.Information = 0;
1487 IoCompleteRequest(Irp,
1489 return(STATUS_VERIFY_REQUIRED);
1492 /* Class driver verifies the IRP */
1493 Status = DeviceExtension->ClassReadWriteVerification(DeviceObject,
1495 if (!NT_SUCCESS(Status))
1497 IoCompleteRequest(Irp,
1501 else if (Status == STATUS_PENDING)
1503 IoMarkIrpPending(Irp);
1504 return(STATUS_PENDING);
1507 /* Finish a zero-byte transfer */
1508 if (CurrentTransferLength == 0)
1510 Irp->IoStatus.Status = STATUS_SUCCESS;
1511 Irp->IoStatus.Information = 0;
1512 IoCompleteRequest(Irp,
1514 return(STATUS_SUCCESS);
1517 if (DeviceExtension->ClassStartIo != NULL)
1519 DPRINT("ScsiClassReadWrite() starting packet\n");
1521 IoMarkIrpPending(Irp);
1522 IoStartPacket(DeviceObject,
1527 return(STATUS_PENDING);
1530 /* Adjust partition-relative starting offset to absolute offset */
1531 IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart;
1533 /* Calculate number of pages in this transfer */
1534 CurrentTransferPages =
1535 ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
1536 IrpStack->Parameters.Read.Length);
1538 if (CurrentTransferLength > MaximumTransferLength ||
1539 CurrentTransferPages > MaximumTransferPages)
1541 DPRINT("Split current request: MaximumTransferLength %lu CurrentTransferLength %lu\n",
1542 MaximumTransferLength, CurrentTransferLength);
1544 /* Adjust the maximum transfer length */
1545 CurrentTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages;
1547 if (MaximumTransferLength > CurrentTransferPages * PAGE_SIZE)
1548 MaximumTransferLength = CurrentTransferPages * PAGE_SIZE;
1550 if (MaximumTransferLength == 0)
1551 MaximumTransferLength = PAGE_SIZE;
1553 IoMarkIrpPending(Irp);
1555 /* Split current request */
1556 ScsiClassSplitRequest(DeviceObject,
1558 MaximumTransferLength);
1560 return(STATUS_PENDING);
1563 ScsiClassBuildRequest(DeviceObject,
1566 DPRINT("ScsiClassReadWrite() done\n");
1568 /* Call the port driver */
1569 return(IoCallDriver(DeviceExtension->PortDeviceObject,
1574 static NTSTATUS STDCALL
1575 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
1578 DPRINT1("ScsiClassScsiDispatch() called\n");
1580 Irp->IoStatus.Status = STATUS_SUCCESS;
1581 Irp->IoStatus.Information = 0;
1582 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1584 return(STATUS_SUCCESS);
1588 static NTSTATUS STDCALL
1589 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
1592 PDEVICE_EXTENSION DeviceExtension;
1594 DPRINT("ScsiClassDeviceDispatch() called\n");
1596 DeviceExtension = DeviceObject->DeviceExtension;
1597 if (DeviceExtension->ClassDeviceControl)
1599 return(DeviceExtension->ClassDeviceControl(DeviceObject, Irp));
1602 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1603 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1605 return(STATUS_INVALID_DEVICE_REQUEST);
1609 static NTSTATUS STDCALL
1610 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
1613 PDEVICE_EXTENSION DeviceExtension;
1615 DPRINT("ScsiClassShutdownFlush() called\n");
1617 DeviceExtension = DeviceObject->DeviceExtension;
1618 if (DeviceExtension->ClassShutdownFlush)
1620 return(DeviceExtension->ClassShutdownFlush(DeviceObject, Irp));
1623 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1624 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1626 return(STATUS_INVALID_DEVICE_REQUEST);
1631 ScsiClassRetryRequest(
1632 PDEVICE_OBJECT DeviceObject,
1634 PSCSI_REQUEST_BLOCK Srb,
1638 PDEVICE_EXTENSION DeviceExtension;
1639 PIO_STACK_LOCATION CurrentIrpStack;
1640 PIO_STACK_LOCATION NextIrpStack;
1642 ULONG TransferLength;
1644 DPRINT("ScsiPortRetryRequest() called\n");
1646 DeviceExtension = DeviceObject->DeviceExtension;
1647 CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
1648 NextIrpStack = IoGetNextIrpStackLocation(Irp);
1650 if (CurrentIrpStack->MajorFunction != IRP_MJ_READ &&
1651 CurrentIrpStack->MajorFunction != IRP_MJ_WRITE)
1653 /* We shouldn't setup the buffer pointer and transfer length on read/write requests. */
1654 if (Irp->MdlAddress != NULL)
1656 TransferLength = Irp->MdlAddress->ByteCount;
1663 Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1664 Srb->DataTransferLength = TransferLength;
1668 Srb->ScsiStatus = 0;
1670 /* Don't modify the flags */
1672 // Srb->QueueTag = SP_UNTAGGED;
1674 NextIrpStack->MajorFunction = IRP_MJ_SCSI;
1675 NextIrpStack->Parameters.Scsi.Srb = Srb;
1677 if (Associated == FALSE)
1679 IoSetCompletionRoutine(Irp,
1680 ScsiClassIoComplete,
1688 IoSetCompletionRoutine(Irp,
1689 ScsiClassIoCompleteAssociated,
1697 IoCallDriver(DeviceExtension->PortDeviceObject,
1700 DPRINT("ScsiPortRetryRequest() done\n");