/*
* ReactOS kernel
- * Copyright (C) 2001, 2002, 2003 ReactOS Team
+ * Copyright (C) 2001, 2002, 2003, 2004 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: disk.c,v 1.26 2003/04/27 18:10:38 ekohl Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/storage/disk/disk.c
* PURPOSE: disk class driver
- * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ * PROGRAMMER: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#define VERSION "0.0.1"
+#define SCSI_DISK_TIMEOUT 10 /* Default timeout: 10 seconds */
+#define MODE_DATA_SIZE 192
+
typedef struct _DISK_DATA
{
PDEVICE_EXTENSION NextPartition;
+ ULONG Signature;
+ ULONG MbrCheckSum;
ULONG HiddenSectors;
ULONG PartitionNumber;
ULONG PartitionOrdinal;
BOOLEAN DriveNotReady;
} DISK_DATA, *PDISK_DATA;
-
BOOLEAN STDCALL
DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath,
DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+static VOID
+DiskClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
+ IN ULONG DeviceNumber);
static NTSTATUS
DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+static BOOLEAN
+ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
+ IN HANDLE BusKey,
+ OUT PULONG DetectedDiskNumber);
+
static VOID
DiskClassUpdatePartitionDeviceObjects (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static VOID
ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension);
+static BOOLEAN
+ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
+ OUT PULONG Checksum);
+
+
+static NTSTATUS
+DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
+ IN PIRP Irp);
+
/* FUNCTIONS ****************************************************************/
PCHAR Buffer;
ULONG Bus;
ULONG DeviceCount;
- BOOLEAN FoundDevice;
+ BOOLEAN FoundDevice = FALSE;
NTSTATUS Status;
DPRINT("DiskClassFindDevices() called.\n");
{
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 VOID
+DiskClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
+ IN ULONG DeviceNumber)
+{
+ WCHAR NameBuffer[MAX_PATH];
+ UNICODE_STRING Name;
+
+ swprintf (NameBuffer,
+ L"\\Device\\MediaChangeEvent%lu",
+ DeviceNumber);
+ RtlInitUnicodeString (&Name,
+ NameBuffer);
+
+ DeviceExtension->MediaChangeEvent =
+ IoCreateSynchronizationEvent (&Name,
+ &DeviceExtension->MediaChangeEventHandle);
+
+ KeClearEvent (DeviceExtension->MediaChangeEvent);
+}
+
+
+
/**********************************************************************
* NAME EXPORTED
* DiskClassCheckDevice
{
PDEVICE_EXTENSION DeviceExtension;
PDISK_DATA DiskData;
+ PIO_STACK_LOCATION IrpStack;
+ ULARGE_INTEGER EndingOffset;
DPRINT("DiskClassCheckReadWrite() called\n");
return(STATUS_INVALID_PARAMETER);
}
+
+
+ IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ EndingOffset.QuadPart = IrpStack->Parameters.Read.ByteOffset.QuadPart +
+ IrpStack->Parameters.Read.Length;
+
+
+ DPRINT("Ending %I64d, and RealEnding %I64d! PartSize %I64d\n",EndingOffset.QuadPart,
+ DeviceExtension->PartitionLength.QuadPart,
+ DeviceExtension->PartitionLength.QuadPart /
+ DeviceExtension->DiskGeometry->BytesPerSector);
+
+ if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
+ (DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
+ {
+/* Assume if removable media and if Partition length is 0, Partition not built yet! */
+ if (DeviceExtension->PartitionLength.QuadPart == 0)
+ return(STATUS_SUCCESS);
+ }
+
+ if (EndingOffset.QuadPart > DeviceExtension->PartitionLength.QuadPart)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ return(STATUS_INVALID_PARAMETER);
+ }
+
return(STATUS_SUCCESS);
}
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 = DiskDeviceObject->DeviceExtension;
DiskDeviceExtension->LockCount = 0;
DiskDeviceExtension->DeviceNumber = DiskNumber;
+ DiskDeviceExtension->DeviceObject = DiskDeviceObject;
DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
DiskDeviceExtension->PortCapabilities = Capabilities;
DiskDeviceExtension->PathId = InquiryData->PathId;
DiskDeviceExtension->TargetId = InquiryData->TargetId;
DiskDeviceExtension->Lun = InquiryData->Lun;
+ DiskDeviceExtension->SrbFlags = 0;
+
+ /* Enable the command queueing, if it possible */
+ if (Capabilities->TaggedQueuing &&
+ ((PINQUIRYDATA)InquiryData->InquiryData)->CommandQueue)
+ {
+ DiskDeviceExtension->SrbFlags |= SRB_FLAGS_QUEUE_ACTION_ENABLE;
+ }
+
+ /* Get timeout value */
+ DiskDeviceExtension->TimeOutValue =
+ ScsiClassQueryTimeOutRegistryValue(RegistryPath);
+ if (DiskDeviceExtension->TimeOutValue == 0)
+ DiskDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
/* Initialize the lookaside list for SRBs */
ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
return(STATUS_INSUFFICIENT_RESOURCES);
}
+ /* Allocate sense data buffer */
+ DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPoolCacheAligned,
+ 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) &&
(DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
{
- DPRINT1("Failed to retrieve drive capacity!\n");
+ DPRINT("Failed to retrieve drive capacity!\n");
return(STATUS_SUCCESS);
}
else
DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
+ if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
+ (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
+ {
+ DiskClassCreateMediaChangeEvent(DiskDeviceExtension,DiskNumber);
+ if (DiskDeviceExtension->MediaChangeEvent != NULL)
+ {
+ DPRINT("Allocated media change event!\n");
+ }
+ }
+
/* Check disk for presence of a disk manager */
HalExamineMBR(DiskDeviceObject,
DiskDeviceExtension->DiskGeometry->BytesPerSector,
if (NT_SUCCESS(Status))
{
DPRINT("Read partition table!\n");
-
DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
+ /* Set disk signature */
+ DiskData->Signature = PartitionList->Signature;
+
+ /* Calculate MBR checksum if disk got no signature */
+ if (DiskData->Signature == 0)
+ {
+ if (!ScsiDiskCalcMbrCheckSum(DiskDeviceExtension,
+ &DiskData->MbrCheckSum))
+ {
+ DPRINT("MBR checksum calculation failed for disk %lu\n",
+ DiskDeviceExtension->DeviceNumber);
+ }
+ else
+ {
+ DPRINT("MBR checksum for disk %lu is %lx\n",
+ DiskDeviceExtension->DeviceNumber,
+ DiskData->MbrCheckSum);
+ }
+ }
+ else
+ {
+ DPRINT("Signature on disk %lu is %lx\n",
+ DiskDeviceExtension->DeviceNumber,
+ DiskData->Signature);
+ }
+
+ /* Update disk geometry if disk is visible to the BIOS */
ScsiDiskUpdateFixedDiskGeometry(DiskDeviceExtension);
for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
PartitionEntry->PartitionNumber,
PartitionEntry->BootIndicator,
PartitionEntry->PartitionType,
- PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
- PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
+ PartitionEntry->StartingOffset.QuadPart /
+ DiskDeviceExtension->DiskGeometry->BytesPerSector,
+ PartitionEntry->PartitionLength.QuadPart /
+ DiskDeviceExtension->DiskGeometry->BytesPerSector);
/* Create partition device object */
sprintf(NameBuffer2,
Status = ScsiClassCreateDeviceObject(DriverObject,
NameBuffer2,
DiskDeviceObject,
- &PartitionDeviceObject,
+ &PartitionDeviceObject ,
InitializationData);
DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
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->PortDeviceObject = PortDeviceObject;
PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
PartitionDeviceExtension->TargetId = InquiryData->TargetId;
PartitionDeviceExtension->Lun = InquiryData->Lun;
PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
+ PartitionDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
/* Initialize lookaside list for SRBs */
ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
}
else
{
- DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
+ DPRINT("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
break;
}
}
+static NTSTATUS
+DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
+ IN PIRP Irp)
+{
+ PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
+ PDEVICE_EXTENSION DiskDeviceExtension, DDE;
+ PDISK_DATA DiskData, DD;
+ PPARTITION_INFORMATION PartitionEntry;
+ ULONG PartitionNumber;
+ NTSTATUS Status;
+
+ DPRINT("DiskBuildPartitionTable() start\n");
+
+ DiskDeviceExtension = (PDEVICE_EXTENSION)DiskDeviceObject->DeviceExtension;
+ DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
+
+ DDE = (PDEVICE_EXTENSION) DiskDeviceExtension->PhysicalDevice->DeviceExtension;
+ DD = (PDISK_DATA)(DDE +1);
+
+ /* Clear flag for Partition0, just incase it was set. */
+ DD->DriveNotReady = FALSE;
+
+ Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Drive is not ready. */
+ DPRINT("Drive not ready\n");
+ DiskData->DriveNotReady = TRUE;
+ return Status;
+ }
+
+ /* Read partition table */
+ Status = IoReadPartitionTable(DiskDeviceExtension->PhysicalDevice,
+ DiskDeviceExtension->DiskGeometry->BytesPerSector,
+ TRUE,
+ &PartitionList);
+
+ DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* Drive is not ready. */
+ DPRINT("Drive not ready\n");
+ DiskData->DriveNotReady = TRUE;
+ if (PartitionList != NULL)
+ ExFreePool(PartitionList);
+ return Status;
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("Read partition table!\n");
+ DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
+
+ /* Set disk signature */
+ DiskData->Signature = PartitionList->Signature;
+
+ DiskData->NextPartition = NULL;
+
+ if (PartitionList->PartitionCount)
+ {
+ for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
+ {
+ PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
+
+ DiskData->PartitionType = PartitionEntry->PartitionType;
+ DiskData->PartitionNumber = PartitionNumber + 1;
+ DiskData->PartitionOrdinal = PartitionNumber + 1;
+ DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
+ DiskData->BootIndicator = PartitionEntry->BootIndicator;
+ DiskData->DriveNotReady = FALSE;
+ DiskDeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
+ DiskDeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
+
+ DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
+ PartitionNumber,
+ DiskData->PartitionNumber,
+ DiskData->BootIndicator,
+ DiskData->PartitionType,
+ DiskDeviceExtension->StartingOffset.QuadPart /
+ DiskDeviceExtension->DiskGeometry->BytesPerSector,
+ DiskDeviceExtension->PartitionLength.QuadPart /
+ DiskDeviceExtension->DiskGeometry->BytesPerSector);
+ }
+ }
+ else
+ {
+ DiskData->PartitionType = 0;
+ DiskData->PartitionNumber = 1;
+ DiskData->PartitionOrdinal = 0;
+ DiskData->HiddenSectors = 0;
+ DiskData->BootIndicator = 0;
+ DiskData->DriveNotReady = FALSE;
+ DiskDeviceExtension->StartingOffset.QuadPart = 0;
+ DiskDeviceExtension->PartitionLength.QuadPart += DiskDeviceExtension->StartingOffset.QuadPart;
+ }
+ }
+
+ DPRINT("DiskBuildPartitionTable() done\n");
+ if (PartitionList != NULL)
+ ExFreePool(PartitionList);
+ return(STATUS_SUCCESS);
+}
+
+
/**********************************************************************
* NAME EXPORTED
* DiskClassDeviceControl
NTSTATUS STDCALL
DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
-{
+{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
ULONG ControlCode, InputLength, OutputLength;
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 = TRUE;
+ 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:
DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
+
+ if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
+ (DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
+ {
+ /* Update a partition list for a single entry. */
+ Status = DiskBuildPartitionTable(DeviceObject,Irp);
+ }
+
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION))
{
Status = STATUS_INVALID_DEVICE_REQUEST;
}
else
- {
+ {
PPARTITION_INFORMATION PartitionInfo;
PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
DeviceExtension->DiskGeometry->SectorsPerTrack,
DeviceExtension->DiskGeometry->TracksPerCylinder,
PartitionList);
- if (NT_SUCCESS(Status))
- {
- Information = TableSize;
- }
}
}
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:
case IOCTL_DISK_REQUEST_STRUCTURE:
case IOCTL_DISK_REQUEST_DATA:
/* If we get here, something went wrong. Inform the requestor */
- DPRINT1("Unhandled control code: %lx\n", ControlCode);
+ DPRINT("Unhandled control code: %lx\n", ControlCode);
Status = STATUS_INVALID_DEVICE_REQUEST;
Information = 0;
break;
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;
DeviceExtension->PartitionLength.QuadPart))
continue;
- DPRINT1("Found matching partition entry for partition %lu\n",
+ DPRINT("Found matching partition entry for partition %lu\n",
DiskData->PartitionNumber);
/* Found matching partition */
/* Assign new partiton ordinal */
DiskData->PartitionOrdinal = PartitionOrdinal;
- DPRINT1("Partition ordinal %lu was assigned to partition %lu\n",
- DiskData->PartitionOrdinal,
- DiskData->PartitionNumber);
+ DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
+ DiskData->PartitionOrdinal,
+ DiskData->PartitionNumber);
}
else
{
/* Delete this partition */
DeviceExtension->PartitionLength.QuadPart = 0ULL;
- DPRINT1("Deleting partition %lu\n",
- DiskData->PartitionNumber);
+ DPRINT("Deleting partition %lu\n",
+ DiskData->PartitionNumber);
}
}
if (PartitionNumber == 0)
{
/* Create a new partition device object */
- DPRINT1("Create new partition device object\n");
+ DPRINT("Create new partition device object\n");
/* Get new partiton number */
LastPartitionNumber++;
&DeviceObject);
if (!NT_SUCCESS(Status))
{
- DPRINT1("IoCreateDevice() failed (Status %lx)\n", Status);
+ DPRINT("IoCreateDevice() failed (Status %lx)\n", Status);
continue;
}
else
{
/* Reuse an existing partition device object */
- DPRINT1("Reuse an exisiting partition device object\n");
+ DPRINT("Reuse an exisiting partition device object\n");
DiskData = (PDISK_DATA)(DeviceExtension + 1);
}
/* Update partition number in the partition list */
PartitionEntry->PartitionNumber = PartitionNumber;
- DPRINT1("Partition ordinal %lu was assigned to partition %lu\n",
- DiskData->PartitionOrdinal,
- DiskData->PartitionNumber);
+ DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
+ DiskData->PartitionOrdinal,
+ DiskData->PartitionNumber);
}
DPRINT("ScsiDiskUpdatePartitionDeviceObjects() done\n");
}
+/**********************************************************************
+ * NAME INTERNAL
+ * ScsiDiskSearchForDisk
+ *
+ * DESCRIPTION
+ * Searches the hardware tree for the given disk.
+ *
+ * RUN LEVEL
+ * PASSIVE_LEVEL
+ *
+ * ARGUMENTS
+ * DeviceExtension
+ * Disk device extension.
+ *
+ * BusKey
+ * Handle to the hardware bus key.
+ *
+ * DetectedDiskNumber
+ * Returned disk number.
+ *
+ * RETURN VALUE
+ * TRUE: Disk was found.
+ * FALSE: Search failed.
+ */
+
+static BOOLEAN
+ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
+ IN HANDLE BusKey,
+ OUT PULONG DetectedDiskNumber)
+{
+ PKEY_VALUE_FULL_INFORMATION ValueData;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PDISK_DATA DiskData;
+ UNICODE_STRING IdentifierString;
+ UNICODE_STRING NameString;
+ HANDLE BusInstanceKey;
+ HANDLE ControllerKey;
+ HANDLE DiskKey;
+ HANDLE DiskInstanceKey;
+ ULONG BusNumber;
+ ULONG ControllerNumber;
+ ULONG DiskNumber;
+ ULONG Length;
+ WCHAR Buffer[32];
+ BOOLEAN DiskFound;
+ NTSTATUS Status;
+
+ DPRINT("ScsiDiskSearchForDiskData() called\n");
+
+ DiskFound = FALSE;
+
+ /* Enumerate buses */
+ for (BusNumber = 0; ; BusNumber++)
+ {
+ /* Open bus instance subkey */
+ swprintf(Buffer,
+ L"%lu",
+ BusNumber);
+
+ RtlInitUnicodeString(&NameString,
+ Buffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NameString,
+ OBJ_CASE_INSENSITIVE,
+ BusKey,
+ NULL);
+
+ Status = ZwOpenKey(&BusInstanceKey,
+ KEY_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ /* Open 'DiskController' subkey */
+ RtlInitUnicodeString(&NameString,
+ L"DiskController");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NameString,
+ OBJ_CASE_INSENSITIVE,
+ BusInstanceKey,
+ NULL);
+
+ Status = ZwOpenKey(&ControllerKey,
+ KEY_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwClose(BusInstanceKey);
+ continue;
+ }
+
+ /* Enumerate controllers */
+ for (ControllerNumber = 0; ; ControllerNumber++)
+ {
+ /* Open 'DiskPeripheral' subkey */
+ swprintf(Buffer,
+ L"%lu\\DiskPeripheral",
+ ControllerNumber);
+
+ RtlInitUnicodeString(&NameString,
+ Buffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NameString,
+ OBJ_CASE_INSENSITIVE,
+ ControllerKey,
+ NULL);
+
+ Status = ZwOpenKey(&DiskKey,
+ KEY_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ /* Enumerate disks */
+ for (DiskNumber = 0; ; DiskNumber++)
+ {
+ /* Open disk instance subkey */
+ swprintf(Buffer,
+ L"%lu",
+ DiskNumber);
+
+ RtlInitUnicodeString(&NameString,
+ Buffer);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NameString,
+ OBJ_CASE_INSENSITIVE,
+ DiskKey,
+ NULL);
+
+ Status = ZwOpenKey(&DiskInstanceKey,
+ KEY_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ DPRINT("Found disk key: bus %lu controller %lu disk %lu\n",
+ BusNumber,
+ ControllerNumber,
+ DiskNumber);
+
+ /* Allocate data buffer */
+ ValueData = ExAllocatePool(PagedPool,
+ 2048);
+ if (ValueData == NULL)
+ {
+ ZwClose(DiskInstanceKey);
+ continue;
+ }
+
+ /* Get the 'Identifier' value */
+ RtlInitUnicodeString(&NameString,
+ L"Identifier");
+ Status = ZwQueryValueKey(DiskInstanceKey,
+ &NameString,
+ KeyValueFullInformation,
+ ValueData,
+ 2048,
+ &Length);
+
+ ZwClose(DiskInstanceKey);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(ValueData);
+ continue;
+ }
+
+ IdentifierString.Buffer =
+ (PWSTR)((PUCHAR)ValueData + ValueData->DataOffset);
+ IdentifierString.Length = (USHORT)ValueData->DataLength - 2;
+ IdentifierString.MaximumLength = (USHORT)ValueData->DataLength;
+
+ DPRINT("DiskIdentifier: %wZ\n",
+ &IdentifierString);
+
+ DiskData = (PDISK_DATA)(DeviceExtension + 1);
+ if (DiskData->Signature != 0)
+ {
+ /* Comapre disk signature */
+ swprintf(Buffer,
+ L"%08lx",
+ DiskData->Signature);
+ if (!_wcsnicmp(Buffer, &IdentifierString.Buffer[9], 8))
+ {
+ DPRINT("Found disk %lu\n", DiskNumber);
+ DiskFound = TRUE;
+ *DetectedDiskNumber = DiskNumber;
+ }
+ }
+ else
+ {
+ /* Comapre mbr checksum */
+ swprintf(Buffer,
+ L"%08lx",
+ DiskData->MbrCheckSum);
+ if (!_wcsnicmp(Buffer, &IdentifierString.Buffer[0], 8))
+ {
+ DPRINT("Found disk %lu\n", DiskNumber);
+ DiskFound = TRUE;
+ *DetectedDiskNumber = DiskNumber;
+ }
+ }
+
+ ExFreePool(ValueData);
+
+ ZwClose(DiskInstanceKey);
+
+ if (DiskFound == TRUE)
+ break;
+ }
+
+ ZwClose(DiskKey);
+ }
+
+ ZwClose(ControllerKey);
+ ZwClose(BusInstanceKey);
+ }
+
+ DPRINT("ScsiDiskSearchForDisk() done\n");
+
+ return DiskFound;
+}
+
+
/**********************************************************************
* NAME INTERNAL
* DiskClassUpdateFixedDiskGeometry
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
HANDLE SystemKey;
+ HANDLE BusKey;
+ ULONG DiskNumber;
ULONG Length;
+#if 0
ULONG i;
+#endif
+ ULONG Cylinders;
+ ULONG Sectors;
+ ULONG SectorsPerTrack;
+ ULONG TracksPerCylinder;
NTSTATUS Status;
- DPRINT1("ScsiDiskUpdateFixedDiskGeometry() called\n");
+ DPRINT("ScsiDiskUpdateFixedDiskGeometry() called\n");
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\Hardware\\Description\\System");
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
- DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status);
+ DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
return;
}
1024);
if (ValueBuffer == NULL)
{
- DPRINT1("Failed to allocate value buffer\n");
+ DPRINT("Failed to allocate value buffer\n");
ZwClose(SystemKey);
return;
}
&Length);
if (!NT_SUCCESS(Status))
{
- DPRINT1("ZwQueryValueKey() failed (Status %lx)\n", Status);
+ DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
ExFreePool(ValueBuffer);
ZwClose(SystemKey);
return;
}
+ /* Open the 'MultifunctionAdapter' subkey */
+ RtlInitUnicodeString(&KeyName,
+ L"MultifunctionAdapter");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ SystemKey,
+ NULL);
+
+ Status = ZwOpenKey(&BusKey,
+ KEY_READ,
+ &ObjectAttributes);
ZwClose(SystemKey);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
+ ExFreePool(ValueBuffer);
+ return;
+ }
+
+ if (!ScsiDiskSearchForDisk(DeviceExtension, BusKey, &DiskNumber))
+ {
+ DPRINT("ScsiDiskSearchForDisk() failed\n");
+ ZwClose(BusKey);
+ ExFreePool(ValueBuffer);
+ return;
+ }
+ ZwClose(BusKey);
ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
((PUCHAR)ValueBuffer + ValueBuffer->DataOffset);
DriveParameters = (PCM_INT13_DRIVE_PARAMETER)
((PUCHAR)ResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
+#if 0
for (i = 0; i< DriveParameters[0].NumberDrives; i++)
{
- DPRINT1("Drive %lu: %lu Cylinders %hu Heads %hu Sectors\n",
+ DPRINT("Drive %lu: %lu Cylinders %hu Heads %hu Sectors\n",
i,
DriveParameters[i].MaxCylinders,
DriveParameters[i].MaxHeads,
DriveParameters[i].SectorsPerTrack);
}
+#endif
+
+ Cylinders = DriveParameters[DiskNumber].MaxCylinders + 1;
+ TracksPerCylinder = DriveParameters[DiskNumber].MaxHeads +1;
+ SectorsPerTrack = DriveParameters[DiskNumber].SectorsPerTrack;
+
+ DPRINT("BIOS geometry: %lu Cylinders %hu Heads %hu Sectors\n",
+ Cylinders,
+ TracksPerCylinder,
+ SectorsPerTrack);
+
+ Sectors = (ULONG)
+ (DeviceExtension->PartitionLength.QuadPart >> DeviceExtension->SectorShift);
+
+ DPRINT("Physical sectors: %lu\n",
+ Sectors);
+
+ Length = TracksPerCylinder * SectorsPerTrack;
+ if (Length == 0)
+ {
+ DPRINT("Invalid track length 0\n");
+ ExFreePool(ValueBuffer);
+ return;
+ }
+
+ Cylinders = Sectors / Length;
+
+ DPRINT("Logical geometry: %lu Cylinders %hu Heads %hu Sectors\n",
+ Cylinders,
+ TracksPerCylinder,
+ SectorsPerTrack);
+
+ /* Update the disk geometry */
+ DeviceExtension->DiskGeometry->SectorsPerTrack = SectorsPerTrack;
+ DeviceExtension->DiskGeometry->TracksPerCylinder = TracksPerCylinder;
+ DeviceExtension->DiskGeometry->Cylinders.QuadPart = (ULONGLONG)Cylinders;
- DPRINT1("*** System stopped ***\n");
- for(;;);
+ if (DeviceExtension->DMActive)
+ {
+ DPRINT("FIXME: Update geometry with respect to the installed disk manager!\n");
+
+ /* FIXME: Update geometry for disk managers */
+
+ }
ExFreePool(ValueBuffer);
- DPRINT1("ScsiDiskUpdateFixedDiskGeometry() done\n");
+ DPRINT("ScsiDiskUpdateFixedDiskGeometry() done\n");
+}
+
+
+/**********************************************************************
+ * NAME INTERNAL
+ * ScsiDiskCalcMbrCheckSum
+ *
+ * DESCRIPTION
+ * Calculates the Checksum from drives MBR.
+ *
+ * RUN LEVEL
+ * PASSIVE_LEVEL
+ *
+ * ARGUMENTS
+ * DeviceExtension
+ * Disk device extension.
+ *
+ * Checksum
+ * Pointer to the caller supplied cecksum variable.
+ *
+ * RETURN VALUE
+ * TRUE: Checksum was calculated.
+ * FALSE: Calculation failed.
+ */
+
+static BOOLEAN
+ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
+ OUT PULONG Checksum)
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER SectorOffset;
+ ULONG SectorSize;
+ PULONG MbrBuffer;
+ KEVENT Event;
+ PIRP Irp;
+ ULONG i;
+ ULONG Sum;
+ NTSTATUS Status;
+
+ KeInitializeEvent(&Event,
+ NotificationEvent,
+ FALSE);
+
+ /* Get the disk sector size */
+ SectorSize = DeviceExtension->DiskGeometry->BytesPerSector;
+ if (SectorSize < 512)
+ {
+ SectorSize = 512;
+ }
+
+ /* Allocate MBR buffer */
+ MbrBuffer = ExAllocatePool(NonPagedPool,
+ SectorSize);
+ if (MbrBuffer == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Allocate an IRP */
+ SectorOffset.QuadPart = 0ULL;
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+ DeviceExtension->DeviceObject,
+ MbrBuffer,
+ SectorSize,
+ &SectorOffset,
+ &Event,
+ &IoStatusBlock);
+ if (Irp == NULL)
+ {
+ ExFreePool(MbrBuffer);
+ return FALSE;
+ }
+
+ /* Call the miniport driver */
+ Status = IoCallDriver(DeviceExtension->DeviceObject,
+ Irp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event,
+ Suspended,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = IoStatusBlock.Status;
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(MbrBuffer);
+ return FALSE;
+ }
+
+ /* Calculate MBR checksum */
+ Sum = 0;
+ for (i = 0; i < 128; i++)
+ {
+ Sum += MbrBuffer[i];
+ }
+ *Checksum = ~Sum + 1;
+
+ ExFreePool(MbrBuffer);
+
+ return TRUE;
}
/* EOF */