/*++
Copyright (C) Microsoft Corporation, 1991 - 2010
Module Name:
disk.c
Abstract:
SCSI disk class driver
Environment:
kernel mode only
Notes:
Revision History:
--*/
#define DEBUG_MAIN_SOURCE 1
#include "disk.h"
//
// Now instantiate the GUIDs
//
#include "initguid.h"
#include "ntddstor.h"
#include "ntddvol.h"
#include "ioevent.h"
#ifdef DEBUG_USE_WPP
#include "disk.tmh"
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DiskUnload)
#pragma alloc_text(PAGE, DiskCreateFdo)
#pragma alloc_text(PAGE, DiskDetermineMediaTypes)
#pragma alloc_text(PAGE, DiskModeSelect)
#pragma alloc_text(PAGE, DisableWriteCache)
#pragma alloc_text(PAGE, DiskSetSpecialHacks)
#pragma alloc_text(PAGE, DiskGetCacheInformation)
#pragma alloc_text(PAGE, DiskSetCacheInformation)
#pragma alloc_text(PAGE, DiskLogCacheInformation)
#pragma alloc_text(PAGE, DiskSetInfoExceptionInformation)
#pragma alloc_text(PAGE, DiskGetInfoExceptionInformation)
#pragma alloc_text(PAGE, DiskIoctlGetCacheSetting)
#pragma alloc_text(PAGE, DiskIoctlSetCacheSetting)
#pragma alloc_text(PAGE, DiskIoctlGetLengthInfo)
#pragma alloc_text(PAGE, DiskIoctlGetDriveGeometry)
#pragma alloc_text(PAGE, DiskIoctlGetDriveGeometryEx)
#pragma alloc_text(PAGE, DiskIoctlGetCacheInformation)
#pragma alloc_text(PAGE, DiskIoctlSetCacheInformation)
#pragma alloc_text(PAGE, DiskIoctlGetMediaTypesEx)
#pragma alloc_text(PAGE, DiskIoctlPredictFailure)
#pragma alloc_text(PAGE, DiskIoctlReassignBlocks)
#pragma alloc_text(PAGE, DiskIoctlReassignBlocksEx)
#pragma alloc_text(PAGE, DiskIoctlIsWritable)
#pragma alloc_text(PAGE, DiskIoctlUpdateDriveSize)
#pragma alloc_text(PAGE, DiskIoctlGetVolumeDiskExtents)
#pragma alloc_text(PAGE, DiskIoctlSmartGetVersion)
#pragma alloc_text(PAGE, DiskIoctlSmartReceiveDriveData)
#pragma alloc_text(PAGE, DiskIoctlSmartSendDriveCommand)
#pragma alloc_text(PAGE, DiskIoctlVerifyThread)
#endif
//
// ETW related globals
//
BOOLEAN DiskETWEnabled = FALSE;
BOOLEAN DiskIsPastReinit = FALSE;
const GUID GUID_NULL = { 0 };
#define DiskCompareGuid(_First,_Second) \
(memcmp ((_First),(_Second), sizeof (GUID)))
//
// This macro is used to work around a bug in the definition of
// DISK_CACHE_RETENTION_PRIORITY. The value KeepReadData should be
// assigned 0xf rather than 0x2. Since the interface was already published
// when this was discovered the disk driver has been modified to translate
// between the interface value and the correct scsi value.
//
// 0x2 is turned into 0xf
// 0xf is turned into 0x2 - this ensures that future SCSI defintions can be
// accomodated.
//
#define TRANSLATE_RETENTION_PRIORITY(_x)\
((_x) == 0xf ? 0x2 : \
((_x) == 0x2 ? 0xf : _x) \
)
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS_ADMIN CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_READ_ACCESS)
VOID
DiskDriverReinit(
IN PDRIVER_OBJECT DriverObject,
IN PVOID Nothing,
IN ULONG Count
)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(Nothing);
UNREFERENCED_PARAMETER(Count);
DiskIsPastReinit = TRUE;
}
VOID
DiskBootDriverReinit(
IN PDRIVER_OBJECT DriverObject,
IN PVOID Nothing,
IN ULONG Count
)
{
IoRegisterDriverReinitialization(DriverObject, DiskDriverReinit, NULL);
#if defined(_X86_) || defined(_AMD64_)
DiskDriverReinitialization(DriverObject, Nothing, Count);
#else
UNREFERENCED_PARAMETER(Nothing);
UNREFERENCED_PARAMETER(Count);
#endif
}
NTSTATUS
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 = { 0 };
CLASS_QUERY_WMI_REGINFO_EX_LIST classQueryWmiRegInfoExList = { 0 };
GUID guidQueryRegInfoEx = GUID_CLASSPNP_QUERY_REGINFOEX;
GUID guidSrbSupport = GUID_CLASSPNP_SRB_SUPPORT;
ULONG srbSupport;
NTSTATUS status;
//
// Initializes tracing
//
WPP_INIT_TRACING(DriverObject, RegistryPath);
#if defined(_X86_) || defined(_AMD64_)
//
// Read the information NtDetect squirreled away about the disks in this
// system.
//
DiskSaveDetectInfo(DriverObject);
#endif
InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
//
// Setup sizes and entry points for functional device objects
//
InitializationData.FdoData.DeviceExtensionSize = FUNCTIONAL_EXTENSION_SIZE;
InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK;
InitializationData.FdoData.DeviceCharacteristics = FILE_DEVICE_SECURE_OPEN;
InitializationData.FdoData.ClassInitDevice = DiskInitFdo;
InitializationData.FdoData.ClassStartDevice = DiskStartFdo;
InitializationData.FdoData.ClassStopDevice = DiskStopDevice;
InitializationData.FdoData.ClassRemoveDevice = DiskRemoveDevice;
InitializationData.FdoData.ClassPowerDevice = ClassSpinDownPowerHandler;
InitializationData.FdoData.ClassError = DiskFdoProcessError;
InitializationData.FdoData.ClassReadWriteVerification = DiskReadWriteVerification;
InitializationData.FdoData.ClassDeviceControl = DiskDeviceControl;
InitializationData.FdoData.ClassShutdownFlush = DiskShutdownFlush;
InitializationData.FdoData.ClassCreateClose = NULL;
InitializationData.FdoData.ClassWmiInfo.GuidCount = 7;
InitializationData.FdoData.ClassWmiInfo.GuidRegInfo = DiskWmiFdoGuidList;
InitializationData.FdoData.ClassWmiInfo.ClassQueryWmiRegInfo = DiskFdoQueryWmiRegInfo;
InitializationData.FdoData.ClassWmiInfo.ClassQueryWmiDataBlock = DiskFdoQueryWmiDataBlock;
InitializationData.FdoData.ClassWmiInfo.ClassSetWmiDataBlock = DiskFdoSetWmiDataBlock;
InitializationData.FdoData.ClassWmiInfo.ClassSetWmiDataItem = DiskFdoSetWmiDataItem;
InitializationData.FdoData.ClassWmiInfo.ClassExecuteWmiMethod = DiskFdoExecuteWmiMethod;
InitializationData.FdoData.ClassWmiInfo.ClassWmiFunctionControl = DiskWmiFunctionControl;
InitializationData.ClassAddDevice = DiskAddDevice;
InitializationData.ClassUnload = DiskUnload;
//
// Initialize regregistration data structures
//
DiskInitializeReregistration();
//
// Call the class init routine
//
status = ClassInitialize(DriverObject, RegistryPath, &InitializationData);
if (NT_SUCCESS(status)) {
IoRegisterBootDriverReinitialization(DriverObject,
DiskBootDriverReinit,
NULL);
}
//
// Call class init Ex routine to register a
// PCLASS_QUERY_WMI_REGINFO_EX routine
//
classQueryWmiRegInfoExList.Size = sizeof(CLASS_QUERY_WMI_REGINFO_EX_LIST);
classQueryWmiRegInfoExList.ClassFdoQueryWmiRegInfoEx = DiskFdoQueryWmiRegInfoEx;
(VOID)ClassInitializeEx(DriverObject,
&guidQueryRegInfoEx,
&classQueryWmiRegInfoExList);
//
// Call class init Ex routine to register SRB support
//
srbSupport = CLASS_SRB_SCSI_REQUEST_BLOCK | CLASS_SRB_STORAGE_REQUEST_BLOCK;
if (!NT_SUCCESS(ClassInitializeEx(DriverObject,
&guidSrbSupport,
&srbSupport))) {
//
// Should not fail
//