3 * Copyright (C) 2001, 2002, 2003 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.34 2003/05/01 17:49:23 ekohl 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>
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(DeviceObject
,
931 return(STATUS_MORE_PROCESSING_REQUIRED
);
936 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
939 Irp
->IoStatus
.Status
= Status
;
940 if (!NT_SUCCESS(Status
))
942 Irp
->IoStatus
.Information
= 0;
943 if (IoIsErrorUserInduced(Status
))
945 IoSetHardErrorOrVerifyDevice(Irp
,
950 if (DeviceExtension
->ClassStartIo
!= NULL
)
952 if (IrpStack
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
)
954 IoStartNextPacket(DeviceObject
,
959 DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status
);
966 ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject
,
970 PDEVICE_EXTENSION DeviceExtension
;
971 PIO_STACK_LOCATION IrpStack
;
972 PSCSI_REQUEST_BLOCK Srb
;
978 DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n",
979 DeviceObject
, Irp
, Context
);
981 MasterIrp
= Irp
->AssociatedIrp
.MasterIrp
;
982 DeviceExtension
= DeviceObject
->DeviceExtension
;
984 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
986 //BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
987 //Must pass Srb as Context arg!! See comment about Completion routines in
988 //IofCallDriver for more info.
990 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
992 DPRINT("Srb %p\n", Srb
);
994 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
996 Status
= STATUS_SUCCESS
;
1000 /* Get more detailed status information */
1001 Retry
= ScsiClassInterpretSenseInfo(DeviceObject
,
1003 IrpStack
->MajorFunction
,
1005 MAXIMUM_RETRIES
- ((ULONG
)IrpStack
->Parameters
.Others
.Argument4
),
1009 ((ULONG
)IrpStack
->Parameters
.Others
.Argument4
> 0))
1011 ((ULONG
)IrpStack
->Parameters
.Others
.Argument4
)--;
1013 ScsiClassRetryRequest(
1019 return(STATUS_MORE_PROCESSING_REQUIRED
);
1024 ExFreeToNPagedLookasideList(&DeviceExtension
->SrbLookasideListHead
,
1027 Irp
->IoStatus
.Status
= Status
;
1029 IrpStack
= IoGetNextIrpStackLocation(MasterIrp
);
1030 if (!NT_SUCCESS(Status
))
1032 MasterIrp
->IoStatus
.Status
= Status
;
1033 MasterIrp
->IoStatus
.Information
= 0;
1035 if (IoIsErrorUserInduced(Status
))
1037 IoSetHardErrorOrVerifyDevice(MasterIrp
,
1042 /* Decrement the request counter in the Master IRP */
1043 RequestCount
= InterlockedDecrement((PLONG
)&IrpStack
->Parameters
.Others
.Argument1
);
1045 if (RequestCount
== 0)
1047 /* Complete the Master IRP */
1048 IoCompleteRequest(MasterIrp
,
1051 if (DeviceExtension
->ClassStartIo
)
1053 IoStartNextPacket(DeviceObject
,
1058 /* Free the current IRP */
1061 return(STATUS_MORE_PROCESSING_REQUIRED
);
1066 ScsiClassModeSense(PDEVICE_OBJECT DeviceObject
,
1067 CHAR ModeSenseBuffer
,
1076 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath
)
1078 PRTL_QUERY_REGISTRY_TABLE Table
;
1085 if (RegistryPath
== NULL
)
1093 /* Allocate zero-terminated path string */
1094 Size
= RegistryPath
->Length
+ sizeof(WCHAR
);
1095 Path
= (PWSTR
)ExAllocatePool (NonPagedPool
,
1101 RtlZeroMemory (Path
,
1103 RtlCopyMemory (Path
,
1104 RegistryPath
->Buffer
,
1105 Size
- sizeof(WCHAR
));
1107 /* Allocate query table */
1108 Size
= sizeof(RTL_QUERY_REGISTRY_TABLE
) * 2;
1109 Table
= (PRTL_QUERY_REGISTRY_TABLE
)ExAllocatePool (NonPagedPool
,
1116 RtlZeroMemory (Table
,
1119 Table
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1120 Table
[0].Name
= L
"TimeOutValue";
1121 Table
[0].EntryContext
= &TimeOutValue
;
1122 Table
[0].DefaultType
= REG_DWORD
;
1123 Table
[0].DefaultData
= &ZeroTimeOut
;
1124 Table
[0].DefaultLength
= sizeof(ULONG
);
1126 Status
= RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
,
1131 if (!NT_SUCCESS(Status
))
1133 DPRINT("RtlQueryRegistryValue() failed (Status %lx)\n", Status
);
1140 DPRINT("TimeOut: %lu\n", TimeOutValue
);
1142 return TimeOutValue
;
1147 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject
)
1149 PDEVICE_EXTENSION DeviceExtension
;
1150 PREAD_CAPACITY_DATA CapacityBuffer
;
1151 SCSI_REQUEST_BLOCK Srb
;
1157 DPRINT("ScsiClassReadDriveCapacity() called\n");
1159 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1161 CapacityBuffer
= ExAllocatePool(NonPagedPool
,
1162 sizeof(READ_CAPACITY_DATA
));
1163 if (CapacityBuffer
== NULL
)
1165 return(STATUS_INSUFFICIENT_RESOURCES
);
1168 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
1171 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
1173 Cdb
= (PCDB
)Srb
.Cdb
;
1174 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
1177 Status
= ScsiClassSendSrbSynchronous(DeviceObject
,
1180 sizeof(READ_CAPACITY_DATA
),
1182 DPRINT("Status: %lx\n", Status
);
1183 DPRINT("Srb: %p\n", &Srb
);
1184 if (NT_SUCCESS(Status
))
1186 SectorSize
= (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[0] << 24) |
1187 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[1] << 16) |
1188 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[2] << 8) |
1189 ((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[3];
1192 LastSector
= (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[0] << 24) |
1193 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[1] << 16) |
1194 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[2] << 8) |
1195 ((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[3];
1197 DeviceExtension
->DiskGeometry
->BytesPerSector
= SectorSize
;
1199 DeviceExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(LastSector
+ 1);
1200 WHICH_BIT(DeviceExtension
->DiskGeometry
->BytesPerSector
,
1201 DeviceExtension
->SectorShift
);
1202 DeviceExtension
->PartitionLength
.QuadPart
=
1203 (DeviceExtension
->PartitionLength
.QuadPart
<< DeviceExtension
->SectorShift
);
1205 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1207 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
1211 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
1213 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
= (LONGLONG
)((LastSector
+ 1)/(32 * 64));
1214 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= 32;
1215 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= 64;
1217 DPRINT("SectorSize: %lu SectorCount: %lu\n", SectorSize
, LastSector
+ 1);
1221 /* Use default values if disk geometry cannot be read */
1222 RtlZeroMemory(DeviceExtension
->DiskGeometry
,
1223 sizeof(DISK_GEOMETRY
));
1224 DeviceExtension
->DiskGeometry
->BytesPerSector
= 512;
1225 DeviceExtension
->SectorShift
= 9;
1226 DeviceExtension
->PartitionLength
.QuadPart
= 0;
1228 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
1230 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
1234 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
1237 DPRINT("SectorSize: 512 SectorCount: 0\n");
1240 ExFreePool(CapacityBuffer
);
1242 DPRINT("ScsiClassReadDriveCapacity() done\n");
1249 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject
)
1256 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject
,
1257 PSCSI_REQUEST_BLOCK Srb
,
1259 PVOID BufferAddress
,
1261 BOOLEAN WriteToDevice
)
1268 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject
,
1269 PSCSI_REQUEST_BLOCK Srb
,
1270 PVOID BufferAddress
,
1272 BOOLEAN WriteToDevice
)
1274 PDEVICE_EXTENSION DeviceExtension
;
1275 IO_STATUS_BLOCK IoStatusBlock
;
1276 PIO_STACK_LOCATION IrpStack
;
1284 DPRINT("ScsiClassSendSrbSynchronous() called\n");
1286 RetryCount
= MAXIMUM_RETRIES
;
1287 DeviceExtension
= DeviceObject
->DeviceExtension
;
1289 Srb
->Length
= SCSI_REQUEST_BLOCK_SIZE
;
1290 Srb
->PathId
= DeviceExtension
->PathId
;
1291 Srb
->TargetId
= DeviceExtension
->TargetId
;
1292 Srb
->Lun
= DeviceExtension
->Lun
;
1293 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
1295 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
1296 Srb
->SenseInfoBuffer
= ExAllocatePool(NonPagedPool
,
1298 if (Srb
->SenseInfoBuffer
== NULL
)
1299 return(STATUS_INSUFFICIENT_RESOURCES
);
1301 if (BufferAddress
== NULL
)
1304 RequestType
= IOCTL_SCSI_EXECUTE_NONE
;
1305 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
1309 if (WriteToDevice
== TRUE
)
1311 RequestType
= IOCTL_SCSI_EXECUTE_IN
; // needs _in_ to the device
1312 Srb
->SrbFlags
= SRB_FLAGS_DATA_OUT
; // needs _out_ from the caller
1316 RequestType
= IOCTL_SCSI_EXECUTE_OUT
;
1317 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
1321 Srb
->DataTransferLength
= BufferLength
;
1322 Srb
->DataBuffer
= BufferAddress
;
1324 Event
= ExAllocatePool(NonPagedPool
,
1327 KeInitializeEvent(Event
,
1331 Irp
= IoBuildDeviceIoControlRequest(RequestType
,
1332 DeviceExtension
->PortDeviceObject
,
1342 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1343 ExFreePool(Srb
->SenseInfoBuffer
);
1345 return(STATUS_INSUFFICIENT_RESOURCES
);
1348 /* Attach Srb to the Irp */
1349 IrpStack
= IoGetNextIrpStackLocation(Irp
);
1350 IrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1351 Srb
->OriginalRequest
= Irp
;
1353 /* Call the SCSI port driver */
1354 Status
= IoCallDriver(DeviceExtension
->PortDeviceObject
,
1356 if (Status
== STATUS_PENDING
)
1358 KeWaitForSingleObject(Event
,
1365 if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
)
1367 Retry
= ScsiClassInterpretSenseInfo(DeviceObject
,
1371 MAXIMUM_RETRIES
- RetryCount
,
1375 DPRINT("Try again (RetryCount %lu)\n", RetryCount
);
1377 /* FIXME: Wait a little if we got a timeout error */
1385 Status
= STATUS_SUCCESS
;
1388 ExFreePool(Srb
->SenseInfoBuffer
);
1391 DPRINT("ScsiClassSendSrbSynchronous() done\n");
1398 ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject
,
1402 PDEVICE_EXTENSION DeviceExtension
;
1403 PIO_STACK_LOCATION CurrentStack
;
1404 PIO_STACK_LOCATION NextStack
;
1405 PIO_STACK_LOCATION NewStack
;
1406 PSCSI_REQUEST_BLOCK Srb
;
1407 LARGE_INTEGER Offset
;
1410 ULONG TransferLength
;
1415 DPRINT("ScsiClassSplitRequest(DeviceObject %lx Irp %lx MaximumBytes %lu)\n",
1416 DeviceObject
, Irp
, MaximumBytes
);
1418 DeviceExtension
= DeviceObject
->DeviceExtension
;
1419 CurrentStack
= IoGetCurrentIrpStackLocation(Irp
);
1420 NextStack
= IoGetNextIrpStackLocation(Irp
);
1421 DataBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
1423 /* Initialize transfer data for first request */
1424 Offset
= CurrentStack
->Parameters
.Read
.ByteOffset
;
1425 TransferLength
= CurrentStack
->Parameters
.Read
.Length
;
1426 DataLength
= MaximumBytes
;
1427 RequestCount
= ROUND_UP(TransferLength
, MaximumBytes
) / MaximumBytes
;
1429 /* Save request count in the original IRP */
1430 NextStack
->Parameters
.Others
.Argument1
= (PVOID
)RequestCount
;
1432 DPRINT("RequestCount %lu\n", RequestCount
);
1434 for (i
= 0; i
< RequestCount
; i
++)
1436 /* Create a new IRP */
1437 NewIrp
= IoAllocateIrp(DeviceObject
->StackSize
,
1441 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1442 Irp
->IoStatus
.Information
= 0;
1445 IoCompleteRequest(Irp
,
1450 /* Initialize the new IRP */
1451 NewIrp
->MdlAddress
= Irp
->MdlAddress
;
1453 IoSetNextIrpStackLocation(NewIrp
);
1454 NewStack
= IoGetCurrentIrpStackLocation(NewIrp
);
1456 NewStack
->MajorFunction
= CurrentStack
->MajorFunction
;
1457 NewStack
->Parameters
.Read
.ByteOffset
= Offset
;
1458 NewStack
->Parameters
.Read
.Length
= DataLength
;
1459 NewStack
->DeviceObject
= DeviceObject
;
1461 ScsiClassBuildRequest(DeviceObject
,
1464 NewStack
= IoGetNextIrpStackLocation(NewIrp
);
1465 Srb
= NewStack
->Parameters
.Others
.Argument1
;
1466 Srb
->DataBuffer
= DataBuffer
;
1468 NewIrp
->AssociatedIrp
.MasterIrp
= Irp
;
1470 /* Initialize completion routine */
1471 IoSetCompletionRoutine(NewIrp
,
1472 ScsiClassIoCompleteAssociated
,
1478 /* Send the new IRP down to the port driver */
1479 IoCallDriver(DeviceExtension
->PortDeviceObject
,
1482 /* Adjust transfer data for next request */
1483 DataBuffer
= (PCHAR
)DataBuffer
+ MaximumBytes
;
1484 TransferLength
-= MaximumBytes
;
1485 DataLength
= (TransferLength
> MaximumBytes
) ? MaximumBytes
: TransferLength
;
1486 Offset
.QuadPart
= Offset
.QuadPart
+ MaximumBytes
;
1491 /* INTERNAL FUNCTIONS *******************************************************/
1493 static NTSTATUS STDCALL
1494 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject
,
1497 PDEVICE_EXTENSION DeviceExtension
;
1499 DPRINT("ScsiClassCreateClose() called\n");
1501 DeviceExtension
= DeviceObject
->DeviceExtension
;
1503 if (DeviceExtension
->ClassCreateClose
)
1504 return(DeviceExtension
->ClassCreateClose(DeviceObject
,
1507 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1508 Irp
->IoStatus
.Information
= 0;
1509 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1511 return(STATUS_SUCCESS
);
1515 static NTSTATUS STDCALL
1516 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1519 PDEVICE_EXTENSION DeviceExtension
;
1520 PIO_STACK_LOCATION IrpStack
;
1521 ULONG MaximumTransferLength
;
1522 ULONG CurrentTransferLength
;
1523 ULONG MaximumTransferPages
;
1524 ULONG CurrentTransferPages
;
1527 DPRINT("ScsiClassReadWrite() called\n");
1529 DeviceExtension
= DeviceObject
->DeviceExtension
;
1530 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1532 DPRINT("Relative Offset: %I64u Length: %lu\n",
1533 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
,
1534 IrpStack
->Parameters
.Read
.Length
);
1536 MaximumTransferLength
= DeviceExtension
->PortCapabilities
->MaximumTransferLength
;
1537 MaximumTransferPages
= DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
;
1539 CurrentTransferLength
= IrpStack
->Parameters
.Read
.Length
;
1541 if ((DeviceObject
->Flags
& DO_VERIFY_VOLUME
) &&
1542 !(IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
))
1544 IoSetHardErrorOrVerifyDevice(Irp
,
1547 Irp
->IoStatus
.Status
= STATUS_VERIFY_REQUIRED
;
1548 Irp
->IoStatus
.Information
= 0;
1550 IoCompleteRequest(Irp
,
1552 return(STATUS_VERIFY_REQUIRED
);
1555 /* Class driver verifies the IRP */
1556 Status
= DeviceExtension
->ClassReadWriteVerification(DeviceObject
,
1558 if (!NT_SUCCESS(Status
))
1560 IoCompleteRequest(Irp
,
1564 else if (Status
== STATUS_PENDING
)
1566 IoMarkIrpPending(Irp
);
1567 return(STATUS_PENDING
);
1570 /* Finish a zero-byte transfer */
1571 if (CurrentTransferLength
== 0)
1573 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1574 Irp
->IoStatus
.Information
= 0;
1575 IoCompleteRequest(Irp
,
1577 return(STATUS_SUCCESS
);
1580 if (DeviceExtension
->ClassStartIo
!= NULL
)
1582 DPRINT("ScsiClassReadWrite() starting packet\n");
1584 IoMarkIrpPending(Irp
);
1585 IoStartPacket(DeviceObject
,
1590 return(STATUS_PENDING
);
1593 /* Adjust partition-relative starting offset to absolute offset */
1594 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
+=
1595 (DeviceExtension
->StartingOffset
.QuadPart
+ DeviceExtension
->DMByteSkew
);
1597 /* Calculate number of pages in this transfer */
1598 CurrentTransferPages
=
1599 ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp
->MdlAddress
),
1600 IrpStack
->Parameters
.Read
.Length
);
1602 if (CurrentTransferLength
> MaximumTransferLength
||
1603 CurrentTransferPages
> MaximumTransferPages
)
1605 DPRINT("Split current request: MaximumTransferLength %lu CurrentTransferLength %lu\n",
1606 MaximumTransferLength
, CurrentTransferLength
);
1608 /* Adjust the maximum transfer length */
1609 CurrentTransferPages
= DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
;
1611 if (MaximumTransferLength
> CurrentTransferPages
* PAGE_SIZE
)
1612 MaximumTransferLength
= CurrentTransferPages
* PAGE_SIZE
;
1614 if (MaximumTransferLength
== 0)
1615 MaximumTransferLength
= PAGE_SIZE
;
1617 IoMarkIrpPending(Irp
);
1619 /* Split current request */
1620 ScsiClassSplitRequest(DeviceObject
,
1622 MaximumTransferLength
);
1624 return(STATUS_PENDING
);
1627 ScsiClassBuildRequest(DeviceObject
,
1630 DPRINT("ScsiClassReadWrite() done\n");
1632 /* Call the port driver */
1633 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
1638 static NTSTATUS STDCALL
1639 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject
,
1642 DPRINT1("ScsiClassScsiDispatch() called\n");
1644 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1645 Irp
->IoStatus
.Information
= 0;
1646 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1648 return(STATUS_SUCCESS
);
1652 static NTSTATUS STDCALL
1653 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject
,
1656 PDEVICE_EXTENSION DeviceExtension
;
1658 DPRINT("ScsiClassDeviceDispatch() called\n");
1660 DeviceExtension
= DeviceObject
->DeviceExtension
;
1661 if (DeviceExtension
->ClassDeviceControl
)
1663 return(DeviceExtension
->ClassDeviceControl(DeviceObject
, Irp
));
1666 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1667 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1669 return(STATUS_INVALID_DEVICE_REQUEST
);
1673 static NTSTATUS STDCALL
1674 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
1677 PDEVICE_EXTENSION DeviceExtension
;
1679 DPRINT("ScsiClassShutdownFlush() called\n");
1681 DeviceExtension
= DeviceObject
->DeviceExtension
;
1682 if (DeviceExtension
->ClassShutdownFlush
)
1684 return(DeviceExtension
->ClassShutdownFlush(DeviceObject
, Irp
));
1687 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1688 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1690 return(STATUS_INVALID_DEVICE_REQUEST
);
1695 ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject
,
1697 PSCSI_REQUEST_BLOCK Srb
,
1700 PDEVICE_EXTENSION DeviceExtension
;
1701 PIO_STACK_LOCATION CurrentIrpStack
;
1702 PIO_STACK_LOCATION NextIrpStack
;
1704 ULONG TransferLength
;
1706 DPRINT("ScsiPortRetryRequest() called\n");
1708 DeviceExtension
= DeviceObject
->DeviceExtension
;
1709 CurrentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1710 NextIrpStack
= IoGetNextIrpStackLocation(Irp
);
1712 if (CurrentIrpStack
->MajorFunction
!= IRP_MJ_READ
&&
1713 CurrentIrpStack
->MajorFunction
!= IRP_MJ_WRITE
)
1715 /* We shouldn't setup the buffer pointer and transfer length on read/write requests. */
1716 if (Irp
->MdlAddress
!= NULL
)
1718 TransferLength
= Irp
->MdlAddress
->ByteCount
;
1725 Srb
->DataBuffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
1726 Srb
->DataTransferLength
= TransferLength
;
1730 Srb
->ScsiStatus
= 0;
1732 /* Don't modify the flags */
1734 // Srb->QueueTag = SP_UNTAGGED;
1736 NextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
1737 NextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
1739 if (Associated
== FALSE
)
1741 IoSetCompletionRoutine(Irp
,
1742 ScsiClassIoComplete
,
1750 IoSetCompletionRoutine(Irp
,
1751 ScsiClassIoCompleteAssociated
,
1758 IoCallDriver(DeviceExtension
->PortDeviceObject
,
1761 DPRINT("ScsiPortRetryRequest() done\n");