-/* $Id: disk.c,v 1.1 2001/07/24 10:21:15 ekohl Exp $
+/*
+ * ReactOS kernel
+ * Copyright (C) 2001, 2002 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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.11 2002/03/22 20:35:09 ekohl Exp $
*
+ * 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)
*/
-// -------------------------------------------------------------------------
+/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
-//#define NDEBUG
-#include <debug.h>
-
-//#include "ide.h"
-//#include "partitio.h"
-
-#define VERSION "V0.0.1"
+#include "../include/scsi.h"
+#include "../include/class2.h"
+#include "../include/ntddscsi.h"
+#define NDEBUG
+#include <debug.h>
-static NTSTATUS DiskCreateDevices(VOID);
-static BOOLEAN DiskFindDiskDrives(PDEVICE_OBJECT PortDeviceObject, ULONG PortNumber);
+#define VERSION "0.0.1"
-/*
- * DiskOpenClose
- *
- * DESCRIPTION:
- * Answer requests for Open/Close calls: a null operation
- *
- * RUN LEVEL:
- * PASSIVE_LEVEL
- *
- * ARGUMENTS:
- * Standard dispatch arguments
- *
- * RETURNS:
- * NTSTATUS
-*/
-#if 0
-static NTSTATUS STDCALL
-DiskOpenClose(IN PDEVICE_OBJECT pDO,
- IN PIRP Irp)
+typedef struct _DISK_DATA
{
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = FILE_OPENED;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ ULONG HiddenSectors;
+ ULONG PartitionNumber;
+ UCHAR PartitionType;
+ BOOLEAN BootIndicator;
+ BOOLEAN DriveNotReady;
+} DISK_DATA, *PDISK_DATA;
- return STATUS_SUCCESS;
-}
-#endif
+BOOLEAN STDCALL
+DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath,
+ PCLASS_INIT_DATA InitializationData,
+ PDEVICE_OBJECT PortDeviceObject,
+ ULONG PortNumber);
-static NTSTATUS STDCALL
-DiskClassReadWrite(IN PDEVICE_OBJECT pDO,
- IN PIRP Irp)
-{
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+BOOLEAN STDCALL
+DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
- return STATUS_SUCCESS;
-}
+NTSTATUS STDCALL
+DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
-static NTSTATUS STDCALL
-DiskClassDeviceControl(IN PDEVICE_OBJECT pDO,
- IN PIRP Irp)
-{
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+static NTSTATUS
+DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath, /* what's this used for? */
+ IN PDEVICE_OBJECT PortDeviceObject,
+ IN ULONG PortNumber,
+ IN ULONG DiskNumber,
+ IN PIO_SCSI_CAPABILITIES Capabilities,
+ IN PSCSI_INQUIRY_DATA InquiryData,
+ IN PCLASS_INIT_DATA InitializationData);
- return STATUS_SUCCESS;
-}
+NTSTATUS STDCALL
+DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+NTSTATUS STDCALL
+DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
-static NTSTATUS STDCALL
-DiskClassShutdownFlush(IN PDEVICE_OBJECT pDO,
- IN PIRP Irp)
-{
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
-}
+/* FUNCTIONS ****************************************************************/
// DriverEntry
//
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
- NTSTATUS Status;
+ CLASS_INIT_DATA InitData;
+
+ DbgPrint("Disk Class Driver %s\n",
+ VERSION);
+ DPRINT("RegistryPath '%wZ'\n",
+ RegistryPath);
+
+ RtlZeroMemory(&InitData,
+ sizeof(CLASS_INIT_DATA));
+
+ InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
+ InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
+ InitData.DeviceType = FILE_DEVICE_DISK;
+ InitData.DeviceCharacteristics = 0;
+
+ InitData.ClassError = NULL; // DiskClassProcessError;
+ InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
+ InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
+ InitData.ClassFindDevices = DiskClassFindDevices;
+ InitData.ClassDeviceControl = DiskClassDeviceControl;
+ InitData.ClassShutdownFlush = DiskClassShutdownFlush;
+ InitData.ClassCreateClose = NULL;
+ InitData.ClassStartIo = NULL;
+
+ return(ScsiClassInitialize(DriverObject,
+ RegistryPath,
+ &InitData));
+}
- DbgPrint("Disk Class Driver %s\n", VERSION);
- /* Export other driver entry points... */
-// DriverObject->DriverStartIo = IDEStartIo;
-// DriverObject->MajorFunction[IRP_MJ_CREATE] = DiskClassOpenClose;
-// DriverObject->MajorFunction[IRP_MJ_CLOSE] = DiskClassOpenClose;
- DriverObject->MajorFunction[IRP_MJ_READ] = DiskClassReadWrite;
- DriverObject->MajorFunction[IRP_MJ_WRITE] = DiskClassReadWrite;
- DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DiskClassDeviceControl;
- DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DiskClassShutdownFlush;
- DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = DiskClassShutdownFlush;
+/**********************************************************************
+ * NAME EXPORTED
+ * DiskClassFindDevices
+ *
+ * DESCRIPTION
+ * This function searches for device that are attached to the
+ * given scsi port.
+ *
+ * RUN LEVEL
+ * PASSIVE_LEVEL
+ *
+ * ARGUMENTS
+ * DriverObject
+ * System allocated Driver Object for this driver
+ *
+ * RegistryPath
+ * Name of registry driver service key
+ *
+ * InitializationData
+ * Pointer to the main initialization data
+ *
+ * PortDeviceObject
+ * Pointer to the port Device Object
+ *
+ * PortNumber
+ * Port number
+ *
+ * RETURN VALUE
+ * TRUE: At least one disk drive was found
+ * FALSE: No disk drive found
+ */
- Status = DiskCreateDevices();
- DPRINT("Status 0x%08X\n", Status);
+BOOLEAN STDCALL
+DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath,
+ PCLASS_INIT_DATA InitializationData,
+ PDEVICE_OBJECT PortDeviceObject,
+ ULONG PortNumber)
+{
+ PCONFIGURATION_INFORMATION ConfigInfo;
+ PIO_SCSI_CAPABILITIES PortCapabilities;
+ PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
+ PSCSI_INQUIRY_DATA UnitInfo;
+ PINQUIRYDATA InquiryData;
+ PCHAR Buffer;
+ ULONG Bus;
+ ULONG DeviceCount;
+ BOOLEAN FoundDevice;
+ NTSTATUS Status;
+
+ DPRINT("DiskClassFindDevices() called.\n");
+
+ /* Get port capabilities */
+ Status = ScsiClassGetCapabilities(PortDeviceObject,
+ &PortCapabilities);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
+ return(FALSE);
+ }
- DPRINT("Returning from DriverEntry\n");
- return STATUS_SUCCESS;
-}
+ DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
+ /* Get inquiry data */
+ Status = ScsiClassGetInquiryData(PortDeviceObject,
+ (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
+ return(FALSE);
+ }
+ /* Check whether there are unclaimed devices */
+ AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
+ DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
+ AdapterBusInfo);
+ if (DeviceCount == 0)
+ {
+ DPRINT1("No unclaimed devices!\n");
+ return(FALSE);
+ }
-static NTSTATUS
-DiskCreateDevices(VOID)
-{
- WCHAR NameBuffer[80];
- UNICODE_STRING PortName;
- ULONG PortNumber = 0;
- PDEVICE_OBJECT PortDeviceObject;
- PFILE_OBJECT FileObject;
- BOOLEAN DiskFound = FALSE;
- NTSTATUS Status;
-
- DPRINT1("DiskCreateDevices() called.\n");
-
- /* look for ScsiPortX scsi port devices */
- do
- {
- swprintf(NameBuffer,
- L"\\Device\\ScsiPort%ld",
- PortNumber);
- RtlInitUnicodeString(&PortName,
- NameBuffer);
- DPRINT1("Checking scsi port %ld\n", PortNumber);
- Status = IoGetDeviceObjectPointer(&PortName,
- FILE_READ_ATTRIBUTES,
- &FileObject,
- &PortDeviceObject);
- DPRINT1("Status 0x%08lX\n", Status);
- if (NT_SUCCESS(Status))
- {
- DPRINT1("ScsiPort%ld found.\n", PortNumber);
+ DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
- /* Check scsi port for attached disk drives */
- DiskFound = DiskFindDiskDrives(PortDeviceObject, PortNumber);
- }
- PortNumber++;
- }
- while (NT_SUCCESS(Status));
+ ConfigInfo = IoGetConfigurationInformation();
+
+ /* Search each bus of this adapter */
+ for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
+ {
+ DPRINT("Searching bus %lu\n", Bus);
+
+ UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
+
+ while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
+ {
+ InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
+
+ if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
+ (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
+ (InquiryData->DeviceTypeQualifier == 0) &&
+ (UnitInfo->DeviceClaimed == FALSE))
+ {
+ DPRINT("Vendor: '%.24s'\n",
+ InquiryData->VendorId);
+
+ /* Create device objects for disk */
+ Status = DiskClassCreateDeviceObject(DriverObject,
+ RegistryPath,
+ PortDeviceObject,
+ PortNumber,
+ ConfigInfo->DiskCount,
+ PortCapabilities,
+ UnitInfo,
+ InitializationData);
+ if (NT_SUCCESS(Status))
+ {
+ ConfigInfo->DiskCount++;
+ FoundDevice = TRUE;
+ }
+ }
+
+ if (UnitInfo->NextInquiryDataOffset == 0)
+ break;
+
+ UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
+ }
+ }
+
+ ExFreePool(Buffer);
+ ExFreePool(PortCapabilities);
+
+ DPRINT("DiskClassFindDevices() done\n");
+
+ return(FoundDevice);
+}
+
+
+/**********************************************************************
+ * NAME EXPORTED
+ * DiskClassCheckDevice
+ *
+ * DESCRIPTION
+ * This function checks the InquiryData for the correct device
+ * type and qualifier.
+ *
+ * RUN LEVEL
+ * PASSIVE_LEVEL
+ *
+ * ARGUMENTS
+ * InquiryData
+ * Pointer to the inquiry data for the device in question.
+ *
+ * RETURN VALUE
+ * TRUE: A disk device was found.
+ * FALSE: Otherwise.
+ */
- return(STATUS_SUCCESS);
+BOOLEAN STDCALL
+DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
+{
+ return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
+ InquiryData->DeviceType == OPTICAL_DEVICE) &&
+ InquiryData->DeviceTypeQualifier == 0);
}
-static BOOLEAN
-DiskFindDiskDrives(PDEVICE_OBJECT PortDeviceObject,
- ULONG PortNumber)
+/**********************************************************************
+ * NAME EXPORTED
+ * DiskClassCheckReadWrite
+ *
+ * DESCRIPTION
+ * This function checks the given IRP for correct data.
+ *
+ * RUN LEVEL
+ * PASSIVE_LEVEL
+ *
+ * ARGUMENTS
+ * DeviceObject
+ * Pointer to the device.
+ *
+ * Irp
+ * Irp to check.
+ *
+ * RETURN VALUE
+ * STATUS_SUCCESS: The IRP matches the requirements of the given device.
+ * Others: Failure.
+ */
+
+NTSTATUS STDCALL
+DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- DPRINT1("DiskFindDiskDevices() called.\n");
+ PDEVICE_EXTENSION DeviceExtension;
+ PDISK_DATA DiskData;
+
+ DPRINT1("DiskClassCheckReadWrite() called\n");
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+ DiskData = (PDISK_DATA)(DeviceExtension + 1);
+
+ if (DiskData->DriveNotReady == TRUE)
+ {
+ Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
+ IoSetHardErrorOrVerifyDevice(Irp,
+ DeviceObject);
+ return(STATUS_INVALID_PARAMETER);
+ }
- return TRUE;
+ return(STATUS_SUCCESS);
}
-// IDECreateDevice
+
+// DiskClassCreateDeviceObject
//
// DESCRIPTION:
-// Creates a device by calling IoCreateDevice and a sylbolic link for Win32
+// Create the raw device and any partition devices on this drive
//
// RUN LEVEL:
// PASSIVE_LEVEL
//
// ARGUMENTS:
-// IN PDRIVER_OBJECT DriverObject The system supplied driver object
-// OUT PDEVICE_OBJECT *DeviceObject The created device object
-// IN PCONTROLLER_OBJECT ControllerObject The Controller for the device
-// IN BOOLEAN LBASupported Does the drive support LBA addressing?
-// IN BOOLEAN DMASupported Does the drive support DMA?
-// IN int SectorsPerLogCyl Sectors per cylinder
-// IN int SectorsPerLogTrk Sectors per track
-// IN DWORD Offset First valid sector for this device
-// IN DWORD Size Count of valid sectors for this device
+// IN PDRIVER_OBJECT DriverObject The system created driver object
+// IN PCONTROLLER_OBJECT ControllerObject
+// IN PIDE_CONTROLLER_EXTENSION ControllerExtension
+// The IDE controller extension for
+// this device
+// IN int DriveIdx The index of the drive on this
+// controller
+// IN int HarddiskIdx The NT device number for this
+// drive
//
// RETURNS:
-// NTSTATUS
+// TRUE Drive exists and devices were created
+// FALSE no devices were created for this device
//
-#if 0
-NTSTATUS
-IDECreateDevice(IN PDRIVER_OBJECT DriverObject,
- OUT PDEVICE_OBJECT *DeviceObject,
- IN PCONTROLLER_OBJECT ControllerObject,
- IN int UnitNumber,
- IN ULONG DiskNumber,
- IN ULONG PartitionNumber,
- IN PIDE_DRIVE_IDENTIFY DrvParms,
- IN DWORD Offset,
- IN DWORD Size)
+
+static NTSTATUS
+DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath, /* what's this used for? */
+ IN PDEVICE_OBJECT PortDeviceObject,
+ IN ULONG PortNumber,
+ IN ULONG DiskNumber,
+ IN PIO_SCSI_CAPABILITIES Capabilities,
+ IN PSCSI_INQUIRY_DATA InquiryData,
+ IN PCLASS_INIT_DATA InitializationData)
{
- WCHAR NameBuffer[IDE_MAX_NAME_LENGTH];
- WCHAR ArcNameBuffer[IDE_MAX_NAME_LENGTH + 15];
- UNICODE_STRING DeviceName;
- UNICODE_STRING ArcName;
- NTSTATUS RC;
- PIDE_DEVICE_EXTENSION DeviceExtension;
-
- // Create a unicode device name
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING UnicodeDeviceDirName;
+ WCHAR NameBuffer[80];
+ CHAR NameBuffer2[80];
+ PDEVICE_OBJECT DiskDeviceObject;
+ PDEVICE_OBJECT PartitionDeviceObject;
+ PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
+ PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
+ PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
+ HANDLE Handle;
+ PPARTITION_INFORMATION PartitionEntry;
+ PDISK_DATA DiskData;
+ ULONG PartitionNumber;
+ NTSTATUS Status;
+
+ DPRINT("DiskClassCreateDeviceObject() called\n");
+
+ /* Create the harddisk device directory */
swprintf(NameBuffer,
- L"\\Device\\Harddisk%d\\Partition%d",
- DiskNumber,
- PartitionNumber);
- RtlInitUnicodeString(&DeviceName,
- NameBuffer);
-
- // Create the device
- RC = IoCreateDevice(DriverObject, sizeof(IDE_DEVICE_EXTENSION),
- &DeviceName, FILE_DEVICE_DISK, 0, TRUE, DeviceObject);
- if (!NT_SUCCESS(RC))
+ L"\\Device\\Harddisk%lu",
+ DiskNumber);
+ RtlInitUnicodeString(&UnicodeDeviceDirName,
+ NameBuffer);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &UnicodeDeviceDirName,
+ 0,
+ NULL,
+ NULL);
+ Status = ZwCreateDirectoryObject(&Handle,
+ 0,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("Could not create device dir object\n");
+ return(Status);
+ }
+
+ /* Claim the disk device */
+ Status = ScsiClassClaimDevice(PortDeviceObject,
+ InquiryData,
+ FALSE,
+ &PortDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("Could not claim disk device\n");
+
+ ZwMakeTemporaryObject(Handle);
+ ZwClose(Handle);
+
+ return(Status);
+ }
+
+ /* Create disk device (Partition 0) */
+ sprintf(NameBuffer2,
+ "\\Device\\Harddisk%lu\\Partition0",
+ DiskNumber);
+
+ Status = ScsiClassCreateDeviceObject(DriverObject,
+ NameBuffer2,
+ NULL,
+ &DiskDeviceObject,
+ InitializationData);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
+
+ /* Release (unclaim) the disk */
+ ScsiClassClaimDevice(PortDeviceObject,
+ InquiryData,
+ TRUE,
+ NULL);
+
+ /* Delete the harddisk device directory */
+ ZwMakeTemporaryObject(Handle);
+ ZwClose(Handle);
+
+ return(Status);
+ }
+
+ DiskDeviceObject->Flags |= DO_DIRECT_IO;
+ if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
+ {
+ DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
+ }
+ DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
+
+ if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
{
- DPRINT("IoCreateDevice call failed\n",0);
- return RC;
+ DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
}
- // Set the buffering strategy here...
- (*DeviceObject)->Flags |= DO_DIRECT_IO;
- (*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT;
-
- // Fill out Device extension data
- DeviceExtension = (PIDE_DEVICE_EXTENSION) (*DeviceObject)->DeviceExtension;
- DeviceExtension->DeviceObject = (*DeviceObject);
- DeviceExtension->ControllerObject = ControllerObject;
- DeviceExtension->UnitNumber = UnitNumber;
- DeviceExtension->LBASupported =
- (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0;
- DeviceExtension->DMASupported =
- (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0;
- // FIXME: deal with bizarre sector sizes
- DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */;
- DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads *
- DrvParms->SectorsPerTrack;
- DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack;
- DeviceExtension->LogicalHeads = DrvParms->LogicalHeads;
- DeviceExtension->Offset = Offset;
- DeviceExtension->Size = Size;
- DPRINT("%wZ: offset %d size %d \n",
- &DeviceName,
- DeviceExtension->Offset,
- DeviceExtension->Size);
-
- // Initialize the DPC object here
- IoInitializeDpcRequest(*DeviceObject, IDEDpcForIsr);
-
- if (PartitionNumber != 0)
+ DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
+ DiskDeviceExtension->LockCount = 0;
+ DiskDeviceExtension->DeviceNumber = DiskNumber;
+ DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
+ DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
+
+ /* FIXME: Not yet! Will cause pointer corruption! */
+// DiskDeviceExtension->PortCapabilities = PortCapabilities;
+
+ DiskDeviceExtension->StartingOffset.QuadPart = 0;
+ DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
+ DiskDeviceExtension->PathId = InquiryData->PathId;
+ DiskDeviceExtension->TargetId = InquiryData->TargetId;
+ DiskDeviceExtension->Lun = InquiryData->Lun;
+
+ /* zero-out disk data */
+ DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
+ RtlZeroMemory(DiskData,
+ sizeof(DISK_DATA));
+
+ /* Get disk geometry */
+ DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
+ sizeof(DISK_GEOMETRY));
+ if (DiskDeviceExtension->DiskGeometry == NULL)
{
- DbgPrint("%wZ %dMB\n", &DeviceName, Size / 2048);
+ DPRINT1("Failed to allocate geometry buffer!\n");
+
+ IoDeleteDevice(DiskDeviceObject);
+
+ /* Release (unclaim) the disk */
+ ScsiClassClaimDevice(PortDeviceObject,
+ InquiryData,
+ TRUE,
+ NULL);
+
+ /* Delete the harddisk device directory */
+ ZwMakeTemporaryObject(Handle);
+ ZwClose(Handle);
+
+ return(STATUS_INSUFFICIENT_RESOURCES);
}
- /* assign arc name */
- if (PartitionNumber == 0)
+ /* Read the drive's capacity */
+ Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
+ if (!NT_SUCCESS(Status) &&
+ (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
{
- swprintf(ArcNameBuffer,
- L"\\ArcName\\multi(0)disk(0)rdisk(%d)",
- DiskNumber);
+ DPRINT1("Failed to retrieve drive capacity!\n");
+ return(STATUS_SUCCESS);
}
else
{
- swprintf(ArcNameBuffer,
- L"\\ArcName\\multi(0)disk(0)rdisk(%d)partition(%d)",
- DiskNumber,
- PartitionNumber);
+ /* Clear the verify flag for removable media drives. */
+ DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
}
- RtlInitUnicodeString (&ArcName,
- ArcNameBuffer);
- DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
- RC = IoAssignArcName (&ArcName,
- &DeviceName);
- if (!NT_SUCCESS(RC))
+
+ DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
+
+ /* Read partition table */
+ Status = IoReadPartitionTable(DiskDeviceObject,
+ DiskDeviceExtension->DiskGeometry->BytesPerSector,
+ TRUE,
+ &PartitionList);
+
+ DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
+
+ if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
+ DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
- DPRINT("IoAssignArcName (%wZ) failed (Status %x)\n",
- &ArcName, RC);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Drive is not ready. */
+ DPRINT1("Drive not ready\n");
+ DiskData->DriveNotReady = TRUE;
+ }
+ else
+ {
+ ExFreePool(PartitionList);
+ }
+
+ /* Allocate a partition list for a single entry. */
+ PartitionList = ExAllocatePool(NonPagedPool,
+ sizeof(DRIVE_LAYOUT_INFORMATION));
+ if (PartitionList != NULL)
+ {
+ RtlZeroMemory(PartitionList,
+ sizeof(DRIVE_LAYOUT_INFORMATION));
+ PartitionList->PartitionCount = 1;
+
+ Status = STATUS_SUCCESS;
+ }
}
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("Read partition table!\n");
+
+ DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
+
+ for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
+ {
+ PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
+
+ DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
+ PartitionNumber,
+ PartitionEntry->PartitionNumber,
+ PartitionEntry->BootIndicator,
+ PartitionEntry->PartitionType,
+ PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
+ PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
+
+ /* Create partition device object */
+ sprintf(NameBuffer2,
+ "\\Device\\Harddisk%lu\\Partition%lu",
+ DiskNumber,
+ PartitionNumber + 1);
+
+ Status = ScsiClassCreateDeviceObject(DriverObject,
+ NameBuffer2,
+ DiskDeviceObject,
+ &PartitionDeviceObject,
+ InitializationData);
+ DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
+ if (NT_SUCCESS(Status))
+ {
+ PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
+ PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
+ PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
+ PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
+
+ PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
+ PartitionDeviceExtension->LockCount = 0;
+ PartitionDeviceExtension->DeviceNumber = DiskNumber;
+ PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
+ PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
+ PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
+
+ /* FIXME: Not yet! Will cause pointer corruption! */
+// PartitionDeviceExtension->PortCapabilities = PortCapabilities;
+
+ PartitionDeviceExtension->StartingOffset.QuadPart =
+ PartitionEntry->StartingOffset.QuadPart;
+ PartitionDeviceExtension->PartitionLength.QuadPart =
+ PartitionEntry->PartitionLength.QuadPart;
+ PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
+ PartitionDeviceExtension->PathId = InquiryData->PathId;
+ PartitionDeviceExtension->TargetId = InquiryData->TargetId;
+ PartitionDeviceExtension->Lun = InquiryData->Lun;
+ PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
+
+ DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
+ DiskData->PartitionType = PartitionEntry->PartitionType;
+ DiskData->PartitionNumber = PartitionNumber + 1;
+ DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
+ DiskData->BootIndicator = PartitionEntry->BootIndicator;
+ DiskData->DriveNotReady = FALSE;
+ }
+ else
+ {
+ DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
+
+ break;
+ }
+ }
+
+
+ }
+
+ if (PartitionList != NULL)
+ ExFreePool(PartitionList);
- return RC;
+ DPRINT("DiskClassCreateDeviceObjects() done\n");
+
+ return(STATUS_SUCCESS);
}
-#endif
-// IDEDispatchDeviceControl
+
+// DiskClassDeviceControl
//
// DESCRIPTION:
// Answer requests for device control calls
// RETURNS:
// NTSTATUS
//
-#if 0
-static NTSTATUS STDCALL
-IDEDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+
+NTSTATUS STDCALL
+DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- NTSTATUS RC;
- ULONG ControlCode, InputLength, OutputLength;
- PIO_STACK_LOCATION IrpStack;
- PIDE_DEVICE_EXTENSION DeviceExtension;
+ PDEVICE_EXTENSION DeviceExtension;
+ PIO_STACK_LOCATION IrpStack;
+ ULONG ControlCode, InputLength, OutputLength;
+ PDISK_DATA DiskData;
+ ULONG Information;
+ NTSTATUS Status;
+
+ DPRINT("DiskClassDeviceControl() called!\n");
- RC = STATUS_SUCCESS;
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ Information = 0;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
- DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+ DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ DiskData = (PDISK_DATA)(DeviceExtension + 1);
- // A huge switch statement in a Windows program?! who would have thought?
- switch (ControlCode)
+ /* A huge switch statement in a Windows program?! who would have thought? */
+ switch (ControlCode)
{
- case IOCTL_DISK_GET_DRIVE_GEOMETRY:
- if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
- {
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- }
- else
- {
- PDISK_GEOMETRY Geometry;
-
- Geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
- Geometry->MediaType = FixedMedia;
- // FIXME: should report for RawDevice even on partition
- Geometry->Cylinders.QuadPart = DeviceExtension->Size /
- DeviceExtension->SectorsPerLogCyl;
- Geometry->TracksPerCylinder = DeviceExtension->SectorsPerLogTrk /
- DeviceExtension->SectorsPerLogCyl;
- Geometry->SectorsPerTrack = DeviceExtension->SectorsPerLogTrk;
- Geometry->BytesPerSector = DeviceExtension->BytesPerSector;
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
- }
- break;
-
- case IOCTL_DISK_GET_PARTITION_INFO:
- case IOCTL_DISK_SET_PARTITION_INFO:
- case IOCTL_DISK_GET_DRIVE_LAYOUT:
- case IOCTL_DISK_SET_DRIVE_LAYOUT:
- 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_HISTOGRAM_DATA:
- case IOCTL_DISK_HISTOGRAM_RESET:
- case IOCTL_DISK_REQUEST_STRUCTURE:
- case IOCTL_DISK_REQUEST_DATA:
-
- // If we get here, something went wrong. inform the requestor
- default:
- RC = STATUS_INVALID_DEVICE_REQUEST;
- Irp->IoStatus.Status = RC;
- Irp->IoStatus.Information = 0;
- break;
+ case IOCTL_DISK_GET_DRIVE_GEOMETRY:
+ DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
+ if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else if (DeviceExtension->DiskGeometry == NULL)
+ {
+ DPRINT1("No disk geometry available!\n");
+ Status = STATUS_NO_SUCH_DEVICE;
+ }
+ else
+ {
+ PDISK_GEOMETRY Geometry;
+
+ Geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
+ RtlMoveMemory(Geometry,
+ 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 (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
+ sizeof(PARTITION_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else if (DiskData->PartitionNumber == 0)
+ {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ }
+ else
+ {
+ PPARTITION_INFORMATION PartitionInfo;
+
+ PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
+
+ PartitionInfo->PartitionType = DiskData->PartitionType;
+ PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
+ PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
+ PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
+ PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
+ PartitionInfo->BootIndicator = DiskData->BootIndicator;
+ PartitionInfo->RewritePartition = FALSE;
+ PartitionInfo->RecognizedPartition =
+ IsRecognizedPartition(DiskData->PartitionType);
+
+ Status = STATUS_SUCCESS;
+ Information = sizeof(PARTITION_INFORMATION);
+ }
+ break;
+
+ case IOCTL_DISK_SET_PARTITION_INFO:
+ DPRINT1("Unhandled IOCTL_DISK_SET_PARTITION_INFO\n");
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ Information = 0;
+ break;
+
+ case IOCTL_DISK_GET_DRIVE_LAYOUT:
+ if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
+ sizeof(DRIVE_LAYOUT_INFORMATION))
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ PDRIVE_LAYOUT_INFORMATION PartitionList;
+
+ Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
+ DeviceExtension->DiskGeometry->BytesPerSector,
+ FALSE,
+ &PartitionList);
+ if (NT_SUCCESS(Status))
+ {
+ ULONG BufferSize;
+
+ BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
+ PartitionEntry[0]);
+ BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);
+
+ if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
+ PartitionList,
+ BufferSize);
+ Status = STATUS_SUCCESS;
+ Information = BufferSize;
+ }
+ ExFreePool(PartitionList);
+ }
+ }
+ break;
+
+ case IOCTL_DISK_SET_DRIVE_LAYOUT:
+ 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_HISTOGRAM_DATA:
+ case IOCTL_DISK_HISTOGRAM_RESET:
+ case IOCTL_DISK_REQUEST_STRUCTURE:
+ case IOCTL_DISK_REQUEST_DATA:
+
+ /* If we get here, something went wrong. inform the requestor */
+ default:
+ DPRINT1("Unhandled control code: %lx\n", ControlCode);
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ Information = 0;
+ break;
}
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = Information;
+ IoCompleteRequest(Irp,
+ IO_NO_INCREMENT);
+
+ return(Status);
+}
+
+
+/**********************************************************************
+ * NAME EXPORTED
+ * DiskClassShutdownFlush
+ *
+ * DESCRIPTION
+ * Answer requests for shutdown and flush calls.
+ *
+ * RUN LEVEL
+ * PASSIVE_LEVEL
+ *
+ * ARGUMENTS
+ * DeviceObject
+ * Pointer to the device.
+ *
+ * Irp
+ * Pointer to the IRP
+ *
+ * RETURN VALUE
+ * Status
+ */
+
+NTSTATUS STDCALL
+DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("DiskClassShutdownFlush() called!\n");
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return RC;
+ return(STATUS_SUCCESS);
}
-#endif
/* EOF */