📄 diskwmi.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
diskwmi.c
Abstract:
SCSI disk class driver - WMI support routines
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include "disk.h"
NTSTATUS
DiskSendFailurePredictIoctl(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PSTORAGE_PREDICT_FAILURE checkFailure
);
NTSTATUS
DiskGetIdentifyInfo(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PBOOLEAN SupportSmart
);
NTSTATUS
DiskDetectFailurePrediction(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PFAILURE_PREDICTION_METHOD FailurePredictCapability
);
NTSTATUS
DiskReadFailurePredictThresholds(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds
);
NTSTATUS
DiskReadSmartLog(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN UCHAR SectorCount,
IN UCHAR LogAddress,
OUT PUCHAR Buffer
);
NTSTATUS
DiskWriteSmartLog(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN UCHAR SectorCount,
IN UCHAR LogAddress,
IN PUCHAR Buffer
);
void DiskReregWorker(
IN PVOID Context
);
//
// WMI reregistration globals
//
// Since it will take too long to do a mode sense on some drive, we
// need a good way to effect the mode sense for the info exceptions
// mode page so that we can determine if SMART is supported and enabled
// for the drive. So the strategy is to do an asynchronous mode sense
// when the device starts and then look at the info exceptions mode
// page within the completion routine. Now within the completion
// routine we cannot call IoWMIRegistrationControl since we are at DPC
// level, so we create a stack of device objects that will be processed
// by a single work item that is fired off only when the stack
// transitions from empty to non empty.
//
WORK_QUEUE_ITEM DiskReregWorkItem;
SINGLE_LIST_ENTRY DiskReregHead;
KSPIN_LOCK DiskReregSpinlock;
LONG DiskReregWorkItems;
GUIDREGINFO DiskWmiFdoGuidList[] =
{
{
WMI_DISK_GEOMETRY_GUID,
1,
0
},
{
WMI_STORAGE_FAILURE_PREDICT_STATUS_GUID,
1,
WMIREG_FLAG_EXPENSIVE
},
{
WMI_STORAGE_FAILURE_PREDICT_DATA_GUID,
1,
WMIREG_FLAG_EXPENSIVE
},
{
WMI_STORAGE_FAILURE_PREDICT_FUNCTION_GUID,
1,
WMIREG_FLAG_EXPENSIVE
},
{
WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID,
1,
WMIREG_FLAG_EVENT_ONLY_GUID
},
{
WMI_STORAGE_FAILURE_PREDICT_THRESHOLDS_GUID,
1,
WMIREG_FLAG_EXPENSIVE
},
{
WMI_STORAGE_SCSI_INFO_EXCEPTIONS_GUID,
1,
0
},
};
GUID DiskPredictFailureEventGuid = WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID;
#define DiskGeometryGuid 0
#define SmartStatusGuid 1
#define SmartDataGuid 2
#define SmartPerformFunction 3
#define AllowDisallowPerformanceHit 1
#define EnableDisableHardwareFailurePrediction 2
#define EnableDisableFailurePredictionPolling 3
#define GetFailurePredictionCapability 4
#define EnableOfflineDiags 5
#define SmartEventGuid 4
#define SmartThresholdsGuid 5
#define ScsiInfoExceptionsGuid 6
#if 0
//
// Enable this to add WMI support for PDOs
GUIDREGINFO DiskWmiPdoGuidList[] =
{
{
// {25007F51-57C2-11d1-A528-00A0C9062910}
{ 0x25007f52, 0x57c2, 0x11d1,
{ 0xa5, 0x28, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0x10 } },
0
},
};
ULONG DiskDummyData[4] = { 1, 2, 3, 4};
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DiskWmiFunctionControl)
#pragma alloc_text(PAGE, DiskFdoQueryWmiRegInfo)
#pragma alloc_text(PAGE, DiskFdoQueryWmiDataBlock)
#pragma alloc_text(PAGE, DiskFdoSetWmiDataBlock)
#pragma alloc_text(PAGE, DiskFdoSetWmiDataItem)
#pragma alloc_text(PAGE, DiskFdoExecuteWmiMethod)
#pragma alloc_text(PAGE, DiskDetectFailurePrediction)
#pragma alloc_text(PAGE, DiskEnableDisableFailurePrediction)
#pragma alloc_text(PAGE, DiskEnableDisableFailurePredictPolling)
#pragma alloc_text(PAGE, DiskReadFailurePredictStatus)
#pragma alloc_text(PAGE, DiskReadFailurePredictData)
#pragma alloc_text(PAGE, DiskReadFailurePredictThresholds)
#pragma alloc_text(PAGE, DiskGetIdentifyInfo)
#pragma alloc_text(PAGE, DiskReadSmartLog)
#pragma alloc_text(PAGE, DiskWriteSmartLog)
#pragma alloc_text(PAGE, DiskPerformSmartCommand)
#pragma alloc_text(PAGE, DiskSendFailurePredictIoctl)
#pragma alloc_text(PAGE, DiskReregWorker)
#pragma alloc_text(PAGE, DiskInitializeReregistration)
#endif
//
// SMART/IDE specific routines
//
// Read SMART data attributes.
// SrbControl should be sizeof(SRB_IO_CONTROL) +
// (sizeof(SENDCMDINPARAMS)-1) +
// READ_ATTRIBUTE_BUFFER_SIZE
// Attribute data returned at &SendCmdOutParams->bBuffer[0]
//
#define DiskReadSmartData(FdoExtension, \
SrbControl, \
BufferSize) \
DiskPerformSmartCommand(FdoExtension, \
IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS, \
SMART_CMD, \
READ_ATTRIBUTES, \
0, \
0, \
(SrbControl), \
(BufferSize))
//
// Read SMART data thresholds.
// SrbControl should be sizeof(SRB_IO_CONTROL) +
// (sizeof(SENDCMDINPARAMS)-1) +
// READ_THRESHOLD_BUFFER_SIZE
// Attribute data returned at &SendCmdOutParams->bBuffer[0]
//
#define DiskReadSmartThresholds(FdoExtension, \
SrbControl, \
BufferSize) \
DiskPerformSmartCommand(FdoExtension, \
IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS, \
SMART_CMD, \
READ_THRESHOLDS, \
0, \
0, \
(SrbControl), \
(BufferSize))
//
// Read SMART status
// SrbControl should be sizeof(SRB_IO_CONTROL) +
// (sizeof(SENDCMDINPARAMS)-1) +
// sizeof(IDEREGS)
// Failure predicted if cmdOutParameters[3] == 0xf4 and [4] == 0x2c
//
#define DiskReadSmartStatus(FdoExtension, \
SrbControl, \
BufferSize) \
DiskPerformSmartCommand(FdoExtension, \
IOCTL_SCSI_MINIPORT_RETURN_STATUS, \
SMART_CMD, \
RETURN_SMART_STATUS, \
0, \
0, \
(SrbControl), \
(BufferSize))
//
// Read disks IDENTIFY data
// SrbControl should be sizeof(SRB_IO_CONTROL) +
// (sizeof(SENDCMDINPARAMS)-1) +
// sizeof(IDENTIFY_BUFFER_SIZE)
// Identify data returned at &cmdOutParams.bBuffer[0]
//
#define DiskGetIdentifyData(FdoExtension, \
SrbControl, \
BufferSize) \
DiskPerformSmartCommand(FdoExtension, \
IOCTL_SCSI_MINIPORT_IDENTIFY, \
ID_CMD, \
0, \
0, \
0, \
(SrbControl), \
(BufferSize))
//
// Enable SMART
//
_inline NTSTATUS
DiskEnableSmart(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
)
{
UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)];
ULONG bufferSize = sizeof(srbControl);
return DiskPerformSmartCommand(FdoExtension,
IOCTL_SCSI_MINIPORT_ENABLE_SMART,
SMART_CMD,
ENABLE_SMART,
0,
0,
(PSRB_IO_CONTROL)srbControl,
&bufferSize);
}
//
// Disable SMART
//
_inline NTSTATUS
DiskDisableSmart(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
)
{
UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)];
ULONG bufferSize = sizeof(srbControl);
return DiskPerformSmartCommand(FdoExtension,
IOCTL_SCSI_MINIPORT_DISABLE_SMART,
SMART_CMD,
DISABLE_SMART,
0,
0,
(PSRB_IO_CONTROL)srbControl,
&bufferSize);
}
//
// Enable Attribute Autosave
//
_inline NTSTATUS
DiskEnableSmartAttributeAutosave(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
)
{
UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)];
ULONG bufferSize = sizeof(srbControl);
return DiskPerformSmartCommand(FdoExtension,
IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE,
SMART_CMD,
ENABLE_DISABLE_AUTOSAVE,
0xf1,
0,
(PSRB_IO_CONTROL)srbControl,
&bufferSize);
}
//
// Disable Attribute Autosave
//
_inline NTSTATUS
DiskDisableSmartAttributeAutosave(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
)
{
UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)];
ULONG bufferSize = sizeof(srbControl);
return DiskPerformSmartCommand(FdoExtension,
IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE,
SMART_CMD,
ENABLE_DISABLE_AUTOSAVE,
0x00,
0,
(PSRB_IO_CONTROL)srbControl,
&bufferSize);
}
//
// Initialize execution of SMART online diagnostics
//
_inline NTSTATUS
DiskExecuteSmartDiagnostics(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
UCHAR Subcommand
)
{
UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)];
ULONG bufferSize = sizeof(srbControl);
return DiskPerformSmartCommand(FdoExtension,
IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS,
SMART_CMD,
EXECUTE_OFFLINE_DIAGS,
0,
Subcommand,
(PSRB_IO_CONTROL)srbControl,
&bufferSize);
}
NTSTATUS
DiskReadSmartLog(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN UCHAR SectorCount,
IN UCHAR LogAddress,
OUT PUCHAR Buffer
)
{
PSRB_IO_CONTROL srbControl;
NTSTATUS status;
PSENDCMDOUTPARAMS sendCmdOutParams;
ULONG logSize, bufferSize;
PAGED_CODE();
logSize = SectorCount * SMART_LOG_SECTOR_SIZE;
bufferSize = sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1 +
logSize;
srbControl = ExAllocatePoolWithTag(NonPagedPool,
bufferSize,
DISK_TAG_SMART);
if (srbControl != NULL)
{
status = DiskPerformSmartCommand(FdoExtension,
IOCTL_SCSI_MINIPORT_READ_SMART_LOG,
SMART_CMD,
SMART_READ_LOG,
SectorCount,
LogAddress,
srbControl,
&bufferSize);
if (NT_SUCCESS(status))
{
sendCmdOutParams = (PSENDCMDOUTPARAMS)((PUCHAR)srbControl +
sizeof(SRB_IO_CONTROL));
RtlCopyMemory(Buffer,
&sendCmdOutParams->bBuffer[0],
logSize);
}
ExFreePool(srbControl);
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
return(status);
}
NTSTATUS
DiskWriteSmartLog(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN UCHAR SectorCount,
IN UCHAR LogAddress,
IN PUCHAR Buffer
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -