1 /* $Id: class2.c,v 1.7 2002/03/03 19:38:09 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
;
221 /* save retry count in current IRP stack */
222 CurrentIrpStack
->Parameters
.Others
.Argument4
= (PVOID
)MAXIMUM_RETRIES
;
225 DPRINT1("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp
, Srb
);
226 IoSetCompletionRoutine(Irp
,
236 ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject
,
237 PSCSI_INQUIRY_DATA LunInfo
,
239 PDEVICE_OBJECT
*NewPortDeviceObject OPTIONAL
)
241 PIO_STACK_LOCATION IoStack
;
242 IO_STATUS_BLOCK IoStatusBlock
;
243 SCSI_REQUEST_BLOCK Srb
;
248 DPRINT("ScsiClassClaimDevice() called\n");
250 if (NewPortDeviceObject
!= NULL
)
251 *NewPortDeviceObject
= NULL
;
253 /* initialize an SRB */
255 sizeof(SCSI_REQUEST_BLOCK
));
256 Srb
.Length
= SCSI_REQUEST_BLOCK_SIZE
;
257 Srb
.PathId
= LunInfo
->PathId
;
258 Srb
.TargetId
= LunInfo
->TargetId
;
259 Srb
.Lun
= LunInfo
->Lun
;
261 (Release
== TRUE
) ? SRB_FUNCTION_RELEASE_DEVICE
: SRB_FUNCTION_CLAIM_DEVICE
;
263 KeInitializeEvent(&Event
,
267 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE
,
278 DPRINT1("Failed to allocate Irp!\n");
279 return(STATUS_INSUFFICIENT_RESOURCES
);
282 /* Link Srb and Irp */
283 IoStack
= IoGetNextIrpStackLocation(Irp
);
284 IoStack
->Parameters
.Scsi
.Srb
= &Srb
;
285 Srb
.OriginalRequest
= Irp
;
287 /* Call SCSI port driver */
288 Status
= IoCallDriver(PortDeviceObject
,
290 if (Status
== STATUS_PENDING
)
292 KeWaitForSingleObject(&Event
,
297 Status
= IoStatusBlock
.Status
;
302 ObDereferenceObject(PortDeviceObject
);
303 return(STATUS_SUCCESS
);
306 // Status = ObReferenceObjectByPointer(Srb.DataBuffer,
307 Status
= ObReferenceObjectByPointer(PortDeviceObject
,
312 if (NewPortDeviceObject
!= NULL
)
314 // *NewPortDeviceObject = Srb.DataBuffer;
315 *NewPortDeviceObject
= PortDeviceObject
;
318 return(STATUS_SUCCESS
);
323 ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject
,
324 IN PCCHAR ObjectNameBuffer
,
325 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
326 IN OUT PDEVICE_OBJECT
*DeviceObject
,
327 IN PCLASS_INIT_DATA InitializationData
)
329 PDEVICE_OBJECT InternalDeviceObject
;
330 PDEVICE_EXTENSION DeviceExtension
;
331 ANSI_STRING AnsiName
;
332 UNICODE_STRING DeviceName
;
335 DPRINT("ScsiClassCreateDeviceObject() called\n");
337 *DeviceObject
= NULL
;
339 RtlInitAnsiString(&AnsiName
,
342 Status
= RtlAnsiStringToUnicodeString(&DeviceName
,
345 if (!NT_SUCCESS(Status
))
350 DPRINT("Device name: '%wZ'\n", &DeviceName
);
352 Status
= IoCreateDevice(DriverObject
,
353 InitializationData
->DeviceExtensionSize
,
355 InitializationData
->DeviceType
,
356 InitializationData
->DeviceCharacteristics
,
358 &InternalDeviceObject
);
359 if (NT_SUCCESS(Status
))
361 DeviceExtension
= InternalDeviceObject
->DeviceExtension
;
363 DeviceExtension
->ClassError
= InitializationData
->ClassError
;
364 DeviceExtension
->ClassReadWriteVerification
= InitializationData
->ClassReadWriteVerification
;
365 DeviceExtension
->ClassFindDevices
= InitializationData
->ClassFindDevices
;
366 DeviceExtension
->ClassDeviceControl
= InitializationData
->ClassDeviceControl
;
367 DeviceExtension
->ClassShutdownFlush
= InitializationData
->ClassShutdownFlush
;
368 DeviceExtension
->ClassCreateClose
= InitializationData
->ClassCreateClose
;
369 DeviceExtension
->ClassStartIo
= InitializationData
->ClassStartIo
;
371 DeviceExtension
->MediaChangeCount
= 0;
373 if (PhysicalDeviceObject
!= NULL
)
375 DeviceExtension
->PhysicalDevice
= PhysicalDeviceObject
;
379 DeviceExtension
->PhysicalDevice
= InternalDeviceObject
;
382 *DeviceObject
= InternalDeviceObject
;
385 RtlFreeUnicodeString(&DeviceName
);
392 ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject
,
400 ScsiClassFindModePage(PCHAR ModeSenseBuffer
,
410 ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData
,
411 PSCSI_ADAPTER_BUS_INFO AdapterInformation
)
413 PSCSI_INQUIRY_DATA UnitInfo
;
414 PINQUIRYDATA InquiryData
;
417 ULONG UnclaimedDevices
= 0;
420 DPRINT("ScsiClassFindUnclaimedDevices() called!\n");
422 DPRINT("NumberOfBuses: %lu\n",AdapterInformation
->NumberOfBuses
);
423 Buffer
= (PUCHAR
)AdapterInformation
;
424 for (Bus
= 0; Bus
< (ULONG
)AdapterInformation
->NumberOfBuses
; Bus
++)
426 DPRINT("Searching bus %lu\n", Bus
);
428 UnitInfo
= (PSCSI_INQUIRY_DATA
)(Buffer
+ AdapterInformation
->BusData
[Bus
].InquiryDataOffset
);
430 while (AdapterInformation
->BusData
[Bus
].InquiryDataOffset
)
432 InquiryData
= (PINQUIRYDATA
)UnitInfo
->InquiryData
;
434 DPRINT("Device: '%.8s'\n", InquiryData
->VendorId
);
436 if ((InitializationData
->ClassFindDeviceCallBack(InquiryData
) == TRUE
) &&
437 (UnitInfo
->DeviceClaimed
== FALSE
))
442 if (UnitInfo
->NextInquiryDataOffset
== 0)
445 UnitInfo
= (PSCSI_INQUIRY_DATA
) (Buffer
+ UnitInfo
->NextInquiryDataOffset
);
449 return(UnclaimedDevices
);
454 ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject
,
455 PIO_SCSI_CAPABILITIES
*PortCapabilities
)
457 PIO_SCSI_CAPABILITIES Buffer
;
458 IO_STATUS_BLOCK IoStatusBlock
;
463 *PortCapabilities
= NULL
;
464 Buffer
= ExAllocatePool(NonPagedPool
, /* FIXME: use paged pool */
465 sizeof(IO_SCSI_CAPABILITIES
));
468 return(STATUS_INSUFFICIENT_RESOURCES
);
471 KeInitializeEvent(&Event
,
475 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES
,
480 sizeof(IO_SCSI_CAPABILITIES
),
487 return(STATUS_INSUFFICIENT_RESOURCES
);
490 Status
= IoCallDriver(PortDeviceObject
,
492 if (Status
== STATUS_PENDING
)
494 KeWaitForSingleObject(&Event
,
499 Status
= IoStatusBlock
.Status
;
502 if (!NT_SUCCESS(Status
))
508 *PortCapabilities
= Buffer
;
516 ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject
,
517 PSCSI_ADAPTER_BUS_INFO
*ConfigInfo
)
519 PSCSI_ADAPTER_BUS_INFO Buffer
;
520 IO_STATUS_BLOCK IoStatusBlock
;
526 Buffer
= ExAllocatePool(NonPagedPool
,
530 return(STATUS_INSUFFICIENT_RESOURCES
);
533 KeInitializeEvent(&Event
,
537 Irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA
,
549 return(STATUS_INSUFFICIENT_RESOURCES
);
552 Status
= IoCallDriver(PortDeviceObject
,
554 if (Status
== STATUS_PENDING
)
556 KeWaitForSingleObject(&Event
,
561 Status
= IoStatusBlock
.Status
;
564 if (!NT_SUCCESS(Status
))
570 *ConfigInfo
= Buffer
;
578 ScsiClassInitialize(PVOID Argument1
,
580 PCLASS_INIT_DATA InitializationData
)
582 PCONFIGURATION_INFORMATION ConfigInfo
;
583 PDRIVER_OBJECT DriverObject
= Argument1
;
584 WCHAR NameBuffer
[80];
585 UNICODE_STRING PortName
;
587 PDEVICE_OBJECT PortDeviceObject
;
588 PFILE_OBJECT FileObject
;
589 BOOLEAN DiskFound
= FALSE
;
592 DPRINT("ScsiClassInitialize() called!\n");
594 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScsiClassCreateClose
;
595 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScsiClassCreateClose
;
596 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScsiClassReadWrite
;
597 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScsiClassReadWrite
;
598 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = ScsiClassScsiDispatch
;
599 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScsiClassDeviceDispatch
;
600 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = ScsiClassShutdownFlush
;
601 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = ScsiClassShutdownFlush
;
602 if (InitializationData
->ClassStartIo
)
604 DriverObject
->DriverStartIo
= InitializationData
->ClassStartIo
;
607 ConfigInfo
= IoGetConfigurationInformation();
609 /* look for ScsiPortX scsi port devices */
610 for (PortNumber
= 0; PortNumber
< ConfigInfo
->ScsiPortCount
; PortNumber
++)
613 L
"\\Device\\ScsiPort%lu",
615 RtlInitUnicodeString(&PortName
,
617 DPRINT("Checking scsi port %ld\n", PortNumber
);
618 Status
= IoGetDeviceObjectPointer(&PortName
,
619 FILE_READ_ATTRIBUTES
,
622 DPRINT("Status 0x%08lX\n", Status
);
623 if (NT_SUCCESS(Status
))
625 DPRINT("ScsiPort%lu found.\n", PortNumber
);
627 /* check scsi port for attached disk drives */
628 if (InitializationData
->ClassFindDevices(DriverObject
,
639 DPRINT1("ScsiClassInitialize() done!\n");
641 return((DiskFound
== TRUE
) ? STATUS_SUCCESS
: STATUS_NO_SUCH_DEVICE
);
646 ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension
,
647 ULONG NumberElements
)
654 ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject
,
662 ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject
,
663 PSCSI_REQUEST_BLOCK Srb
,
664 UCHAR MajorFunctionCode
,
674 ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject
,
678 PDEVICE_EXTENSION DeviceExtension
;
679 PIO_STACK_LOCATION IrpStack
;
680 PSCSI_REQUEST_BLOCK Srb
;
683 DPRINT1("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n",
684 DeviceObject
, Irp
, Context
);
686 DeviceExtension
= DeviceObject
->DeviceExtension
;
687 Srb
= (PSCSI_REQUEST_BLOCK
)Context
;
688 DPRINT1("Srb %p\n", Srb
);
690 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
693 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
)
695 Status
= STATUS_SUCCESS
;
699 /* FIXME: improve error handling */
700 DPRINT1("Srb->SrbStatus %lx\n", Srb
->SrbStatus
);
702 if (SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_PENDING
)
704 Status
= STATUS_SUCCESS
;
707 Status
= STATUS_UNSUCCESSFUL
;
711 /* FIXME: use lookaside list instead */
712 DPRINT1("Freed SRB %p\n", IrpStack
->Parameters
.Scsi
.Srb
);
713 ExFreePool(IrpStack
->Parameters
.Scsi
.Srb
);
715 // Irp->IoStatus.Status = Status;
717 if (!NT_SUCCESS(Status
) &&
718 IoIsErrorUserInduced(Status
))
720 IoSetHardErrorOrVerifyDevice(Irp
,
722 Irp
->IoStatus
.Information
= 0;
725 if (Irp
->PendingReturned
)
727 IoMarkIrpPending(Irp
);
730 if (DeviceExtension
->ClassStartIo
!= NULL
)
732 if (IrpStack
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
)
734 IoStartNextPacket(DeviceObject
,
740 DPRINT1("ScsiClassIoComplete() done (Status %lx)\n", Status
);
743 return(STATUS_SUCCESS
);
748 ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject
,
757 ScsiClassModeSense(PDEVICE_OBJECT DeviceObject
,
758 CHAR ModeSenseBuffer
,
767 ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath
)
774 ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject
)
776 PDEVICE_EXTENSION DeviceExtension
;
777 PREAD_CAPACITY_DATA CapacityBuffer
;
778 SCSI_REQUEST_BLOCK Srb
;
784 DPRINT("ScsiClassReadDriveCapacity() called\n");
786 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
788 CapacityBuffer
= ExAllocatePool(NonPagedPool
, //NonPagedPoolCacheAligned,
789 sizeof(READ_CAPACITY_DATA
));
790 if (CapacityBuffer
== NULL
)
792 return(STATUS_INSUFFICIENT_RESOURCES
);
795 RtlZeroMemory(&Srb
, sizeof(SCSI_REQUEST_BLOCK
));
798 Srb
.TimeOutValue
= DeviceExtension
->TimeOutValue
;
801 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
804 Status
= ScsiClassSendSrbSynchronous(DeviceObject
,
807 sizeof(READ_CAPACITY_DATA
),
809 DPRINT("Status: %lx\n", Status
);
810 DPRINT("Srb: %p\n", &Srb
);
811 if (NT_SUCCESS(Status
))
813 SectorSize
= (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[0] << 24) |
814 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[1] << 16) |
815 (((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[2] << 8) |
816 ((PUCHAR
)&CapacityBuffer
->BytesPerBlock
)[3];
819 LastSector
= (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[0] << 24) |
820 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[1] << 16) |
821 (((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[2] << 8) |
822 ((PUCHAR
)&CapacityBuffer
->LogicalBlockAddress
)[3];
824 DeviceExtension
->DiskGeometry
->BytesPerSector
= SectorSize
;
826 DeviceExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(LastSector
+ 1);
827 WHICH_BIT(DeviceExtension
->DiskGeometry
->BytesPerSector
, DeviceExtension
->SectorShift
);
828 DeviceExtension
->PartitionLength
.QuadPart
=
829 (DeviceExtension
->PartitionLength
.QuadPart
<< DeviceExtension
->SectorShift
);
831 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
833 DeviceExtension
->DiskGeometry
->MediaType
= RemovableMedia
;
837 DeviceExtension
->DiskGeometry
->MediaType
= FixedMedia
;
839 DeviceExtension
->DiskGeometry
->Cylinders
.QuadPart
= (LONGLONG
)((LastSector
+ 1)/(32 * 64));
840 DeviceExtension
->DiskGeometry
->SectorsPerTrack
= 32;
841 DeviceExtension
->DiskGeometry
->TracksPerCylinder
= 64;
843 DPRINT1("SectorSize: %lu SectorCount: %lu\n", SectorSize
, LastSector
+ 1);
846 ExFreePool(CapacityBuffer
);
848 DPRINT1("ScsiClassReadDriveCapacity() done\n");
855 ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject
)
862 ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject
,
863 PSCSI_REQUEST_BLOCK Srb
,
867 BOOLEAN WriteToDevice
)
874 ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject
,
875 PSCSI_REQUEST_BLOCK Srb
,
878 BOOLEAN WriteToDevice
)
880 PDEVICE_EXTENSION DeviceExtension
;
881 IO_STATUS_BLOCK IoStatusBlock
;
882 PIO_STACK_LOCATION IoStack
;
889 DPRINT("ScsiClassSendSrbSynchronous() called\n");
891 DeviceExtension
= DeviceObject
->DeviceExtension
;
893 Srb
->PathId
= DeviceExtension
->PathId
;
894 Srb
->TargetId
= DeviceExtension
->TargetId
;
895 Srb
->Lun
= DeviceExtension
->Lun
;
896 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
898 /* FIXME: more srb initialization required? */
901 if (BufferAddress
== NULL
)
904 RequestType
= IOCTL_SCSI_EXECUTE_NONE
;
905 Srb
->SrbFlags
= SRB_FLAGS_NO_DATA_TRANSFER
;
909 if (WriteToDevice
== TRUE
)
911 RequestType
= IOCTL_SCSI_EXECUTE_OUT
;
912 Srb
->SrbFlags
= SRB_FLAGS_DATA_OUT
;
916 RequestType
= IOCTL_SCSI_EXECUTE_IN
;
917 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
921 Srb
->DataTransferLength
= BufferLength
;
922 Srb
->DataBuffer
= BufferAddress
;
925 KeInitializeEvent(&Event
,
929 Irp
= IoBuildDeviceIoControlRequest(RequestType
,
930 DeviceExtension
->PortDeviceObject
,
940 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
941 return(STATUS_INSUFFICIENT_RESOURCES
);
944 /* FIXME: more irp initialization required? */
947 /* Attach Srb to the Irp */
948 IoStack
= IoGetNextIrpStackLocation(Irp
);
949 IoStack
->Parameters
.Scsi
.Srb
= Srb
;
950 Srb
->OriginalRequest
= Irp
;
953 /* Call the SCSI port driver */
954 Status
= IoCallDriver(DeviceExtension
->PortDeviceObject
,
956 if (Status
== STATUS_PENDING
)
958 KeWaitForSingleObject(&Event
,
965 if (SRB_STATUS(Srb
->SrbStatus
) != SRB_STATUS_SUCCESS
)
968 DPRINT1("Fix return value!\n");
969 Status
= STATUS_UNSUCCESSFUL
;
973 Status
= STATUS_SUCCESS
;
976 DPRINT1("ScsiClassSendSrbSynchronous() done\n");
983 ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject
,
991 /* INTERNAL FUNCTIONS *******************************************************/
993 static NTSTATUS STDCALL
994 ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject
,
997 PDEVICE_EXTENSION DeviceExtension
;
999 DPRINT("ScsiClassCreateClose() called\n");
1001 DeviceExtension
= DeviceObject
->DeviceExtension
;
1003 if (DeviceExtension
->ClassCreateClose
)
1004 return(DeviceExtension
->ClassCreateClose(DeviceObject
,
1007 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1008 Irp
->IoStatus
.Information
= 0;
1009 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1011 return(STATUS_SUCCESS
);
1015 static NTSTATUS STDCALL
1016 ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1019 PDEVICE_EXTENSION DeviceExtension
;
1020 PIO_STACK_LOCATION IrpStack
;
1021 ULONG TransferLength
;
1022 ULONG TransferPages
;
1025 DPRINT1("ScsiClassReadWrite() called\n");
1027 DeviceExtension
= DeviceObject
->DeviceExtension
;
1028 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
1030 DPRINT1("Relative Offset: %I64u Length: %lu\n",
1031 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
,
1032 IrpStack
->Parameters
.Read
.Length
);
1034 TransferLength
= IrpStack
->Parameters
.Read
.Length
;
1038 if ((DeviceObject
->Flags
& DO_VERIFY_VOLUME
) &&
1039 !(IrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
))
1041 IoSetHardErrorOrVerifyDevice(Irp
,
1044 Irp
->IoStatus
.Status
= STATUS_VERIFY_REQUIRED
;
1045 Irp
->IoStatus
.Information
= 0;
1047 IoCompleteRequest(Irp
,
1049 return(STATUS_VERIFY_REQUIRED
);
1053 /* let the class driver perform its verification */
1054 Status
= DeviceExtension
->ClassReadWriteVerification(DeviceObject
,
1056 if (!NT_SUCCESS(Status
))
1058 IoCompleteRequest(Irp
,
1062 else if (Status
== STATUS_PENDING
)
1064 IoMarkIrpPending(Irp
);
1065 return(STATUS_PENDING
);
1069 /* Finish a zero-byte transfer. */
1070 if (TransferLength
== 0)
1072 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1073 Irp
->IoStatus
.Information
= 0;
1074 IoCompleteRequest(Irp
,
1076 return(STATUS_SUCCESS
);
1079 if (DeviceExtension
->ClassStartIo
!= NULL
)
1081 DPRINT1("ScsiClassReadWrite() starting packet\n");
1083 IoMarkIrpPending(Irp
);
1084 IoStartPacket(DeviceObject
,
1089 return(STATUS_PENDING
);
1092 IoMarkIrpPending(Irp
);
1094 /* Adjust partition-relative starting offset to absolute offset */
1095 IrpStack
->Parameters
.Read
.ByteOffset
.QuadPart
+= DeviceExtension
->StartingOffset
.QuadPart
;
1097 /* Calculate number of pages in this transfer. */
1098 TransferPages
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp
->MdlAddress
),
1099 IrpStack
->Parameters
.Read
.Length
);
1102 if (IrpStack
->Parameters
.Read
.Length
> maximumTransferLength
||
1103 TransferPages
> DeviceExtension
->PortCapabilities
->MaximumPhysicalPages
)
1109 ScsiClassBuildRequest(DeviceObject
,
1112 DPRINT1("ScsiClassReadWrite() done\n");
1114 /* Call the port driver */
1115 return(IoCallDriver(DeviceExtension
->PortDeviceObject
,
1120 static NTSTATUS STDCALL
1121 ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject
,
1124 DPRINT1("ScsiClassScsiDispatch() called\n");
1126 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1127 Irp
->IoStatus
.Information
= 0;
1128 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1130 return(STATUS_SUCCESS
);
1134 static NTSTATUS STDCALL
1135 ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject
,
1138 PDEVICE_EXTENSION DeviceExtension
;
1140 DPRINT("ScsiClassDeviceDispatch() called\n");
1142 DeviceExtension
= DeviceObject
->DeviceExtension
;
1143 if (DeviceExtension
->ClassDeviceControl
)
1145 return(DeviceExtension
->ClassDeviceControl(DeviceObject
, Irp
));
1148 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1149 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1151 return(STATUS_INVALID_DEVICE_REQUEST
);
1155 static NTSTATUS STDCALL
1156 ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject
,
1159 PDEVICE_EXTENSION DeviceExtension
;
1161 DPRINT("ScsiClassShutdownFlush() called\n");
1163 DeviceExtension
= DeviceObject
->DeviceExtension
;
1164 if (DeviceExtension
->ClassShutdownFlush
)
1166 return(DeviceExtension
->ClassShutdownFlush(DeviceObject
, Irp
));
1169 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1170 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1172 return(STATUS_INVALID_DEVICE_REQUEST
);