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.
19 /* $Id: class2.c,v 1.24 2002/09/08 10:22:22 chorns Exp $
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>
36 #include "../include/scsi.h"
37 #include "../include/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
* PAGESIZE
)
1538 MaximumTransferLength
= CurrentTransferPages
* PAGESIZE
;
1540 if (MaximumTransferLength
== 0)
1541 MaximumTransferLength
= PAGESIZE
;
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");