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,
73 PSCSI_REQUEST_BLOCK Srb,
76 /* FUNCTIONS ****************************************************************/
78 /**********************************************************************
83 * This function initializes the driver.
90 * System allocated Driver Object for this driver.
92 * Name of registry driver service key.
99 DriverEntry(IN PDRIVER_OBJECT DriverObject,
100 IN PUNICODE_STRING RegistryPath)
102 DPRINT("Class Driver %s\n", VERSION);
103 return(STATUS_SUCCESS);
108 ScsiClassDebugPrint(IN ULONG DebugPrintLevel,
109 IN PCHAR DebugMessage,
116 if (DebugPrintLevel > InternalDebugLevel)
120 va_start(ap, DebugMessage);
121 vsprintf(Buffer, DebugMessage, ap);
129 ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject,
138 ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject,
141 PDEVICE_EXTENSION DeviceExtension;
142 PIO_STACK_LOCATION CurrentIrpStack;
143 PIO_STACK_LOCATION NextIrpStack;
144 LARGE_INTEGER StartingOffset;
145 LARGE_INTEGER StartingBlock;
146 PSCSI_REQUEST_BLOCK Srb;
148 ULONG LogicalBlockAddress;
149 USHORT TransferBlocks;
151 DeviceExtension = DeviceObject->DeviceExtension;
152 CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
153 NextIrpStack = IoGetNextIrpStackLocation(Irp);
154 StartingOffset = CurrentIrpStack->Parameters.Read.ByteOffset;
156 /* Calculate logical block address */
157 StartingBlock.QuadPart = StartingOffset.QuadPart >> DeviceExtension->SectorShift;
158 LogicalBlockAddress = (ULONG)StartingBlock.u.LowPart;
160 DPRINT("Logical block address: %lu\n", LogicalBlockAddress);
162 /* Allocate and initialize an SRB */
163 /* FIXME: use lookaside list instead */
164 Srb = ExAllocatePool(NonPagedPool,
165 sizeof(SCSI_REQUEST_BLOCK));
168 Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE;
169 Srb->OriginalRequest = Irp;
170 Srb->PathId = DeviceExtension->PathId;
171 Srb->TargetId = DeviceExtension->TargetId;
172 Srb->Lun = DeviceExtension->Lun;
173 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
174 Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
175 Srb->DataTransferLength = CurrentIrpStack->Parameters.Read.Length;
176 Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
177 Srb->QueueSortKey = LogicalBlockAddress;
179 Srb->SenseInfoBuffer = DeviceExtension->SenseData;
180 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
183 ((Srb->DataTransferLength + 0xFFFF) >> 16) * DeviceExtension->TimeOutValue;
185 Srb->SrbStatus = SRB_STATUS_SUCCESS;
190 Cdb = (PCDB)Srb->Cdb;
192 /* Initialize ATAPI packet (12 bytes) */
196 Cdb->CDB10.LogicalUnitNumber = DeviceExtension->Lun;
197 TransferBlocks = (USHORT)(CurrentIrpStack->Parameters.Read.Length >> DeviceExtension->SectorShift);
199 /* Copy little endian values into CDB in big endian format */
200 Cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte3;
201 Cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte2;
202 Cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte1;
203 Cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte0;
205 Cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&TransferBlocks)->Byte1;
206 Cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&TransferBlocks)->Byte0;
209 if (CurrentIrpStack->MajorFunction == IRP_MJ_READ)
211 DPRINT("ScsiClassBuildRequest: Read Command\n");
213 Srb->SrbFlags |= SRB_FLAGS_DATA_IN;
214 Cdb->CDB10.OperationCode = SCSIOP_READ;
218 DPRINT("ScsiClassBuildRequest: Write Command\n");
220 Srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
221 Cdb->CDB10.OperationCode = SCSIOP_WRITE;
225 /* if this is not a write-through request, then allow caching */
226 if (!(CurrentIrpStack->Flags & SL_WRITE_THROUGH))
228 Srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE;
230 else if (DeviceExtension->DeviceFlags & DEV_WRITE_CACHE)
232 /* if write caching is enable then force media access in the cdb */
233 Cdb->CDB10.ForceUnitAccess = TRUE;
237 /* Update srb flags */
238 Srb->SrbFlags |= DeviceExtension->SrbFlags;
240 /* Initialize next stack location */
241 NextIrpStack->MajorFunction = IRP_MJ_SCSI;
242 NextIrpStack->Parameters.Scsi.Srb = Srb;
243 NextIrpStack->DeviceObject = DeviceObject;
245 /* Set retry count */
246 NextIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
248 DPRINT("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp, Srb);
249 IoSetCompletionRoutine(Irp,
259 ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
260 PSCSI_INQUIRY_DATA LunInfo,
262 PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL)
264 PIO_STACK_LOCATION IoStack;
265 IO_STATUS_BLOCK IoStatusBlock;
266 SCSI_REQUEST_BLOCK Srb;
271 DPRINT("ScsiClassClaimDevice() called\n");
273 if (NewPortDeviceObject != NULL)
274 *NewPortDeviceObject = NULL;
276 /* initialize an SRB */
278 sizeof(SCSI_REQUEST_BLOCK));
279 Srb.Length = SCSI_REQUEST_BLOCK_SIZE;
280 Srb.PathId = LunInfo->PathId;
281 Srb.TargetId = LunInfo->TargetId;
282 Srb.Lun = LunInfo->Lun;
284 (Release == TRUE) ? SRB_FUNCTION_RELEASE_DEVICE : SRB_FUNCTION_CLAIM_DEVICE;
286 KeInitializeEvent(&Event,
290 Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE,
301 DPRINT("Failed to allocate Irp!\n");
302 return(STATUS_INSUFFICIENT_RESOURCES);
305 /* Link Srb and Irp */
306 IoStack = IoGetNextIrpStackLocation(Irp);
307 IoStack->Parameters.Scsi.Srb = &Srb;
308 Srb.OriginalRequest = Irp;
310 /* Call SCSI port driver */
311 Status = IoCallDriver(PortDeviceObject,
313 if (Status == STATUS_PENDING)
315 KeWaitForSingleObject(&Event,
320 Status = IoStatusBlock.Status;
325 ObDereferenceObject(PortDeviceObject);
326 return(STATUS_SUCCESS);
329 // Status = ObReferenceObjectByPointer(Srb.DataBuffer,
330 Status = ObReferenceObjectByPointer(PortDeviceObject,
335 if (NewPortDeviceObject != NULL)
337 // *NewPortDeviceObject = Srb.DataBuffer;
338 *NewPortDeviceObject = PortDeviceObject;
341 return(STATUS_SUCCESS);
346 ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
347 IN PCCHAR ObjectNameBuffer,
348 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
349 IN OUT PDEVICE_OBJECT *DeviceObject,
350 IN PCLASS_INIT_DATA InitializationData)
352 PDEVICE_OBJECT InternalDeviceObject;
353 PDEVICE_EXTENSION DeviceExtension;
354 ANSI_STRING AnsiName;
355 UNICODE_STRING DeviceName;
358 DPRINT("ScsiClassCreateDeviceObject() called\n");
360 *DeviceObject = NULL;
362 RtlInitAnsiString(&AnsiName,
365 Status = RtlAnsiStringToUnicodeString(&DeviceName,
368 if (!NT_SUCCESS(Status))
373 DPRINT("Device name: '%wZ'\n", &DeviceName);
375 Status = IoCreateDevice(DriverObject,
376 InitializationData->DeviceExtensionSize,
378 InitializationData->DeviceType,
379 InitializationData->DeviceCharacteristics,
381 &InternalDeviceObject);
382 if (NT_SUCCESS(Status))
384 DeviceExtension = InternalDeviceObject->DeviceExtension;
386 DeviceExtension->ClassError = InitializationData->ClassError;
387 DeviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification;
388 DeviceExtension->ClassFindDevices = InitializationData->ClassFindDevices;
389 DeviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl;
390 DeviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush;
391 DeviceExtension->ClassCreateClose = InitializationData->ClassCreateClose;
392 DeviceExtension->ClassStartIo = InitializationData->ClassStartIo;
394 DeviceExtension->MediaChangeCount = 0;
396 if (PhysicalDeviceObject != NULL)
398 DeviceExtension->PhysicalDevice = PhysicalDeviceObject;
402 DeviceExtension->PhysicalDevice = InternalDeviceObject;
405 *DeviceObject = InternalDeviceObject;
408 RtlFreeUnicodeString(&DeviceName);
415 ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
418 PDEVICE_EXTENSION DeviceExtension;
419 PIO_STACK_LOCATION Stack;
421 ULONG OutputBufferLength;
423 DPRINT1("ScsiClassDeviceControl() called\n");
425 DeviceExtension = DeviceObject->DeviceExtension;
426 Stack = IoGetCurrentIrpStackLocation(Irp);
428 IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
429 OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
431 if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
433 PSCSI_ADDRESS ScsiAddress;
435 if (OutputBufferLength < sizeof(SCSI_ADDRESS))
437 Irp->IoStatus.Information = 0;
438 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
439 IoCompleteRequest(Irp, IO_NO_INCREMENT);
441 return(STATUS_BUFFER_TOO_SMALL);
444 ScsiAddress = Irp->AssociatedIrp.SystemBuffer;
445 ScsiAddress->Length = sizeof(SCSI_ADDRESS);
446 ScsiAddress->PortNumber = DeviceExtension->PortNumber;
447 ScsiAddress->PathId = DeviceExtension->PathId;
448 ScsiAddress->TargetId = DeviceExtension->TargetId;
449 ScsiAddress->Lun = DeviceExtension->Lun;
451 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
452 Irp->IoStatus.Status = STATUS_SUCCESS;
453 IoCompleteRequest(Irp, IO_NO_INCREMENT);
455 return(STATUS_SUCCESS);
458 if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
459 IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
461 DPRINT1("Fixme: IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
464 Irp->IoStatus.Information = 0;
465 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
466 IoCompleteRequest(Irp, IO_NO_INCREMENT);
468 return(STATUS_UNSUCCESSFUL);
471 DPRINT1("Fixme: unknown device io control code\n");
473 Irp->IoStatus.Information = 0;
474 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
475 IoCompleteRequest(Irp, IO_NO_INCREMENT);
477 return(STATUS_UNSUCCESSFUL);
482 ScsiClassFindModePage(PCHAR ModeSenseBuffer,
492 ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
493 PSCSI_ADAPTER_BUS_INFO AdapterInformation)
495 PSCSI_INQUIRY_DATA UnitInfo;
496 PINQUIRYDATA InquiryData;
499 ULONG UnclaimedDevices = 0;
502 DPRINT("ScsiClassFindUnclaimedDevices() called\n");
504 DPRINT("NumberOfBuses: %lu\n",AdapterInformation->NumberOfBuses);
505 Buffer = (PUCHAR)AdapterInformation;
506 for (Bus = 0; Bus < (ULONG)AdapterInformation->NumberOfBuses; Bus++)
508 DPRINT("Searching bus %lu\n", Bus);
510 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterInformation->BusData[Bus].InquiryDataOffset);
512 while (AdapterInformation->BusData[Bus].InquiryDataOffset)
514 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
516 DPRINT("Device: '%.8s'\n", InquiryData->VendorId);
518 if ((InitializationData->ClassFindDeviceCallBack(InquiryData) == TRUE) &&
519 (UnitInfo->DeviceClaimed == FALSE))
524 if (UnitInfo->NextInquiryDataOffset == 0)
527 UnitInfo = (PSCSI_INQUIRY_DATA) (Buffer + UnitInfo->NextInquiryDataOffset);
531 return(UnclaimedDevices);
536 ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
537 PIO_SCSI_CAPABILITIES *PortCapabilities)
539 IO_STATUS_BLOCK IoStatusBlock;
544 KeInitializeEvent(&Event,
548 Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES,
559 return(STATUS_INSUFFICIENT_RESOURCES);
562 Status = IoCallDriver(PortDeviceObject,
564 if (Status == STATUS_PENDING)
566 KeWaitForSingleObject(&Event,
571 Status = IoStatusBlock.Status;
574 DPRINT("PortCapabilities at %p\n", *PortCapabilities);
581 ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
582 PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
584 PSCSI_ADAPTER_BUS_INFO Buffer;
585 IO_STATUS_BLOCK IoStatusBlock;
590 DPRINT("ScsiClassGetInquiryData() called\n");
593 Buffer = ExAllocatePool(NonPagedPool,
597 return(STATUS_INSUFFICIENT_RESOURCES);
600 KeInitializeEvent(&Event,
604 Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA,
616 return(STATUS_INSUFFICIENT_RESOURCES);
619 Status = IoCallDriver(PortDeviceObject,
621 if (Status == STATUS_PENDING)
623 KeWaitForSingleObject(&Event,
628 Status = IoStatusBlock.Status;
631 if (!NT_SUCCESS(Status))
637 *ConfigInfo = Buffer;
640 DPRINT("ScsiClassGetInquiryData() done\n");
647 ScsiClassInitialize(PVOID Argument1,
649 PCLASS_INIT_DATA InitializationData)
651 PCONFIGURATION_INFORMATION ConfigInfo;
652 PDRIVER_OBJECT DriverObject = Argument1;
653 WCHAR NameBuffer[80];
654 UNICODE_STRING PortName;
656 PDEVICE_OBJECT PortDeviceObject;
657 PFILE_OBJECT FileObject;
658 BOOLEAN DiskFound = FALSE;
661 DPRINT("ScsiClassInitialize() called!\n");
663 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
664 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
665 DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
666 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
667 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassScsiDispatch;
668 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch;
669 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
670 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
671 if (InitializationData->ClassStartIo)
673 DriverObject->DriverStartIo = InitializationData->ClassStartIo;
676 ConfigInfo = IoGetConfigurationInformation();
678 DPRINT("ScsiPorts: %lu\n", ConfigInfo->ScsiPortCount);
680 /* look for ScsiPortX scsi port devices */
681 for (PortNumber = 0; PortNumber < ConfigInfo->ScsiPortCount; PortNumber++)
684 L"\\Device\\ScsiPort%lu",
686 RtlInitUnicodeString(&PortName,
688 DPRINT("Checking scsi port %ld\n", PortNumber);
689 Status = IoGetDeviceObjectPointer(&PortName,
690 FILE_READ_ATTRIBUTES,
693 DPRINT("Status 0x%08lX\n", Status);
694 if (NT_SUCCESS(Status))
696 DPRINT("ScsiPort%lu found.\n", PortNumber);
698 /* check scsi port for attached disk drives */
699 if (InitializationData->ClassFindDevices(DriverObject,
710 DbgPrint("Couldn't find ScsiPort%lu (Status %lx)\n", PortNumber, Status);
714 DPRINT("ScsiClassInitialize() done!\n");
716 return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE);
720 /**********************************************************************
722 * ScsiClassInitializeSrbLookasideList
725 * Initializes a lookaside list for SRBs.
732 * Class specific device extension.
735 * Maximum number of elements of the lookaside list.
742 ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension,
743 ULONG NumberElements)
745 ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
749 sizeof(SCSI_REQUEST_BLOCK),
751 (USHORT)NumberElements);
756 ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject,
764 ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
765 PSCSI_REQUEST_BLOCK Srb,
766 UCHAR MajorFunctionCode,
771 PDEVICE_EXTENSION DeviceExtension;
772 PSENSE_DATA SenseData;
775 DPRINT("ScsiClassInterpretSenseInfo() called\n");
777 DPRINT("Srb->SrbStatus %lx\n", Srb->SrbStatus);
779 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING)
781 *Status = STATUS_SUCCESS;
785 DeviceExtension = DeviceObject->DeviceExtension;
786 SenseData = Srb->SenseInfoBuffer;
789 if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
790 (Srb->SenseInfoBufferLength > 0))
792 /* Got valid sense data, interpret them */
794 DPRINT("ErrorCode: %x\n", SenseData->ErrorCode);
795 DPRINT("SenseKey: %x\n", SenseData->SenseKey);
796 DPRINT("SenseCode: %x\n", SenseData->AdditionalSenseCode);
798 switch (SenseData->SenseKey & 0xf)
800 /* FIXME: add more sense key codes */
802 case SCSI_SENSE_NOT_READY:
803 DPRINT("SCSI_SENSE_NOT_READY\n");
804 *Status = STATUS_DEVICE_NOT_READY;
807 case SCSI_SENSE_UNIT_ATTENTION:
808 DPRINT("SCSI_SENSE_UNIT_ATTENTION\n");
809 if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
810 (DeviceObject->Vpb->Flags & VPB_MOUNTED))
812 DeviceObject->Flags |= DO_VERIFY_VOLUME;
813 *Status = STATUS_VERIFY_REQUIRED;
818 *Status = STATUS_IO_DEVICE_ERROR;
822 case SCSI_SENSE_ILLEGAL_REQUEST:
823 DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
824 *Status = STATUS_INVALID_DEVICE_REQUEST;
830 DPRINT1("SCSI error (sense key: %x)\n",
831 SenseData->SenseKey & 0xf);
832 *Status = STATUS_IO_DEVICE_ERROR;
838 /* Got no or invalid sense data, return generic error codes */
839 switch (SRB_STATUS(Srb->SrbStatus))
841 /* FIXME: add more srb status codes */
843 case SRB_STATUS_INVALID_PATH_ID:
844 case SRB_STATUS_INVALID_TARGET_ID:
845 case SRB_STATUS_INVALID_LUN:
846 case SRB_STATUS_NO_DEVICE:
847 case SRB_STATUS_NO_HBA:
848 *Status = STATUS_NO_SUCH_DEVICE;
852 case SRB_STATUS_BUSY:
853 *Status = STATUS_DEVICE_BUSY;
857 case SRB_STATUS_DATA_OVERRUN:
858 *Status = STATUS_DATA_OVERRUN;
863 DPRINT1("SCSI error (SRB status: %x)\n",
864 SRB_STATUS(Srb->SrbStatus));
865 *Status = STATUS_IO_DEVICE_ERROR;
870 /* Call the class driver specific error function */
871 if (DeviceExtension->ClassError != NULL)
873 DeviceExtension->ClassError(DeviceObject,
879 /* FIXME: log severe errors */
881 DPRINT("ScsiClassInterpretSenseInfo() done\n");
888 ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
892 PDEVICE_EXTENSION DeviceExtension;
893 PIO_STACK_LOCATION IrpStack;
894 PSCSI_REQUEST_BLOCK Srb;
898 DPRINT("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n",
899 DeviceObject, Irp, Context);
901 DeviceExtension = DeviceObject->DeviceExtension;
902 Srb = (PSCSI_REQUEST_BLOCK)Context;
903 DPRINT("Srb %p\n", Srb);
905 IrpStack = IoGetCurrentIrpStackLocation(Irp);
907 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
909 Status = STATUS_SUCCESS;
913 Retry = ScsiClassInterpretSenseInfo(DeviceObject,
915 IrpStack->MajorFunction,
917 MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
919 if ((Retry == TRUE) &&
920 ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
922 ((ULONG)IrpStack->Parameters.Others.Argument4)--;
924 ScsiClassRetryRequest(DeviceObject,
928 return(STATUS_MORE_PROCESSING_REQUIRED);
932 /* FIXME: use lookaside list instead */
933 DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
934 ExFreePool(IrpStack->Parameters.Scsi.Srb);
936 Irp->IoStatus.Status = Status;
937 if (!NT_SUCCESS(Status))
939 Irp->IoStatus.Information = 0;
940 if (IoIsErrorUserInduced(Status))
942 IoSetHardErrorOrVerifyDevice(Irp,
947 if (DeviceExtension->ClassStartIo != NULL)
949 if (IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL)
951 IoStartNextPacket(DeviceObject,
956 DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status);
963 ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
967 PDEVICE_EXTENSION DeviceExtension;
968 PIO_STACK_LOCATION IrpStack;
969 PSCSI_REQUEST_BLOCK Srb;
975 DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n",
976 DeviceObject, Irp, Context);
978 MasterIrp = Irp->AssociatedIrp.MasterIrp;
979 DeviceExtension = DeviceObject->DeviceExtension;
980 Srb = (PSCSI_REQUEST_BLOCK)Context;
981 DPRINT("Srb %p\n", Srb);
983 IrpStack = IoGetCurrentIrpStackLocation(Irp);
985 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
987 Status = STATUS_SUCCESS;
991 /* Get more detailed status information */
992 Retry = ScsiClassInterpretSenseInfo(DeviceObject,
994 IrpStack->MajorFunction,
996 MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
999 DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
1001 if ((Retry == TRUE) &&
1002 ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
1004 ((ULONG)IrpStack->Parameters.Others.Argument4)--;
1006 ScsiClassRetryRequest(DeviceObject,
1010 return(STATUS_MORE_PROCESSING_REQUIRED);
1014 /* FIXME: use lookaside list instead */
1015 DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb);
1016 ExFreePool(IrpStack->Parameters.Scsi.Srb);
1018 Irp->IoStatus.Status = Status;
1020 IrpStack = IoGetNextIrpStackLocation(MasterIrp);
1021 if (!NT_SUCCESS(Status))
1023 MasterIrp->IoStatus.Status = Status;
1024 MasterIrp->IoStatus.Information = 0;
1026 if (IoIsErrorUserInduced(Status))
1028 IoSetHardErrorOrVerifyDevice(MasterIrp,
1033 /* Decrement the request counter in the Master IRP */
1034 RequestCount = InterlockedDecrement((PLONG)&IrpStack->Parameters.Others.Argument1);
1036 if (RequestCount == 0)
1038 /* Complete the Master IRP */
1039 IoCompleteRequest(MasterIrp,
1042 if (DeviceExtension->ClassStartIo)
1044 IoStartNextPacket(DeviceObject,
1049 /* Free the current IRP */
1052 return(STATUS_MORE_PROCESSING_REQUIRED);
1057 ScsiClassModeSense(PDEVICE_OBJECT DeviceObject,
1058 CHAR ModeSenseBuffer,
1067 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
1074 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
1076 PDEVICE_EXTENSION DeviceExtension;
1077 PREAD_CAPACITY_DATA CapacityBuffer;
1078 SCSI_REQUEST_BLOCK Srb;
1084 DPRINT("ScsiClassReadDriveCapacity() called\n");
1086 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1088 CapacityBuffer = ExAllocatePool(NonPagedPool,
1089 sizeof(READ_CAPACITY_DATA));
1090 if (CapacityBuffer == NULL)
1092 return(STATUS_INSUFFICIENT_RESOURCES);
1095 RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
1098 Srb.TimeOutValue = DeviceExtension->TimeOutValue;
1100 Cdb = (PCDB)Srb.Cdb;
1101 Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
1104 Status = ScsiClassSendSrbSynchronous(DeviceObject,
1107 sizeof(READ_CAPACITY_DATA),
1109 DPRINT("Status: %lx\n", Status);
1110 DPRINT("Srb: %p\n", &Srb);
1111 if (NT_SUCCESS(Status))
1113 SectorSize = (((PUCHAR)&CapacityBuffer->BytesPerBlock)[0] << 24) |
1114 (((PUCHAR)&CapacityBuffer->BytesPerBlock)[1] << 16) |
1115 (((PUCHAR)&CapacityBuffer->BytesPerBlock)[2] << 8) |
1116 ((PUCHAR)&CapacityBuffer->BytesPerBlock)[3];
1119 LastSector = (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[0] << 24) |
1120 (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[1] << 16) |
1121 (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[2] << 8) |
1122 ((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[3];
1124 DeviceExtension->DiskGeometry->BytesPerSector = SectorSize;
1126 DeviceExtension->PartitionLength.QuadPart = (LONGLONG)(LastSector + 1);
1127 WHICH_BIT(DeviceExtension->DiskGeometry->BytesPerSector,
1128 DeviceExtension->SectorShift);
1129 DeviceExtension->PartitionLength.QuadPart =
1130 (DeviceExtension->PartitionLength.QuadPart << DeviceExtension->SectorShift);
1132 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
1134 DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
1138 DeviceExtension->DiskGeometry->MediaType = FixedMedia;
1140 DeviceExtension->DiskGeometry->Cylinders.QuadPart = (LONGLONG)((LastSector + 1)/(32 * 64));
1141 DeviceExtension->DiskGeometry->SectorsPerTrack = 32;
1142 DeviceExtension->DiskGeometry->TracksPerCylinder = 64;
1144 DPRINT("SectorSize: %lu SectorCount: %lu\n", SectorSize, LastSector + 1);
1148 /* Use default values if disk geometry cannot be read */
1149 RtlZeroMemory(DeviceExtension->DiskGeometry,
1150 sizeof(DISK_GEOMETRY));
1151 DeviceExtension->DiskGeometry->BytesPerSector = 512;
1152 DeviceExtension->SectorShift = 9;
1153 DeviceExtension->PartitionLength.QuadPart = 0;
1155 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
1157 DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
1161 DeviceExtension->DiskGeometry->MediaType = FixedMedia;
1164 DPRINT("SectorSize: 512 SectorCount: 0\n");
1167 ExFreePool(CapacityBuffer);
1169 DPRINT("ScsiClassReadDriveCapacity() done\n");
1176 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
1183 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
1184 PSCSI_REQUEST_BLOCK Srb,
1186 PVOID BufferAddress,
1188 BOOLEAN WriteToDevice)
1195 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
1196 PSCSI_REQUEST_BLOCK Srb,
1197 PVOID BufferAddress,
1199 BOOLEAN WriteToDevice)
1201 PDEVICE_EXTENSION DeviceExtension;
1202 IO_STATUS_BLOCK IoStatusBlock;
1203 PIO_STACK_LOCATION IrpStack;
1211 DPRINT("ScsiClassSendSrbSynchronous() called\n");
1213 RetryCount = MAXIMUM_RETRIES;
1214 DeviceExtension = DeviceObject->DeviceExtension;
1216 Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1217 Srb->PathId = DeviceExtension->PathId;
1218 Srb->TargetId = DeviceExtension->TargetId;
1219 Srb->Lun = DeviceExtension->Lun;
1220 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1222 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1223 Srb->SenseInfoBuffer = ExAllocatePool(NonPagedPool,
1225 if (Srb->SenseInfoBuffer == NULL)
1226 return(STATUS_INSUFFICIENT_RESOURCES);
1228 if (BufferAddress == NULL)
1231 RequestType = IOCTL_SCSI_EXECUTE_NONE;
1232 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1236 if (WriteToDevice == TRUE)
1238 RequestType = IOCTL_SCSI_EXECUTE_OUT;
1239 Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1243 RequestType = IOCTL_SCSI_EXECUTE_IN;
1244 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
1248 Srb->DataTransferLength = BufferLength;
1249 Srb->DataBuffer = BufferAddress;
1251 Event = ExAllocatePool(NonPagedPool,
1254 KeInitializeEvent(Event,
1258 Irp = IoBuildDeviceIoControlRequest(RequestType,
1259 DeviceExtension->PortDeviceObject,
1269 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1270 ExFreePool(Srb->SenseInfoBuffer);
1272 return(STATUS_INSUFFICIENT_RESOURCES);
1275 /* Attach Srb to the Irp */
1276 IrpStack = IoGetNextIrpStackLocation(Irp);
1277 IrpStack->Parameters.Scsi.Srb = Srb;
1278 Srb->OriginalRequest = Irp;
1280 /* Call the SCSI port driver */
1281 Status = IoCallDriver(DeviceExtension->PortDeviceObject,
1283 if (Status == STATUS_PENDING)
1285 KeWaitForSingleObject(Event,
1292 if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS)
1294 Retry = ScsiClassInterpretSenseInfo(DeviceObject,
1298 MAXIMUM_RETRIES - RetryCount,
1302 DPRINT("Try again (RetryCount %lu)\n", RetryCount);
1304 /* FIXME: Wait a little if we got a timeout error */
1312 Status = STATUS_SUCCESS;
1315 ExFreePool(Srb->SenseInfoBuffer);
1318 DPRINT("ScsiClassSendSrbSynchronous() done\n");
1325 ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
1329 PDEVICE_EXTENSION DeviceExtension;
1330 PIO_STACK_LOCATION CurrentStack;
1331 PIO_STACK_LOCATION NextStack;
1332 PIO_STACK_LOCATION NewStack;
1333 PSCSI_REQUEST_BLOCK Srb;
1334 LARGE_INTEGER Offset;
1337 ULONG TransferLength;
1342 DPRINT("ScsiClassSplitRequest(DeviceObject %lx Irp %lx MaximumBytes %lu)\n",
1343 DeviceObject, Irp, MaximumBytes);
1345 DeviceExtension = DeviceObject->DeviceExtension;
1346 CurrentStack = IoGetCurrentIrpStackLocation(Irp);
1347 NextStack = IoGetNextIrpStackLocation(Irp);
1348 DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1350 /* Initialize transfer data for first request */
1351 Offset = CurrentStack->Parameters.Read.ByteOffset;
1352 TransferLength = CurrentStack->Parameters.Read.Length;
1353 DataLength = MaximumBytes;
1354 RequestCount = ROUND_UP(TransferLength, MaximumBytes) / MaximumBytes;
1356 /* Save request count in the original IRP */
1357 NextStack->Parameters.Others.Argument1 = (PVOID)RequestCount;
1359 DPRINT("RequestCount %lu\n", RequestCount);
1361 for (i = 0; i < RequestCount; i++)
1363 /* Create a new IRP */
1364 NewIrp = IoAllocateIrp(DeviceObject->StackSize,
1368 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1369 Irp->IoStatus.Information = 0;
1372 IoCompleteRequest(Irp,
1377 /* Initialize the new IRP */
1378 NewIrp->MdlAddress = Irp->MdlAddress;
1380 IoSetNextIrpStackLocation(NewIrp);
1381 NewStack = IoGetCurrentIrpStackLocation(NewIrp);
1383 NewStack->MajorFunction = CurrentStack->MajorFunction;
1384 NewStack->Parameters.Read.ByteOffset = Offset;
1385 NewStack->Parameters.Read.Length = DataLength;
1386 NewStack->DeviceObject = DeviceObject;
1388 ScsiClassBuildRequest(DeviceObject,
1391 NewStack = IoGetNextIrpStackLocation(NewIrp);
1392 Srb = NewStack->Parameters.Others.Argument1;
1393 Srb->DataBuffer = DataBuffer;
1395 NewIrp->AssociatedIrp.MasterIrp = Irp;
1397 /* Initialize completion routine */
1398 IoSetCompletionRoutine(NewIrp,
1399 ScsiClassIoCompleteAssociated,
1405 /* Send the new IRP down to the port driver */
1406 IoCallDriver(DeviceExtension->PortDeviceObject,
1409 /* Adjust transfer data for next request */
1410 DataBuffer = (PCHAR)DataBuffer + MaximumBytes;
1411 TransferLength -= MaximumBytes;
1412 DataLength = (TransferLength > MaximumBytes) ? MaximumBytes : TransferLength;
1413 Offset.QuadPart = Offset.QuadPart + MaximumBytes;
1418 /* INTERNAL FUNCTIONS *******************************************************/
1420 static NTSTATUS STDCALL
1421 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
1424 PDEVICE_EXTENSION DeviceExtension;
1426 DPRINT("ScsiClassCreateClose() called\n");
1428 DeviceExtension = DeviceObject->DeviceExtension;
1430 if (DeviceExtension->ClassCreateClose)
1431 return(DeviceExtension->ClassCreateClose(DeviceObject,
1434 Irp->IoStatus.Status = STATUS_SUCCESS;
1435 Irp->IoStatus.Information = 0;
1436 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1438 return(STATUS_SUCCESS);
1442 static NTSTATUS STDCALL
1443 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
1446 PDEVICE_EXTENSION DeviceExtension;
1447 PIO_STACK_LOCATION IrpStack;
1448 ULONG MaximumTransferLength;
1449 ULONG CurrentTransferLength;
1450 ULONG MaximumTransferPages;
1451 ULONG CurrentTransferPages;
1454 DPRINT("ScsiClassReadWrite() called\n");
1456 DeviceExtension = DeviceObject->DeviceExtension;
1457 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1459 DPRINT("Relative Offset: %I64u Length: %lu\n",
1460 IrpStack->Parameters.Read.ByteOffset.QuadPart,
1461 IrpStack->Parameters.Read.Length);
1463 MaximumTransferLength = DeviceExtension->PortCapabilities->MaximumTransferLength;
1464 MaximumTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages;
1466 CurrentTransferLength = IrpStack->Parameters.Read.Length;
1468 if ((DeviceObject->Flags & DO_VERIFY_VOLUME) &&
1469 !(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
1471 IoSetHardErrorOrVerifyDevice(Irp,
1474 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
1475 Irp->IoStatus.Information = 0;
1477 IoCompleteRequest(Irp,
1479 return(STATUS_VERIFY_REQUIRED);
1482 /* Class driver verifies the IRP */
1483 Status = DeviceExtension->ClassReadWriteVerification(DeviceObject,
1485 if (!NT_SUCCESS(Status))
1487 IoCompleteRequest(Irp,
1491 else if (Status == STATUS_PENDING)
1493 IoMarkIrpPending(Irp);
1494 return(STATUS_PENDING);
1497 /* Finish a zero-byte transfer */
1498 if (CurrentTransferLength == 0)
1500 Irp->IoStatus.Status = STATUS_SUCCESS;
1501 Irp->IoStatus.Information = 0;
1502 IoCompleteRequest(Irp,
1504 return(STATUS_SUCCESS);
1507 if (DeviceExtension->ClassStartIo != NULL)
1509 DPRINT("ScsiClassReadWrite() starting packet\n");
1511 IoMarkIrpPending(Irp);
1512 IoStartPacket(DeviceObject,
1517 return(STATUS_PENDING);
1520 /* Adjust partition-relative starting offset to absolute offset */
1521 IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart;
1523 /* Calculate number of pages in this transfer */
1524 CurrentTransferPages =
1525 ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
1526 IrpStack->Parameters.Read.Length);
1528 if (CurrentTransferLength > MaximumTransferLength ||
1529 CurrentTransferPages > MaximumTransferPages)
1531 DPRINT("Split current request: MaximumTransferLength %lu CurrentTransferLength %lu\n",
1532 MaximumTransferLength, CurrentTransferLength);
1534 /* Adjust the maximum transfer length */
1535 CurrentTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages;
1537 if (MaximumTransferLength > CurrentTransferPages * PAGE_SIZE)
1538 MaximumTransferLength = CurrentTransferPages * PAGE_SIZE;
1540 if (MaximumTransferLength == 0)
1541 MaximumTransferLength = PAGE_SIZE;
1543 IoMarkIrpPending(Irp);
1545 /* Split current request */
1546 ScsiClassSplitRequest(DeviceObject,
1548 MaximumTransferLength);
1550 return(STATUS_PENDING);
1553 ScsiClassBuildRequest(DeviceObject,
1556 DPRINT("ScsiClassReadWrite() done\n");
1558 /* Call the port driver */
1559 return(IoCallDriver(DeviceExtension->PortDeviceObject,
1564 static NTSTATUS STDCALL
1565 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject,
1568 DPRINT1("ScsiClassScsiDispatch() called\n");
1570 Irp->IoStatus.Status = STATUS_SUCCESS;
1571 Irp->IoStatus.Information = 0;
1572 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1574 return(STATUS_SUCCESS);
1578 static NTSTATUS STDCALL
1579 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,
1582 PDEVICE_EXTENSION DeviceExtension;
1584 DPRINT("ScsiClassDeviceDispatch() called\n");
1586 DeviceExtension = DeviceObject->DeviceExtension;
1587 if (DeviceExtension->ClassDeviceControl)
1589 return(DeviceExtension->ClassDeviceControl(DeviceObject, Irp));
1592 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1593 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1595 return(STATUS_INVALID_DEVICE_REQUEST);
1599 static NTSTATUS STDCALL
1600 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
1603 PDEVICE_EXTENSION DeviceExtension;
1605 DPRINT("ScsiClassShutdownFlush() called\n");
1607 DeviceExtension = DeviceObject->DeviceExtension;
1608 if (DeviceExtension->ClassShutdownFlush)
1610 return(DeviceExtension->ClassShutdownFlush(DeviceObject, Irp));
1613 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1614 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1616 return(STATUS_INVALID_DEVICE_REQUEST);
1621 ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
1623 PSCSI_REQUEST_BLOCK Srb,
1626 PDEVICE_EXTENSION DeviceExtension;
1627 PIO_STACK_LOCATION CurrentIrpStack;
1628 PIO_STACK_LOCATION NextIrpStack;
1629 ULONG TransferLength;
1631 DPRINT("ScsiPortRetryRequest() called\n");
1633 DeviceExtension = DeviceObject->DeviceExtension;
1634 CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
1635 NextIrpStack = IoGetNextIrpStackLocation(Irp);
1637 if (CurrentIrpStack->MajorFunction == IRP_MJ_READ ||
1638 CurrentIrpStack->MajorFunction == IRP_MJ_WRITE)
1640 TransferLength = CurrentIrpStack->Parameters.Read.Length;
1642 else if (Irp->MdlAddress != NULL)
1644 TransferLength = Irp->MdlAddress->ByteCount;
1651 Srb->DataTransferLength = TransferLength;
1653 Srb->ScsiStatus = 0;
1655 /* Don't modify the flags */
1657 // Srb->QueueTag = SP_UNTAGGED;
1659 NextIrpStack->MajorFunction = IRP_MJ_SCSI;
1660 NextIrpStack->Parameters.Scsi.Srb = Srb;
1662 if (Associated == FALSE)
1664 IoSetCompletionRoutine(Irp,
1665 ScsiClassIoComplete,
1673 IoSetCompletionRoutine(Irp,
1674 ScsiClassIoCompleteAssociated,
1681 IoCallDriver(DeviceExtension->PortDeviceObject,
1684 DPRINT("ScsiPortRetryRequest() done\n");