📄 disk.c
字号:
/*
* PROJECT: ReactOS Storage Stack
* LICENSE: DDK - see license.txt in the root dir
* FILE: drivers/storage/disk/disk.c
* PURPOSE: Disk class driver
* PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK
*/
#include <ntddk.h>
#include <ntdddisk.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <mountdev.h>
#include <mountmgr.h>
#include <include/class2.h>
#include <stdio.h>
//#define NDEBUG
#include <debug.h>
#define IO_WRITE_CACHE_ENABLED ((NTSTATUS)0x80040020L)
#define IO_WRITE_CACHE_DISABLED ((NTSTATUS)0x80040022L)
#ifdef POOL_TAGGING
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'DscS')
#endif
//
// Disk device data
//
typedef struct _DISK_DATA {
//
// Partition chain
//
PDEVICE_EXTENSION NextPartition;
//
// Disk signature (from MBR)
//
ULONG Signature;
//
// MBR checksum
//
ULONG MbrCheckSum;
//
// Number of hidden sectors for BPB.
//
ULONG HiddenSectors;
//
// Partition number of this device object
//
// This field is set during driver initialization or when the partition
// is created to identify a parition to the system.
//
ULONG PartitionNumber;
//
// This field is the ordinal of a partition as it appears on a disk.
//
ULONG PartitionOrdinal;
//
// Partition type of this device object
//
// This field is set by:
//
// 1) Initially set according to the partition list entry partition
// type returned by IoReadPartitionTable.
//
// 2) Subsequently set by the IOCTL_DISK_SET_PARTITION_INFORMATION
// I/O control function when IoSetPartitionInformation function
// successfully updates the partition type on the disk.
//
UCHAR PartitionType;
//
// Boot indicator - indicates whether this partition is a bootable (active)
// partition for this device
//
// This field is set according to the partition list entry boot indicator
// returned by IoReadPartitionTable.
//
BOOLEAN BootIndicator;
//
// DriveNotReady - inidicates that the this device is currenly not ready
// beacasue there is no media in the device.
//
BOOLEAN DriveNotReady;
} DISK_DATA, *PDISK_DATA;
//
// Define a general structure of identfing disk controllers with bad
// hardware.
//
typedef struct _BAD_CONTROLLER_INFORMATION {
PCHAR InquiryString;
BOOLEAN DisableTaggedQueuing;
BOOLEAN DisableSynchronousTransfers;
BOOLEAN DisableDisconnects;
BOOLEAN DisableWriteCache;
}BAD_CONTROLLER_INFORMATION, *PBAD_CONTROLLER_INFORMATION;
BAD_CONTROLLER_INFORMATION const ScsiDiskBadControllers[] = {
{ "TOSHIBA MK538FB 60", TRUE, FALSE, FALSE, FALSE },
{ "CONNER CP3500", FALSE, TRUE, FALSE, FALSE },
{ "OLIVETTICP3500", FALSE, TRUE, FALSE, FALSE },
{ "SyQuest SQ5110 CHC", TRUE, TRUE, FALSE, FALSE },
{ "SEAGATE ST41601N 0102", FALSE, TRUE, FALSE, FALSE },
{ "SEAGATE ST3655N", FALSE, FALSE, FALSE, TRUE },
{ "SEAGATE ST3390N", FALSE, FALSE, FALSE, TRUE },
{ "SEAGATE ST12550N", FALSE, FALSE, FALSE, TRUE },
{ "SEAGATE ST32430N", FALSE, FALSE, FALSE, TRUE },
{ "SEAGATE ST31230N", FALSE, FALSE, FALSE, TRUE },
{ "SEAGATE ST15230N", FALSE, FALSE, FALSE, TRUE },
{ "FUJITSU M2652S-512", TRUE, FALSE, FALSE, FALSE },
{ "MAXTOR MXT-540SL I1.2", TRUE, FALSE, FALSE, FALSE },
{ "COMPAQ PD-1", FALSE, TRUE, FALSE, FALSE }
};
#define NUMBER_OF_BAD_CONTROLLERS (sizeof(ScsiDiskBadControllers) / sizeof(BAD_CONTROLLER_INFORMATION))
#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA)
#define MODE_DATA_SIZE 192
#define VALUE_BUFFER_SIZE 2048
#define SCSI_DISK_TIMEOUT 10
#define PARTITION0_LIST_SIZE 4
NTSTATUS
STDCALL
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
BOOLEAN
STDCALL
ScsiDiskDeviceVerification(
IN PINQUIRYDATA InquiryData
);
BOOLEAN
STDCALL
FindScsiDisks(
IN PDRIVER_OBJECT DriveObject,
IN PUNICODE_STRING RegistryPath,
IN PCLASS_INIT_DATA InitializationData,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber
);
NTSTATUS
STDCALL
ScsiDiskCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
STDCALL
ScsiDiskReadWriteVerification(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
STDCALL
ScsiDiskDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
STDCALL
ScsiDiskProcessError(
PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
NTSTATUS *Status,
BOOLEAN *Retry
);
NTSTATUS
STDCALL
ScsiDiskShutdownFlush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
STDCALL
DisableWriteCache(
IN PDEVICE_OBJECT DeviceObject,
IN PSCSI_INQUIRY_DATA LunInfo
);
BOOLEAN
STDCALL
ScsiDiskModeSelect(
IN PDEVICE_OBJECT DeviceObject,
IN PCHAR ModeSelectBuffer,
IN ULONG Length,
IN BOOLEAN SavePage
);
BOOLEAN
STDCALL
IsFloppyDevice(
IN PDEVICE_OBJECT DeviceObject
);
BOOLEAN
STDCALL
CalculateMbrCheckSum(
IN PDEVICE_EXTENSION DeviceExtension,
OUT PULONG Checksum
);
BOOLEAN
STDCALL
EnumerateBusKey(
IN PDEVICE_EXTENSION DeviceExtension,
HANDLE BusKey,
PULONG DiskNumber
);
VOID
STDCALL
UpdateGeometry(
IN PDEVICE_EXTENSION DeviceExtension
);
NTSTATUS
STDCALL
UpdateRemovableGeometry (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
STDCALL
CreateDiskDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN PULONG DeviceCount,
IN PIO_SCSI_CAPABILITIES PortCapabilities,
IN PSCSI_INQUIRY_DATA LunInfo,
IN PCLASS_INIT_DATA InitData
);
VOID
STDCALL
UpdateDeviceObjects(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
STDCALL
ScanForSpecial(
PDEVICE_OBJECT DeviceObject,
PSCSI_INQUIRY_DATA LunInfo,
PIO_SCSI_CAPABILITIES PortCapabilities
);
VOID
STDCALL
ResetScsiBus(
IN PDEVICE_OBJECT DeviceObject
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DriverEntry)
#pragma alloc_text(PAGE, FindScsiDisks)
#pragma alloc_text(PAGE, CreateDiskDeviceObject)
#pragma alloc_text(PAGE, CalculateMbrCheckSum)
#pragma alloc_text(PAGE, EnumerateBusKey)
#pragma alloc_text(PAGE, UpdateGeometry)
#pragma alloc_text(PAGE, IsFloppyDevice)
#pragma alloc_text(PAGE, ScanForSpecial)
#pragma alloc_text(PAGE, ScsiDiskDeviceControl)
#pragma alloc_text(PAGE, ScsiDiskModeSelect)
#endif
NTSTATUS
STDCALL
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine initializes the SCSI hard disk class driver.
Arguments:
DriverObject - Pointer to driver object created by system.
RegistryPath - Pointer to the name of the services node for this driver.
Return Value:
The function value is the final status from the initialization operation.
--*/
{
CLASS_INIT_DATA InitializationData;
//
// Zero InitData
//
RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));
//
// Set sizes
//
InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
InitializationData.DeviceType = FILE_DEVICE_DISK;
InitializationData.DeviceCharacteristics = 0;
//
// Set entry points
//
InitializationData.ClassError = ScsiDiskProcessError;
InitializationData.ClassReadWriteVerification = ScsiDiskReadWriteVerification;
InitializationData.ClassFindDevices = FindScsiDisks;
InitializationData.ClassFindDeviceCallBack = ScsiDiskDeviceVerification;
InitializationData.ClassDeviceControl = ScsiDiskDeviceControl;
InitializationData.ClassShutdownFlush = ScsiDiskShutdownFlush;
InitializationData.ClassCreateClose = NULL;
//
// Call the class init routine
//
return ScsiClassInitialize( DriverObject, RegistryPath, &InitializationData);
} // end DriverEntry()
BOOLEAN
STDCALL
ScsiDiskDeviceVerification(
IN PINQUIRYDATA InquiryData
)
/*++
Routine Description:
This routine checks InquiryData for the correct device type and qualifier.
Arguments:
InquiryData - Pointer to the inquiry data for the device in question.
Return Value:
True is returned if the correct device type is found.
--*/
{
if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
(InquiryData->DeviceType == OPTICAL_DEVICE)) &&
InquiryData->DeviceTypeQualifier == 0) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
STDCALL
FindScsiDisks(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PCLASS_INIT_DATA InitializationData,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber
)
/*++
Routine Description:
This routine gets a port drivers capabilities, obtains the
inquiry data, searches the SCSI bus for the port driver and creates
the device objects for the disks found.
Arguments:
DriverObject - Pointer to driver object created by system.
PortDeviceObject - Device object use to send requests to port driver.
PortNumber - Number for port driver. Used to pass on to
CreateDiskDeviceObjects() and create device objects.
Return Value:
True is returned if one disk was found and successfully created.
--*/
{
PIO_SCSI_CAPABILITIES portCapabilities;
PULONG diskCount;
PCONFIGURATION_INFORMATION configurationInformation;
PCHAR buffer;
PSCSI_INQUIRY_DATA lunInfo;
PSCSI_ADAPTER_BUS_INFO adapterInfo;
PINQUIRYDATA inquiryData;
ULONG scsiBus;
ULONG adapterDisk;
NTSTATUS status;
BOOLEAN foundOne = FALSE;
PAGED_CODE();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -