1 /* $Id: class2.c,v 1.8 2002/03/03 23:45:30 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/storage/class2/class2.c
6 * PURPOSE: SCSI class driver
7 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
15 /* INCLUDES *****************************************************************/
17 #include <ddk/ntddk.h>
18 #include "../include/scsi.h"
19 #include "../include/class2.h"
25 #define VERSION "0.0.1"
27 #define INQUIRY_DATA_SIZE 2048
30 static NTSTATUS STDCALL
31 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject
,
34 static NTSTATUS STDCALL
35 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject
,
38 static NTSTATUS STDCALL
39 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject
,
42 static NTSTATUS STDCALL
43 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject
,
46 static NTSTATUS STDCALL
47 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
51 /* FUNCTIONS ****************************************************************/
56 // This function initializes the driver.
62 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
64 // IN PUNICODE_STRING RegistryPath Name of registry driver service
71 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
72 IN PUNICODE_STRING RegistryPath
)
74 DbgPrint("Class Driver %s\n", VERSION
);
75 return(STATUS_SUCCESS
);
80 ScsiClassDebugPrint(IN ULONG DebugPrintLevel
,
81 IN PCHAR DebugMessage
,
88 if (DebugPrintLevel
> InternalDebugLevel
)
92 va_start(ap
, DebugMessage
);
93 vsprintf(Buffer
, DebugMessage
, ap
);
101 ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject
,
110 ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject
,
113 PDEVICE_EXTENSION DeviceExtension
;
114 PIO_STACK_LOCATION CurrentIrpStack
;
115 PIO_STACK_LOCATION NextIrpStack
;
116 LARGE_INTEGER StartingOffset
;
117 LARGE_INTEGER StartingBlock
;
118 PSCSI_REQUEST_BLOCK Srb
;
120 ULONG LogicalBlockAddress
;
121 USHORT TransferBlocks
;
123 DeviceExtension
= DeviceObject
->DeviceExtension
;
124 CurrentIrpStack
= IoGetCurrentIrpStackLocation(Irp
);
125 NextIrpStack
= IoGetNextIrpStackLocation(Irp
);
126 StartingOffset
= CurrentIrpStack
->Parameters
.Read
.ByteOffset
;
128 /* calculate logical block address */
129 StartingBlock
.QuadPart
= StartingOffset
.QuadPart
/ 512; // >> deviceExtension->SectorShift;
130 LogicalBlockAddress
= (ULONG
)StartingBlock
.u
.LowPart
;
132 DPRINT1("Logical block address: %lu\n", LogicalBlockAddress
);
134 /* allocate and initialize an SRB */
135 /* FIXME: use lookaside list instead */
136 Srb
= ExAllocatePool(NonPagedPool
,
137 sizeof(SCSI_REQUEST_BLOCK
));
140 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
); //SCSI_REQUEST_BLOCK_SIZE;
141 Srb
->OriginalRequest
= Irp
;
142 Srb
->PathId
= DeviceExtension
->PathId
;
143 Srb
->TargetId
= DeviceExtension
->TargetId
;
144 Srb
->Lun
= DeviceExtension
->Lun
;
145 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
146 Srb
->DataBuffer
= MmGetMdlVirtualAddress(Irp
->MdlAddress
);
147 Srb
->DataTransferLength
= CurrentIrpStack
->Parameters
.Read
.Length
;
148 Srb
->QueueAction
= SRB_SIMPLE_TAG_REQUEST
;
149 Srb
->QueueSortKey
= LogicalBlockAddress
;
151 Srb
->SenseInfoBuffer
= DeviceExtension
->SenseData
;
152 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
155 ((Srb
->DataTransferLength
+ 0xFFFF) >> 16) * DeviceExtension
->TimeOutValue
;
157 Srb
->SrbStatus
= SRB_STATUS_SUCCESS
;
162 Cdb
= (PCDB
)Srb
->Cdb
;
164 /* Initialize ATAPI packet (12 bytes) */
168 Cdb
->CDB10
.LogicalUnitNumber
= DeviceExtension
->Lun
;
169 TransferBlocks
= (USHORT
)(CurrentIrpStack
->Parameters
.Read
.Length
>> DeviceExtension
->SectorShift
);
171 /* Copy little endian values into CDB in big endian format */
172 Cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte3
;
173 Cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte2
;
174 Cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte1
;
175 Cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)&LogicalBlockAddress
)->Byte0
;
177 Cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)&TransferBlocks
)->Byte1
;
178 Cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)&TransferBlocks
)->Byte0
;
181 if (CurrentIrpStack
->MajorFunction
== IRP_MJ_READ
)
183 DPRINT1("ScsiClassBuildRequest: Read Command\n");
185 Srb
->SrbFlags
|= SRB_FLAGS_DATA_IN
;
186 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
190 DPRINT1("ScsiClassBuildRequest: Write Command\n");
192 Srb
->SrbFlags
|= SRB_FLAGS_DATA_OUT
;
193 Cdb
->CDB10
.OperationCode
= SCSIOP_WRITE
;
198 /* if this is not a write-through request, then allow caching */
199 if (!(CurrentIrpStack
->Flags
& SL_WRITE_THROUGH
))
201 Srb
->SrbFlags
|= SRB_FLAGS_ADAPTER_CACHE_ENABLE
;
205 /* if write caching is enable then force media access in the cdb */
206 if (DeviceExtension
->DeviceFlags
& DEV_WRITE_CACHE
)
208 Cdb
->CDB10
.ForceUnitAccess
= TRUE
;
213 /* or in the default flags from the device object. */
214 Srb
->SrbFlags
|= DeviceExtension
->SrbFlags
;
217 NextIrpStack
->MajorFunction
= IRP_MJ_SCSI
;
218 NextIrpStack
->Parameters
.Scsi
.Srb
= Srb
;
219 NextIrpStack
->DeviceObject
= DeviceObject
;
222 /* save retry count in current IRP stack */
223 CurrentIrpStack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
226 DPRINT1("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp
, Srb
);
227 IoSetCompletionRoutine(Irp
,
237 ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject
,
238 PSCSI_INQUIRY_DATA LunInfo
,
240 PDEVICE_OBJECT
*NewPortDeviceObject OPTIONAL
)
242 PIO_STACK_LOCATION IoStack
;
243 IO_STATUS_BLOCK IoStatusBlock
;
244 SCSI_REQUEST_BLOCK Srb
;
249 DPRINT("ScsiClassClaimDevice() called\n");
251 if (NewPortDeviceObject
!= NULL
)
252 *NewPortDeviceObject
= NULL
;
254 /* initialize an SRB */
256 sizeof(SCSI_REQUEST_BLOCK
));
257 Srb
.Length
= SCSI_REQUEST_BLOCK_SIZE
;
258 Srb
.PathId
= LunInfo
->PathId
;
259 Srb
.TargetId
= LunInfo
->TargetId
;
260 Srb
.Lun
= LunInfo
->Lun
;
262 (Release
== TRUE
) ? SRB_FUNCTION_RELEASE_DEVICE
: SRB_FUNCTION_CLAIM_DEVICE
;
264 KeInitializeEvent(&Event
,
268 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE
,
279 DPRINT1("Failed to allocate Irp!\n");
280 return(STATUS_INSUFFICIENT_RESOURCES
);
283 /* Link Srb and Irp */
284 IoStack
= IoGetNextIrpStackLocation(Irp
);
285 IoStack
->Parameters
.Scsi
.Srb
= &Srb
;
286 Srb
.OriginalRequest
= Irp
;
288 /* Call SCSI port driver */
289 Status
= IoCallDriver(PortDeviceObject
,
291 if (Status
== STATUS_PENDING
)
293 KeWaitForSingleObject(&Event
,
298 Status
= IoStatusBlock
.Status
;
303 ObDereferenceObject(PortDeviceObject
);
304 return(STATUS_SUCCESS
);
307 // Status = ObReferenceObjectByPointer(Srb.DataBuffer,
308 Status
= ObReferenceObjectByPointer(PortDeviceObject
,
313 if (NewPortDeviceObject
!= NULL
)
315 // *NewPortDeviceObject = Srb.DataBuffer;
316 *NewPortDeviceObject
= PortDeviceObject
;
319 return(STATUS_SUCCESS
);
324 ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
325 IN PCCHAR ObjectNameBuffer
,
326 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
327 IN OUT PDEVICE_OBJECT
*DeviceObject
,
328 IN PCLASS_INIT_DATA InitializationData
)
330 PDEVICE_OBJECT InternalDeviceObject
;
331 PDEVICE_EXTENSION DeviceExtension
;
332 ANSI_STRING AnsiName
;
333 UNICODE_STRING DeviceName
;
336 DPRINT("ScsiClassCreateDeviceObject() called\n");
338 *DeviceObject
= NULL
;
340 RtlInitAnsiString(&AnsiName
,
343 Status
= RtlAnsiStringToUnicodeString(&DeviceName
,
346 if (!NT_SUCCESS(Status
))
351 DPRINT("Device name: '%wZ'\n", &DeviceName
);
353 Status
= IoCreateDevice(DriverObject
,
354 InitializationData
->DeviceExtensionSize
,
356 InitializationData
->DeviceType
,
357 InitializationData
->DeviceCharacteristics
,
359 &InternalDeviceObject
);
360 if (NT_SUCCESS(Status
))
362 DeviceExtension
= InternalDeviceObject
->DeviceExtension
;
364 DeviceExtension
->ClassError
= InitializationData
->ClassError
;
365 DeviceExtension
->ClassReadWriteVerification
= InitializationData
->ClassReadWriteVerification
;
366 DeviceExtension
->ClassFindDevices
= InitializationData
->ClassFindDevices
;
367 DeviceExtension
->ClassDeviceControl
= InitializationData
->ClassDeviceControl
;
368 DeviceExtension
->ClassShutdownFlush
= InitializationData
->ClassShutdownFlush
;
369 DeviceExtension
->ClassCreateClose
= InitializationData
->ClassCreateClose
;
370 DeviceExtension
->ClassStartIo
= InitializationData
->ClassStartIo
;
372 DeviceExtension
->MediaChangeCount
= 0;
374 if (PhysicalDeviceObject
!= NULL
)
376 DeviceExtension
->PhysicalDevice
= PhysicalDeviceObject
;
380 DeviceExtension
->PhysicalDevice
= InternalDeviceObject
;
383 *DeviceObject
= InternalDeviceObject
;
386 RtlFreeUnicodeString(&DeviceName
);
393 ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject
,
401 ScsiClassFindModePage(PCHAR ModeSenseBuffer
,
411 ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData
,
412 PSCSI_ADAPTER_BUS_INFO AdapterInformation
)
414 PSCSI_INQUIRY_DATA UnitInfo
;
415 PINQUIRYDATA InquiryData
;
418 ULONG UnclaimedDevices
= 0;
421 DPRINT("ScsiClassFindUnclaimedDevices() called!\n");
423 DPRINT("NumberOfBuses: %lu\n",AdapterInformation
->NumberOfBuses
);
424 Buffer
= (PUCHAR
)AdapterInformation
;
425 for (Bus
= 0; Bus
< (ULONG
)AdapterInformation
->NumberOfBuses
; Bus
++)
427 DPRINT("Searching bus %lu\n", Bus
);
429 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterInformation
->BusData
[Bus
].InquiryDataOffset
);
431 while (AdapterInformation
->BusData
[Bus
].InquiryDataOffset
)
433 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
435 DPRINT("Device: '%.8s'\n", InquiryData
->VendorId
);
437 if ((InitializationData
->ClassFindDeviceCallBack(InquiryData
) == TRUE
) &&
438 (UnitInfo
->DeviceClaimed
== FALSE
))
443 if (UnitInfo
->NextInquiryDataOffset
== 0)
446 UnitInfo
= (PSCSI_INQUIRY_DATA
) (Buffer
+ UnitInfo
->NextInquiryDataOffset
);
450 return(UnclaimedDevices
);
455 ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject
,
456 PIO_SCSI_CAPABILITIES
*PortCapabilities
)
458 PIO_SCSI_CAPABILITIES Buffer
;
459 IO_STATUS_BLOCK IoStatusBlock
;
464 *PortCapabilities
= NULL
;
465 Buffer
= ExAllocatePool(NonPagedPool
, /* FIXME: use paged pool */
466 sizeof(IO_SCSI_CAPABILITIES
));
469 return(STATUS_INSUFFICIENT_RESOURCES
);
472 KeInitializeEvent(&Event
,
476 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES
,
481 sizeof(IO_SCSI_CAPABILITIES
),
488 return(STATUS_INSUFFICIENT_RESOURCES
);
491 Status
= IoCallDriver(PortDeviceObject
,
493 if (Status
== STATUS_PENDING
)
495 KeWaitForSingleObject(&Event
,
500 Status
= IoStatusBlock
.Status
;
503 if (!NT_SUCCESS(Status
))
509 *PortCapabilities
= Buffer
;
517 ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject
,
518 PSCSI_ADAPTER_BUS_INFO
*ConfigInfo
)
520 PSCSI_ADAPTER_BUS_INFO Buffer
;
521 IO_STATUS_BLOCK IoStatusBlock
;
527 Buffer
= ExAllocatePool(NonPagedPool
,
531 return(STATUS_INSUFFICIENT_RESOURCES
);
534 KeInitializeEvent(&Event
,
538 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA
,
550 return(STATUS_INSUFFICIENT_RESOURCES
);
553 Status
= IoCallDriver(PortDeviceObject
,
555 if (Status
== STATUS_PENDING
)
557 KeWaitForSingleObject(&Event
,
562 Status
= IoStatusBlock
.Status
;
565 if (!NT_SUCCESS(Status
))
571 *ConfigInfo
= Buffer
;
579 ScsiClassInitialize(PVOID Argument1
,
581 PCLASS_INIT_DATA InitializationData
)
583 PCONFIGURATION_INFORMATION ConfigInfo
;
584 PDRIVER_OBJECT DriverObject
= Argument1
;
585 WCHAR NameBuffer
[80];
586 UNICODE_STRING PortName
;
588 PDEVICE_OBJECT PortDeviceObject
;
589 PFILE_OBJECT FileObject
;
590 BOOLEAN DiskFound
= FALSE
;
593 DPRINT("ScsiClassInitialize() called!\n");
595 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiClassCreateClose
;
596 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiClassCreateClose
;
597 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScsiClassReadWrite
;
598 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScsiClassReadWrite
;
599 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiClassScsiDispatch
;
600 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiClassDeviceDispatch
;
601 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = ScsiClassShutdownFlush
;
602 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = ScsiClassShutdownFlush
;
603 if (InitializationData
->ClassStartIo
)
605 DriverObject
->DriverStartIo
= InitializationData
->ClassStartIo
;
608 ConfigInfo
= IoGetConfigurationInformation();
610 /* look for ScsiPortX scsi port devices */
611 for (PortNumber
= 0; PortNumber
< ConfigInfo
->ScsiPortCount
; PortNumber
++)
614 L
"\\Device\\ScsiPort%lu",
616 RtlInitUnicodeString(&PortName
,
618 DPRINT("Checking scsi port %ld\n", PortNumber
);
619 Status
= IoGetDeviceObjectPointer(&PortName
,
620 FILE_READ_ATTRIBUTES
,
623 DPRINT("Status 0x%08lX\n", Status
);
624 if (NT_SUCCESS(Status
))
626 DPRINT("ScsiPort%lu found.\n", PortNumber
);
628 /* check scsi port for attached disk drives */
629 if (InitializationData
->ClassFindDevices(DriverObject
,
640 DPRINT1("ScsiClassInitialize() done!\n");
642 return((DiskFound
== TRUE
) ? STATUS_SUCCESS
: STATUS_NO_SUCH_DEVICE
);
647 ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension
,
648 ULONG NumberElements
)
655 ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject
,
663 ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject
,
664 PSCSI_REQUEST_BLOCK Srb
,
665 UCHAR MajorFunctionCode
,
675 ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject
,
679 PDEVICE_EXTENSION DeviceExtension
;
680 PIO_STACK_LOCATION IrpStack
;
681 PSCSI_REQUEST_BLOCK Srb
;
684 DPRINT1("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n",
685 DeviceObject
, Irp
, Context
);
687 DeviceExtension
= DeviceObject
->DeviceExtension
;
688 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
689 DPRINT1("Srb %p\n", Srb
);
691 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
694 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
696 Status
= STATUS_SUCCESS
;
700 /* FIXME: improve error handling */
701 DPRINT1("Srb->SrbStatus %lx\n", Srb
->SrbStatus
);
703 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_PENDING
)
705 Status
= STATUS_SUCCESS
;
708 Status
= STATUS_UNSUCCESSFUL
;
712 /* FIXME: use lookaside list instead */
713 DPRINT1("Freed SRB %p\n", IrpStack
->Parameters
.Scsi
.Srb
);
714 ExFreePool(IrpStack
->Parameters
.Scsi
.Srb
);
716 // Irp->IoStatus.Status = Status;
718 if (!NT_SUCCESS(Status
) &&
719 IoIsErrorUserInduced(Status
))
721 IoSetHardErrorOrVerifyDevice(Irp
,
723 Irp
->IoStatus
.Information
= 0;
726 if (Irp
->PendingReturned
)
728 IoMarkIrpPending(Irp
);
731 if (DeviceExtension
->ClassStartIo
!= NULL
)
733 if (IrpStack
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
)
735 IoStartNextPacket(DeviceObject
,
741 DPRINT1("ScsiClassIoComplete() done (Status %lx)\n", Status
);
744 return(STATUS_SUCCESS
);
749 ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject
,
758 ScsiClassModeSense(PDEVICE_OBJECT DeviceObject
,
759 CHAR ModeSenseBuffer
,
768 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath
)
775 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject
)
777 PDEVICE_EXTENSION DeviceExtension
;
778 PREAD_CAPACITY_DATA CapacityBuffer
;
779 SCSI_REQUEST_BLOCK Srb
;
785 DPRINT("ScsiClassReadDriveCapacity() called\n");
787 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
789 CapacityBuffer
= ExAllocatePool(NonPagedPool
, //NonPagedPoolCacheAligned,
790 sizeof(READ_CAPACITY_DATA
));
791 if (CapacityBuffer
== NULL
)
793 return(STATUS_INSUFFICIENT_RESOURCES
);
796 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
799 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
802 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
805 Status
= ScsiClassSendSrbSynchronous(DeviceObject
,
808 sizeof(READ_CAPACITY_DATA
),
810 DPRINT("Status: %lx\n", Status
);
811 DPRINT("Srb: %p\n", &Srb
);
812 if (NT_SUCCESS(Status
))
814 SectorSize
= (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[0] << 24) |
815 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[1] << 16) |
816 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[2] << 8) |
817 ((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[3];
820 LastSector
= (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[0] << 24) |
821 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[1] << 16) |
822 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[2] << 8) |
823 ((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[3];
825 DeviceExtension
->DiskGeometry
->BytesPerSector
= SectorSize
;
827 DeviceExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(LastSector
+ 1);
828 WHICH_BIT(DeviceExtension
->DiskGeometry
->BytesPerSector
, DeviceExtension
->SectorShift
);
829 DeviceExtension
->PartitionLength
.QuadPart
=
830 (DeviceExtension
->PartitionLength
.QuadPart
<< DeviceExtension
->SectorShift
);
832 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
834 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
838 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
840 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
= (LONGLONG
)((LastSector
+ 1)/(32 * 64));
841 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= 32;
842 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= 64;
844 DPRINT1("SectorSize: %lu SectorCount: %lu\n", SectorSize
, LastSector
+ 1);
847 ExFreePool(CapacityBuffer
);
849 DPRINT1("ScsiClassReadDriveCapacity() done\n");
856 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject
)
863 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject
,
864 PSCSI_REQUEST_BLOCK Srb
,
868 BOOLEAN WriteToDevice
)
875 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject
,
876 PSCSI_REQUEST_BLOCK Srb
,
879 BOOLEAN WriteToDevice
)
881 PDEVICE_EXTENSION DeviceExtension
;
882 IO_STATUS_BLOCK IoStatusBlock
;
883 PIO_STACK_LOCATION IoStack
;
890 DPRINT("ScsiClassSendSrbSynchronous() called\n");
892 DeviceExtension
= DeviceObject
->DeviceExtension
;
894 Srb
->PathId
= DeviceExtension
->PathId
;
895 Srb
->TargetId
= DeviceExtension
->TargetId
;
896 Srb
->Lun
= DeviceExtension
->Lun
;
897 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
899 /* FIXME: more srb initialization required? */
902 if (BufferAddress
== NULL
)
905 RequestType
= IOCTL_SCSI_EXECUTE_NONE
;
906 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
910 if (WriteToDevice
== TRUE
)
912 RequestType
= IOCTL_SCSI_EXECUTE_OUT
;
913 Srb
->SrbFlags
= SRB_FLAGS_DATA_OUT
;
917 RequestType
= IOCTL_SCSI_EXECUTE_IN
;
918 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
922 Srb
->DataTransferLength
= BufferLength
;
923 Srb
->DataBuffer
= BufferAddress
;
926 KeInitializeEvent(&Event
,
930 Irp
= IoBuildDeviceIoControlRequest(RequestType
,
931 DeviceExtension
->PortDeviceObject
,
941 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
942 return(STATUS_INSUFFICIENT_RESOURCES
);
945 /* FIXME: more irp initialization required? */
948 /* Attach Srb to the Irp */
949 IoStack
= IoGetNextIrpStackLocation(Irp
);
950 IoStack
->Parameters
.Scsi
.Srb
= Srb
;
951 Srb
->OriginalRequest
= Irp
;
954 /* Call the SCSI port driver */
955 Status
= IoCallDriver(DeviceExtension
->PortDeviceObject
,
957 if (Status
== STATUS_PENDING
)
959 KeWaitForSingleObject(&Event
,
966 if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
)
969 DPRINT1("Fix return value!\n");
970 Status
= STATUS_UNSUCCESSFUL
;
974 Status
= STATUS_SUCCESS
;
977 DPRINT1("ScsiClassSendSrbSynchronous() done\n");
984 ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject
,
992 /* INTERNAL FUNCTIONS *******************************************************/
994 static NTSTATUS STDCALL
995 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject
,
998 PDEVICE_EXTENSION DeviceExtension
;
1000 DPRINT("ScsiClassCreateClose() called\n");
1002 DeviceExtension
= DeviceObject
->DeviceExtension
;
1004 if (DeviceExtension
->ClassCreateClose
)
1005 return(DeviceExtension
->ClassCreateClose(DeviceObject
,
1008 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1009 Irp
->IoStatus
.Information
= 0;
1010 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1012 return(STATUS_SUCCESS
);
1016 static NTSTATUS STDCALL
1017 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1020 PDEVICE_EXTENSION DeviceExtension
;
1021 PIO_STACK_LOCATION IrpStack
;
1022 ULONG TransferLength
;
1023 ULONG TransferPages
;
1026 DPRINT1("ScsiClassReadWrite() called\n");
1028 DeviceExtension
= DeviceObject
->DeviceExtension
;
1029 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1031 DPRINT1("Relative Offset: %I64u Length: %lu\n",
1032 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
,
1033 IrpStack
->Parameters
.Read
.Length
);
1035 TransferLength
= IrpStack
->Parameters
.Read
.Length
;
1039 if ((DeviceObject
->Flags
& DO_VERIFY_VOLUME
) &&
1040 !(IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
))
1042 IoSetHardErrorOrVerifyDevice(Irp
,
1045 Irp
->IoStatus
.Status
= STATUS_VERIFY_REQUIRED
;
1046 Irp
->IoStatus
.Information
= 0;
1048 IoCompleteRequest(Irp
,
1050 return(STATUS_VERIFY_REQUIRED
);
1054 /* let the class driver perform its verification */
1055 Status
= DeviceExtension
->ClassReadWriteVerification(DeviceObject
,
1057 if (!NT_SUCCESS(Status
))
1059 IoCompleteRequest(Irp
,
1063 else if (Status
== STATUS_PENDING
)
1065 IoMarkIrpPending(Irp
);
1066 return(STATUS_PENDING
);
1070 /* Finish a zero-byte transfer. */
1071 if (TransferLength
== 0)
1073 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1074 Irp
->IoStatus
.Information
= 0;
1075 IoCompleteRequest(Irp
,
1077 return(STATUS_SUCCESS
);
1080 if (DeviceExtension
->ClassStartIo
!= NULL
)
1082 DPRINT1("ScsiClassReadWrite() starting packet\n");
1084 IoMarkIrpPending(Irp
);
1085 IoStartPacket(DeviceObject
,
1090 return(STATUS_PENDING
);
1093 IoMarkIrpPending(Irp
);
1095 /* Adjust partition-relative starting offset to absolute offset */
1096 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
+= DeviceExtension
->StartingOffset
.QuadPart
;
1098 /* Calculate number of pages in this transfer. */
1099 TransferPages
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp
->MdlAddress
),
1100 IrpStack
->Parameters
.Read
.Length
);
1103 if (IrpStack
->Parameters
.Read
.Length
> maximumTransferLength
||
1104 TransferPages
> DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
)
1110 ScsiClassBuildRequest(DeviceObject
,
1113 DPRINT1("ScsiClassReadWrite() done\n");
1115 /* Call the port driver */
1116 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
1121 static NTSTATUS STDCALL
1122 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject
,
1125 DPRINT1("ScsiClassScsiDispatch() called\n");
1127 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1128 Irp
->IoStatus
.Information
= 0;
1129 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1131 return(STATUS_SUCCESS
);
1135 static NTSTATUS STDCALL
1136 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject
,
1139 PDEVICE_EXTENSION DeviceExtension
;
1141 DPRINT("ScsiClassDeviceDispatch() called\n");
1143 DeviceExtension
= DeviceObject
->DeviceExtension
;
1144 if (DeviceExtension
->ClassDeviceControl
)
1146 return(DeviceExtension
->ClassDeviceControl(DeviceObject
, Irp
));
1149 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1150 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1152 return(STATUS_INVALID_DEVICE_REQUEST
);
1156 static NTSTATUS STDCALL
1157 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
1160 PDEVICE_EXTENSION DeviceExtension
;
1162 DPRINT("ScsiClassShutdownFlush() called\n");
1164 DeviceExtension
= DeviceObject
->DeviceExtension
;
1165 if (DeviceExtension
->ClassShutdownFlush
)
1167 return(DeviceExtension
->ClassShutdownFlush(DeviceObject
, Irp
));
1170 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1171 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1173 return(STATUS_INVALID_DEVICE_REQUEST
);