#define VERSION "0.0.1"
+#define SCSI_DISK_TIMEOUT 10 /* Default timeout: 10 seconds */
+#define MODE_DATA_SIZE 192
+
typedef struct _DISK_DATA
{
{
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
+ DPRINT("Device type %u\n", InquiryData->DeviceType);
+
if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
(InquiryData->DeviceType == OPTICAL_DEVICE)) &&
(InquiryData->DeviceTypeQualifier == 0) &&
static NTSTATUS
DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath, /* what's this used for? */
+ IN PUNICODE_STRING RegistryPath,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN ULONG DiskNumber,
DiskDeviceExtension->TargetId = InquiryData->TargetId;
DiskDeviceExtension->Lun = InquiryData->Lun;
+ /* Get timeout value */
+ DiskDeviceExtension->TimeOutValue =
+ ScsiClassQueryTimeOutRegistryValue(RegistryPath);
+ if (DiskDeviceExtension->TimeOutValue == 0)
+ DiskDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
+
/* Initialize the lookaside list for SRBs */
ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
4);
return(STATUS_INSUFFICIENT_RESOURCES);
}
+ /* Allocate sense data buffer */
+ DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool,
+ sizeof(SENSE_BUFFER_SIZE));
+ if (DiskDeviceExtension->SenseData == NULL)
+ {
+ DPRINT("Failed to allocate sense data buffer!\n");
+
+ ExFreePool (DiskDeviceExtension->DiskGeometry);
+
+ ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
+
+ IoDeleteDevice(DiskDeviceObject);
+
+ /* Release (unclaim) the disk */
+ ScsiClassClaimDevice(PortDeviceObject,
+ InquiryData,
+ TRUE,
+ NULL);
+
+ /* Delete the harddisk device directory */
+ ZwMakeTemporaryObject(Handle);
+ ZwClose(Handle);
+
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
/* Read the drive's capacity */
Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
if (!NT_SUCCESS(Status) &&
PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
+ PartitionDeviceExtension->SenseData = DiskDeviceExtension->SenseData;
PartitionDeviceExtension->LockCount = 0;
PartitionDeviceExtension->DeviceNumber = DiskNumber;
PartitionDeviceExtension->DeviceObject = PartitionDeviceObject;
PartitionDeviceExtension->TargetId = InquiryData->TargetId;
PartitionDeviceExtension->Lun = InquiryData->Lun;
PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
+ PartitionDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
/* Initialize lookaside list for SRBs */
ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
{
Status = STATUS_INVALID_PARAMETER;
+ break;
}
- else
+
+ if (DeviceExtension->DiskGeometry == NULL)
{
- PDISK_GEOMETRY Geometry;
+ DPRINT("No disk geometry available!\n");
+ DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
+ sizeof(DISK_GEOMETRY));
+ }
- if (DeviceExtension->DiskGeometry == NULL)
- {
- DPRINT("No disk geometry available!\n");
- DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
- sizeof(DISK_GEOMETRY));
- }
+ if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
+ {
Status = ScsiClassReadDriveCapacity(DeviceObject);
DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
- if (NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
- Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
- RtlMoveMemory(Geometry,
- DeviceExtension->DiskGeometry,
- sizeof(DISK_GEOMETRY));
-
- Status = STATUS_SUCCESS;
- Information = sizeof(DISK_GEOMETRY);
+ /* Drive is not ready */
+ DiskData->DriveNotReady = FALSE;
+ break;
}
+
+ /* Drive is ready */
+ DiskData->DriveNotReady = FALSE;
}
+
+ RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
+ DeviceExtension->DiskGeometry,
+ sizeof(DISK_GEOMETRY));
+
+ Status = STATUS_SUCCESS;
+ Information = sizeof(DISK_GEOMETRY);
break;
case IOCTL_DISK_GET_PARTITION_INFO:
}
break;
+ case IOCTL_DISK_IS_WRITABLE:
+ {
+ PMODE_PARAMETER_HEADER ModeData;
+ ULONG Length;
+
+ ModeData = ExAllocatePool (NonPagedPool,
+ MODE_DATA_SIZE);
+ if (ModeData == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ RtlZeroMemory (ModeData,
+ MODE_DATA_SIZE);
+
+ Length = ScsiClassModeSense (DeviceObject,
+ (PVOID)ModeData,
+ MODE_DATA_SIZE,
+ MODE_SENSE_RETURN_ALL);
+ if (Length < sizeof(MODE_PARAMETER_HEADER))
+ {
+ /* FIXME: Retry */
+ Status = STATUS_IO_DEVICE_ERROR;
+ ExFreePool (ModeData);
+ break;
+ }
+
+ if (ModeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT)
+ {
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+ ExFreePool (ModeData);
+ }
+ break;
+
case IOCTL_DISK_VERIFY:
case IOCTL_DISK_FORMAT_TRACKS:
case IOCTL_DISK_PERFORMANCE:
- case IOCTL_DISK_IS_WRITABLE:
case IOCTL_DISK_LOGGING:
case IOCTL_DISK_FORMAT_TRACKS_EX:
case IOCTL_DISK_HISTOGRAM_STRUCTURE:
Srb->TargetId = DeviceExtension->TargetId;
Srb->Lun = DeviceExtension->Lun;
+ /* Set timeout */
+ Srb->TimeOutValue = DeviceExtension->TimeOutValue * 4;
+
/* Flush write cache */
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;