1*3088717bSVictor Perevertkin /*++
2*3088717bSVictor Perevertkin
3*3088717bSVictor Perevertkin Copyright (C) Microsoft Corporation, 1991 - 2010
4*3088717bSVictor Perevertkin
5*3088717bSVictor Perevertkin Module Name:
6*3088717bSVictor Perevertkin
7*3088717bSVictor Perevertkin diskwmi.c
8*3088717bSVictor Perevertkin
9*3088717bSVictor Perevertkin Abstract:
10*3088717bSVictor Perevertkin
11*3088717bSVictor Perevertkin SCSI disk class driver - WMI support routines
12*3088717bSVictor Perevertkin
13*3088717bSVictor Perevertkin Environment:
14*3088717bSVictor Perevertkin
15*3088717bSVictor Perevertkin kernel mode only
16*3088717bSVictor Perevertkin
17*3088717bSVictor Perevertkin Notes:
18*3088717bSVictor Perevertkin
19*3088717bSVictor Perevertkin Revision History:
20*3088717bSVictor Perevertkin
21*3088717bSVictor Perevertkin --*/
22*3088717bSVictor Perevertkin
23*3088717bSVictor Perevertkin #include "disk.h"
24*3088717bSVictor Perevertkin
25*3088717bSVictor Perevertkin #ifdef DEBUG_USE_WPP
26*3088717bSVictor Perevertkin #include "diskwmi.tmh"
27*3088717bSVictor Perevertkin #endif
28*3088717bSVictor Perevertkin
29*3088717bSVictor Perevertkin NTSTATUS
30*3088717bSVictor Perevertkin DiskSendFailurePredictIoctl(
31*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
32*3088717bSVictor Perevertkin PSTORAGE_PREDICT_FAILURE checkFailure
33*3088717bSVictor Perevertkin );
34*3088717bSVictor Perevertkin
35*3088717bSVictor Perevertkin NTSTATUS
36*3088717bSVictor Perevertkin DiskGetIdentifyInfo(
37*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
38*3088717bSVictor Perevertkin PBOOLEAN SupportSmart
39*3088717bSVictor Perevertkin );
40*3088717bSVictor Perevertkin
41*3088717bSVictor Perevertkin NTSTATUS
42*3088717bSVictor Perevertkin DiskDetectFailurePrediction(
43*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
44*3088717bSVictor Perevertkin PFAILURE_PREDICTION_METHOD FailurePredictCapability,
45*3088717bSVictor Perevertkin BOOLEAN ScsiAddressAvailable
46*3088717bSVictor Perevertkin );
47*3088717bSVictor Perevertkin
48*3088717bSVictor Perevertkin NTSTATUS
49*3088717bSVictor Perevertkin DiskReadFailurePredictThresholds(
50*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
51*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds
52*3088717bSVictor Perevertkin );
53*3088717bSVictor Perevertkin
54*3088717bSVictor Perevertkin NTSTATUS
55*3088717bSVictor Perevertkin DiskReadSmartLog(
56*3088717bSVictor Perevertkin IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
57*3088717bSVictor Perevertkin IN UCHAR SectorCount,
58*3088717bSVictor Perevertkin IN UCHAR LogAddress,
59*3088717bSVictor Perevertkin OUT PUCHAR Buffer
60*3088717bSVictor Perevertkin );
61*3088717bSVictor Perevertkin
62*3088717bSVictor Perevertkin NTSTATUS
63*3088717bSVictor Perevertkin DiskWriteSmartLog(
64*3088717bSVictor Perevertkin IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
65*3088717bSVictor Perevertkin IN UCHAR SectorCount,
66*3088717bSVictor Perevertkin IN UCHAR LogAddress,
67*3088717bSVictor Perevertkin IN PUCHAR Buffer
68*3088717bSVictor Perevertkin );
69*3088717bSVictor Perevertkin
70*3088717bSVictor Perevertkin IO_WORKITEM_ROUTINE DiskReregWorker;
71*3088717bSVictor Perevertkin
72*3088717bSVictor Perevertkin IO_COMPLETION_ROUTINE DiskInfoExceptionComplete;
73*3088717bSVictor Perevertkin
74*3088717bSVictor Perevertkin //
75*3088717bSVictor Perevertkin // WMI reregistration globals
76*3088717bSVictor Perevertkin //
77*3088717bSVictor Perevertkin // Since it will take too long to do a mode sense on some drive, we
78*3088717bSVictor Perevertkin // need a good way to effect the mode sense for the info exceptions
79*3088717bSVictor Perevertkin // mode page so that we can determine if SMART is supported and enabled
80*3088717bSVictor Perevertkin // for the drive. So the strategy is to do an asynchronous mode sense
81*3088717bSVictor Perevertkin // when the device starts and then look at the info exceptions mode
82*3088717bSVictor Perevertkin // page within the completion routine. Now within the completion
83*3088717bSVictor Perevertkin // routine we cannot call IoWMIRegistrationControl since we are at DPC
84*3088717bSVictor Perevertkin // level, so we create a stack of device objects that will be processed
85*3088717bSVictor Perevertkin // by a single work item that is fired off only when the stack
86*3088717bSVictor Perevertkin // transitions from empty to non empty.
87*3088717bSVictor Perevertkin //
88*3088717bSVictor Perevertkin SINGLE_LIST_ENTRY DiskReregHead;
89*3088717bSVictor Perevertkin KSPIN_LOCK DiskReregSpinlock;
90*3088717bSVictor Perevertkin LONG DiskReregWorkItems;
91*3088717bSVictor Perevertkin
92*3088717bSVictor Perevertkin GUIDREGINFO DiskWmiFdoGuidList[] =
93*3088717bSVictor Perevertkin {
94*3088717bSVictor Perevertkin {
95*3088717bSVictor Perevertkin WMI_DISK_GEOMETRY_GUID,
96*3088717bSVictor Perevertkin 1,
97*3088717bSVictor Perevertkin 0
98*3088717bSVictor Perevertkin },
99*3088717bSVictor Perevertkin
100*3088717bSVictor Perevertkin {
101*3088717bSVictor Perevertkin WMI_STORAGE_FAILURE_PREDICT_STATUS_GUID,
102*3088717bSVictor Perevertkin 1,
103*3088717bSVictor Perevertkin WMIREG_FLAG_EXPENSIVE
104*3088717bSVictor Perevertkin },
105*3088717bSVictor Perevertkin
106*3088717bSVictor Perevertkin {
107*3088717bSVictor Perevertkin WMI_STORAGE_FAILURE_PREDICT_DATA_GUID,
108*3088717bSVictor Perevertkin 1,
109*3088717bSVictor Perevertkin WMIREG_FLAG_EXPENSIVE
110*3088717bSVictor Perevertkin },
111*3088717bSVictor Perevertkin
112*3088717bSVictor Perevertkin {
113*3088717bSVictor Perevertkin WMI_STORAGE_FAILURE_PREDICT_FUNCTION_GUID,
114*3088717bSVictor Perevertkin 1,
115*3088717bSVictor Perevertkin WMIREG_FLAG_EXPENSIVE
116*3088717bSVictor Perevertkin },
117*3088717bSVictor Perevertkin
118*3088717bSVictor Perevertkin {
119*3088717bSVictor Perevertkin WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID,
120*3088717bSVictor Perevertkin 1,
121*3088717bSVictor Perevertkin WMIREG_FLAG_EVENT_ONLY_GUID
122*3088717bSVictor Perevertkin },
123*3088717bSVictor Perevertkin
124*3088717bSVictor Perevertkin {
125*3088717bSVictor Perevertkin WMI_STORAGE_FAILURE_PREDICT_THRESHOLDS_GUID,
126*3088717bSVictor Perevertkin 1,
127*3088717bSVictor Perevertkin WMIREG_FLAG_EXPENSIVE
128*3088717bSVictor Perevertkin },
129*3088717bSVictor Perevertkin
130*3088717bSVictor Perevertkin {
131*3088717bSVictor Perevertkin WMI_STORAGE_SCSI_INFO_EXCEPTIONS_GUID,
132*3088717bSVictor Perevertkin 1,
133*3088717bSVictor Perevertkin 0
134*3088717bSVictor Perevertkin }
135*3088717bSVictor Perevertkin };
136*3088717bSVictor Perevertkin
137*3088717bSVictor Perevertkin
138*3088717bSVictor Perevertkin GUID DiskPredictFailureEventGuid = WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID;
139*3088717bSVictor Perevertkin
140*3088717bSVictor Perevertkin #define DiskGeometryGuid 0
141*3088717bSVictor Perevertkin #define SmartStatusGuid 1
142*3088717bSVictor Perevertkin #define SmartDataGuid 2
143*3088717bSVictor Perevertkin #define SmartPerformFunction 3
144*3088717bSVictor Perevertkin #define AllowDisallowPerformanceHit 1
145*3088717bSVictor Perevertkin #define EnableDisableHardwareFailurePrediction 2
146*3088717bSVictor Perevertkin #define EnableDisableFailurePredictionPolling 3
147*3088717bSVictor Perevertkin #define GetFailurePredictionCapability 4
148*3088717bSVictor Perevertkin #define EnableOfflineDiags 5
149*3088717bSVictor Perevertkin
150*3088717bSVictor Perevertkin #define SmartEventGuid 4
151*3088717bSVictor Perevertkin #define SmartThresholdsGuid 5
152*3088717bSVictor Perevertkin #define ScsiInfoExceptionsGuid 6
153*3088717bSVictor Perevertkin
154*3088717bSVictor Perevertkin #ifdef ALLOC_PRAGMA
155*3088717bSVictor Perevertkin
156*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskWmiFunctionControl)
157*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskFdoQueryWmiRegInfo)
158*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskFdoQueryWmiDataBlock)
159*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskFdoSetWmiDataBlock)
160*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskFdoSetWmiDataItem)
161*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskFdoExecuteWmiMethod)
162*3088717bSVictor Perevertkin
163*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskDetectFailurePrediction)
164*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskEnableDisableFailurePrediction)
165*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskEnableDisableFailurePredictPolling)
166*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskReadFailurePredictStatus)
167*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskReadFailurePredictData)
168*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskReadFailurePredictThresholds)
169*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskGetIdentifyInfo)
170*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskReadSmartLog)
171*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskWriteSmartLog)
172*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskPerformSmartCommand)
173*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskSendFailurePredictIoctl)
174*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskReregWorker)
175*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskInitializeReregistration)
176*3088717bSVictor Perevertkin
177*3088717bSVictor Perevertkin #if (NTDDI_VERSION >= NTDDI_WINBLUE)
178*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskGetModePage)
179*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, DiskEnableInfoExceptions)
180*3088717bSVictor Perevertkin #endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
181*3088717bSVictor Perevertkin
182*3088717bSVictor Perevertkin #endif
183*3088717bSVictor Perevertkin
184*3088717bSVictor Perevertkin
185*3088717bSVictor Perevertkin //
186*3088717bSVictor Perevertkin // Note:
187*3088717bSVictor Perevertkin // Some port drivers assume that the SENDCMDINPARAMS structure will always be atleast
188*3088717bSVictor Perevertkin // sizeof(SENDCMDINPARAMS). So do not adjust for the [pBuffer] if it isn't being used
189*3088717bSVictor Perevertkin //
190*3088717bSVictor Perevertkin
191*3088717bSVictor Perevertkin //
192*3088717bSVictor Perevertkin // SMART/IDE specific routines
193*3088717bSVictor Perevertkin //
194*3088717bSVictor Perevertkin
195*3088717bSVictor Perevertkin //
196*3088717bSVictor Perevertkin // Read SMART data attributes.
197*3088717bSVictor Perevertkin // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE ]
198*3088717bSVictor Perevertkin // Attribute data returned at &SendCmdOutParams->bBuffer[0]
199*3088717bSVictor Perevertkin //
200*3088717bSVictor Perevertkin #define DiskReadSmartData(FdoExtension, \
201*3088717bSVictor Perevertkin SrbControl, \
202*3088717bSVictor Perevertkin BufferSize) \
203*3088717bSVictor Perevertkin DiskPerformSmartCommand(FdoExtension, \
204*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS, \
205*3088717bSVictor Perevertkin SMART_CMD, \
206*3088717bSVictor Perevertkin READ_ATTRIBUTES, \
207*3088717bSVictor Perevertkin 0, \
208*3088717bSVictor Perevertkin 0, \
209*3088717bSVictor Perevertkin (SrbControl), \
210*3088717bSVictor Perevertkin (BufferSize))
211*3088717bSVictor Perevertkin
212*3088717bSVictor Perevertkin
213*3088717bSVictor Perevertkin //
214*3088717bSVictor Perevertkin // Read SMART data thresholds.
215*3088717bSVictor Perevertkin // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE ]
216*3088717bSVictor Perevertkin // Attribute data returned at &SendCmdOutParams->bBuffer[0]
217*3088717bSVictor Perevertkin //
218*3088717bSVictor Perevertkin #define DiskReadSmartThresholds(FdoExtension, \
219*3088717bSVictor Perevertkin SrbControl, \
220*3088717bSVictor Perevertkin BufferSize) \
221*3088717bSVictor Perevertkin DiskPerformSmartCommand(FdoExtension, \
222*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS, \
223*3088717bSVictor Perevertkin SMART_CMD, \
224*3088717bSVictor Perevertkin READ_THRESHOLDS, \
225*3088717bSVictor Perevertkin 0, \
226*3088717bSVictor Perevertkin 0, \
227*3088717bSVictor Perevertkin (SrbControl), \
228*3088717bSVictor Perevertkin (BufferSize))
229*3088717bSVictor Perevertkin
230*3088717bSVictor Perevertkin
231*3088717bSVictor Perevertkin //
232*3088717bSVictor Perevertkin // Read SMART status
233*3088717bSVictor Perevertkin // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS) ]
234*3088717bSVictor Perevertkin // Failure predicted if SendCmdOutParams->bBuffer[3] == 0xf4 and SendCmdOutParams->bBuffer[4] == 0x2c
235*3088717bSVictor Perevertkin //
236*3088717bSVictor Perevertkin #define DiskReadSmartStatus(FdoExtension, \
237*3088717bSVictor Perevertkin SrbControl, \
238*3088717bSVictor Perevertkin BufferSize) \
239*3088717bSVictor Perevertkin DiskPerformSmartCommand(FdoExtension, \
240*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_RETURN_STATUS, \
241*3088717bSVictor Perevertkin SMART_CMD, \
242*3088717bSVictor Perevertkin RETURN_SMART_STATUS, \
243*3088717bSVictor Perevertkin 0, \
244*3088717bSVictor Perevertkin 0, \
245*3088717bSVictor Perevertkin (SrbControl), \
246*3088717bSVictor Perevertkin (BufferSize))
247*3088717bSVictor Perevertkin
248*3088717bSVictor Perevertkin
249*3088717bSVictor Perevertkin //
250*3088717bSVictor Perevertkin // Read disks IDENTIFY data
251*3088717bSVictor Perevertkin // SrbControl should be : sizeof(SRB_IO_CONTROL) + MAX[ sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE ]
252*3088717bSVictor Perevertkin // Identify data returned at &SendCmdOutParams->bBuffer[0]
253*3088717bSVictor Perevertkin //
254*3088717bSVictor Perevertkin #define DiskGetIdentifyData(FdoExtension, \
255*3088717bSVictor Perevertkin SrbControl, \
256*3088717bSVictor Perevertkin BufferSize) \
257*3088717bSVictor Perevertkin DiskPerformSmartCommand(FdoExtension, \
258*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_IDENTIFY, \
259*3088717bSVictor Perevertkin ID_CMD, \
260*3088717bSVictor Perevertkin 0, \
261*3088717bSVictor Perevertkin 0, \
262*3088717bSVictor Perevertkin 0, \
263*3088717bSVictor Perevertkin (SrbControl), \
264*3088717bSVictor Perevertkin (BufferSize))
265*3088717bSVictor Perevertkin
266*3088717bSVictor Perevertkin
267*3088717bSVictor Perevertkin //
268*3088717bSVictor Perevertkin // Enable SMART
269*3088717bSVictor Perevertkin //
270*3088717bSVictor Perevertkin static NTSTATUS
DiskEnableSmart(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)271*3088717bSVictor Perevertkin DiskEnableSmart(
272*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
273*3088717bSVictor Perevertkin )
274*3088717bSVictor Perevertkin {
275*3088717bSVictor Perevertkin UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
276*3088717bSVictor Perevertkin ULONG bufferSize = sizeof(srbControl);
277*3088717bSVictor Perevertkin
278*3088717bSVictor Perevertkin return DiskPerformSmartCommand(FdoExtension,
279*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_ENABLE_SMART,
280*3088717bSVictor Perevertkin SMART_CMD,
281*3088717bSVictor Perevertkin ENABLE_SMART,
282*3088717bSVictor Perevertkin 0,
283*3088717bSVictor Perevertkin 0,
284*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)srbControl,
285*3088717bSVictor Perevertkin &bufferSize);
286*3088717bSVictor Perevertkin }
287*3088717bSVictor Perevertkin
288*3088717bSVictor Perevertkin
289*3088717bSVictor Perevertkin //
290*3088717bSVictor Perevertkin // Disable SMART
291*3088717bSVictor Perevertkin //
292*3088717bSVictor Perevertkin static NTSTATUS
DiskDisableSmart(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)293*3088717bSVictor Perevertkin DiskDisableSmart(
294*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
295*3088717bSVictor Perevertkin )
296*3088717bSVictor Perevertkin {
297*3088717bSVictor Perevertkin UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
298*3088717bSVictor Perevertkin ULONG bufferSize = sizeof(srbControl);
299*3088717bSVictor Perevertkin
300*3088717bSVictor Perevertkin return DiskPerformSmartCommand(FdoExtension,
301*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_DISABLE_SMART,
302*3088717bSVictor Perevertkin SMART_CMD,
303*3088717bSVictor Perevertkin DISABLE_SMART,
304*3088717bSVictor Perevertkin 0,
305*3088717bSVictor Perevertkin 0,
306*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)srbControl,
307*3088717bSVictor Perevertkin &bufferSize);
308*3088717bSVictor Perevertkin }
309*3088717bSVictor Perevertkin
310*3088717bSVictor Perevertkin #ifndef __REACTOS__ // functions are not used
311*3088717bSVictor Perevertkin //
312*3088717bSVictor Perevertkin // Enable Attribute Autosave
313*3088717bSVictor Perevertkin //
314*3088717bSVictor Perevertkin _inline NTSTATUS
DiskEnableSmartAttributeAutosave(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)315*3088717bSVictor Perevertkin DiskEnableSmartAttributeAutosave(
316*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
317*3088717bSVictor Perevertkin )
318*3088717bSVictor Perevertkin {
319*3088717bSVictor Perevertkin UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
320*3088717bSVictor Perevertkin ULONG bufferSize = sizeof(srbControl);
321*3088717bSVictor Perevertkin
322*3088717bSVictor Perevertkin return DiskPerformSmartCommand(FdoExtension,
323*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE,
324*3088717bSVictor Perevertkin SMART_CMD,
325*3088717bSVictor Perevertkin ENABLE_DISABLE_AUTOSAVE,
326*3088717bSVictor Perevertkin 0xf1,
327*3088717bSVictor Perevertkin 0,
328*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)srbControl,
329*3088717bSVictor Perevertkin &bufferSize);
330*3088717bSVictor Perevertkin }
331*3088717bSVictor Perevertkin
332*3088717bSVictor Perevertkin
333*3088717bSVictor Perevertkin //
334*3088717bSVictor Perevertkin // Disable Attribute Autosave
335*3088717bSVictor Perevertkin //
336*3088717bSVictor Perevertkin _inline NTSTATUS
DiskDisableSmartAttributeAutosave(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)337*3088717bSVictor Perevertkin DiskDisableSmartAttributeAutosave(
338*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
339*3088717bSVictor Perevertkin )
340*3088717bSVictor Perevertkin {
341*3088717bSVictor Perevertkin UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
342*3088717bSVictor Perevertkin ULONG bufferSize = sizeof(srbControl);
343*3088717bSVictor Perevertkin
344*3088717bSVictor Perevertkin return DiskPerformSmartCommand(FdoExtension,
345*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE,
346*3088717bSVictor Perevertkin SMART_CMD,
347*3088717bSVictor Perevertkin ENABLE_DISABLE_AUTOSAVE,
348*3088717bSVictor Perevertkin 0x00,
349*3088717bSVictor Perevertkin 0,
350*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)srbControl,
351*3088717bSVictor Perevertkin &bufferSize);
352*3088717bSVictor Perevertkin }
353*3088717bSVictor Perevertkin #endif
354*3088717bSVictor Perevertkin
355*3088717bSVictor Perevertkin //
356*3088717bSVictor Perevertkin // Initialize execution of SMART online diagnostics
357*3088717bSVictor Perevertkin //
358*3088717bSVictor Perevertkin static NTSTATUS
DiskExecuteSmartDiagnostics(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,UCHAR Subcommand)359*3088717bSVictor Perevertkin DiskExecuteSmartDiagnostics(
360*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
361*3088717bSVictor Perevertkin UCHAR Subcommand
362*3088717bSVictor Perevertkin )
363*3088717bSVictor Perevertkin {
364*3088717bSVictor Perevertkin UCHAR srbControl[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)] = {0};
365*3088717bSVictor Perevertkin ULONG bufferSize = sizeof(srbControl);
366*3088717bSVictor Perevertkin
367*3088717bSVictor Perevertkin return DiskPerformSmartCommand(FdoExtension,
368*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS,
369*3088717bSVictor Perevertkin SMART_CMD,
370*3088717bSVictor Perevertkin EXECUTE_OFFLINE_DIAGS,
371*3088717bSVictor Perevertkin 0,
372*3088717bSVictor Perevertkin Subcommand,
373*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)srbControl,
374*3088717bSVictor Perevertkin &bufferSize);
375*3088717bSVictor Perevertkin }
376*3088717bSVictor Perevertkin
377*3088717bSVictor Perevertkin
378*3088717bSVictor Perevertkin NTSTATUS
DiskReadSmartLog(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,IN UCHAR SectorCount,IN UCHAR LogAddress,OUT PUCHAR Buffer)379*3088717bSVictor Perevertkin DiskReadSmartLog(
380*3088717bSVictor Perevertkin IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
381*3088717bSVictor Perevertkin IN UCHAR SectorCount,
382*3088717bSVictor Perevertkin IN UCHAR LogAddress,
383*3088717bSVictor Perevertkin OUT PUCHAR Buffer
384*3088717bSVictor Perevertkin )
385*3088717bSVictor Perevertkin {
386*3088717bSVictor Perevertkin PSRB_IO_CONTROL srbControl;
387*3088717bSVictor Perevertkin NTSTATUS status;
388*3088717bSVictor Perevertkin PSENDCMDOUTPARAMS sendCmdOutParams;
389*3088717bSVictor Perevertkin ULONG logSize, bufferSize;
390*3088717bSVictor Perevertkin
391*3088717bSVictor Perevertkin PAGED_CODE();
392*3088717bSVictor Perevertkin
393*3088717bSVictor Perevertkin logSize = SectorCount * SMART_LOG_SECTOR_SIZE;
394*3088717bSVictor Perevertkin bufferSize = sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + logSize );
395*3088717bSVictor Perevertkin
396*3088717bSVictor Perevertkin srbControl = ExAllocatePoolWithTag(NonPagedPoolNx,
397*3088717bSVictor Perevertkin bufferSize,
398*3088717bSVictor Perevertkin DISK_TAG_SMART);
399*3088717bSVictor Perevertkin
400*3088717bSVictor Perevertkin if (srbControl != NULL)
401*3088717bSVictor Perevertkin {
402*3088717bSVictor Perevertkin status = DiskPerformSmartCommand(FdoExtension,
403*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_READ_SMART_LOG,
404*3088717bSVictor Perevertkin SMART_CMD,
405*3088717bSVictor Perevertkin SMART_READ_LOG,
406*3088717bSVictor Perevertkin SectorCount,
407*3088717bSVictor Perevertkin LogAddress,
408*3088717bSVictor Perevertkin srbControl,
409*3088717bSVictor Perevertkin &bufferSize);
410*3088717bSVictor Perevertkin
411*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
412*3088717bSVictor Perevertkin {
413*3088717bSVictor Perevertkin sendCmdOutParams = (PSENDCMDOUTPARAMS)((PUCHAR)srbControl +
414*3088717bSVictor Perevertkin sizeof(SRB_IO_CONTROL));
415*3088717bSVictor Perevertkin RtlCopyMemory(Buffer,
416*3088717bSVictor Perevertkin &sendCmdOutParams->bBuffer[0],
417*3088717bSVictor Perevertkin logSize);
418*3088717bSVictor Perevertkin }
419*3088717bSVictor Perevertkin
420*3088717bSVictor Perevertkin FREE_POOL(srbControl);
421*3088717bSVictor Perevertkin } else {
422*3088717bSVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
423*3088717bSVictor Perevertkin }
424*3088717bSVictor Perevertkin return(status);
425*3088717bSVictor Perevertkin }
426*3088717bSVictor Perevertkin
427*3088717bSVictor Perevertkin
428*3088717bSVictor Perevertkin NTSTATUS
DiskWriteSmartLog(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,IN UCHAR SectorCount,IN UCHAR LogAddress,IN PUCHAR Buffer)429*3088717bSVictor Perevertkin DiskWriteSmartLog(
430*3088717bSVictor Perevertkin IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
431*3088717bSVictor Perevertkin IN UCHAR SectorCount,
432*3088717bSVictor Perevertkin IN UCHAR LogAddress,
433*3088717bSVictor Perevertkin IN PUCHAR Buffer
434*3088717bSVictor Perevertkin )
435*3088717bSVictor Perevertkin {
436*3088717bSVictor Perevertkin PSRB_IO_CONTROL srbControl;
437*3088717bSVictor Perevertkin NTSTATUS status;
438*3088717bSVictor Perevertkin PSENDCMDINPARAMS sendCmdInParams;
439*3088717bSVictor Perevertkin ULONG logSize, bufferSize;
440*3088717bSVictor Perevertkin
441*3088717bSVictor Perevertkin PAGED_CODE();
442*3088717bSVictor Perevertkin
443*3088717bSVictor Perevertkin logSize = SectorCount * SMART_LOG_SECTOR_SIZE;
444*3088717bSVictor Perevertkin bufferSize = sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1 +
445*3088717bSVictor Perevertkin logSize;
446*3088717bSVictor Perevertkin
447*3088717bSVictor Perevertkin srbControl = ExAllocatePoolWithTag(NonPagedPoolNx,
448*3088717bSVictor Perevertkin bufferSize,
449*3088717bSVictor Perevertkin DISK_TAG_SMART);
450*3088717bSVictor Perevertkin
451*3088717bSVictor Perevertkin if (srbControl != NULL)
452*3088717bSVictor Perevertkin {
453*3088717bSVictor Perevertkin sendCmdInParams = (PSENDCMDINPARAMS)((PUCHAR)srbControl +
454*3088717bSVictor Perevertkin sizeof(SRB_IO_CONTROL));
455*3088717bSVictor Perevertkin RtlCopyMemory(&sendCmdInParams->bBuffer[0],
456*3088717bSVictor Perevertkin Buffer,
457*3088717bSVictor Perevertkin logSize);
458*3088717bSVictor Perevertkin status = DiskPerformSmartCommand(FdoExtension,
459*3088717bSVictor Perevertkin IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG,
460*3088717bSVictor Perevertkin SMART_CMD,
461*3088717bSVictor Perevertkin SMART_WRITE_LOG,
462*3088717bSVictor Perevertkin SectorCount,
463*3088717bSVictor Perevertkin LogAddress,
464*3088717bSVictor Perevertkin srbControl,
465*3088717bSVictor Perevertkin &bufferSize);
466*3088717bSVictor Perevertkin
467*3088717bSVictor Perevertkin FREE_POOL(srbControl);
468*3088717bSVictor Perevertkin } else {
469*3088717bSVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
470*3088717bSVictor Perevertkin }
471*3088717bSVictor Perevertkin return(status);
472*3088717bSVictor Perevertkin }
473*3088717bSVictor Perevertkin
474*3088717bSVictor Perevertkin
475*3088717bSVictor Perevertkin NTSTATUS
DiskPerformSmartCommand(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,IN ULONG SrbControlCode,IN UCHAR Command,IN UCHAR Feature,IN UCHAR SectorCount,IN UCHAR SectorNumber,IN OUT PSRB_IO_CONTROL SrbControl,OUT PULONG BufferSize)476*3088717bSVictor Perevertkin DiskPerformSmartCommand(
477*3088717bSVictor Perevertkin IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
478*3088717bSVictor Perevertkin IN ULONG SrbControlCode,
479*3088717bSVictor Perevertkin IN UCHAR Command,
480*3088717bSVictor Perevertkin IN UCHAR Feature,
481*3088717bSVictor Perevertkin IN UCHAR SectorCount,
482*3088717bSVictor Perevertkin IN UCHAR SectorNumber,
483*3088717bSVictor Perevertkin IN OUT PSRB_IO_CONTROL SrbControl,
484*3088717bSVictor Perevertkin OUT PULONG BufferSize
485*3088717bSVictor Perevertkin )
486*3088717bSVictor Perevertkin /*++
487*3088717bSVictor Perevertkin
488*3088717bSVictor Perevertkin Routine Description:
489*3088717bSVictor Perevertkin
490*3088717bSVictor Perevertkin This routine will perform some SMART command
491*3088717bSVictor Perevertkin
492*3088717bSVictor Perevertkin Arguments:
493*3088717bSVictor Perevertkin
494*3088717bSVictor Perevertkin FdoExtension is the FDO device extension
495*3088717bSVictor Perevertkin
496*3088717bSVictor Perevertkin SrbControlCode is the SRB control code to use for the request
497*3088717bSVictor Perevertkin
498*3088717bSVictor Perevertkin Command is the SMART command to be executed. It may be SMART_CMD or
499*3088717bSVictor Perevertkin ID_CMD.
500*3088717bSVictor Perevertkin
501*3088717bSVictor Perevertkin Feature is the value to place in the IDE feature register.
502*3088717bSVictor Perevertkin
503*3088717bSVictor Perevertkin SectorCount is the value to place in the IDE SectorCount register
504*3088717bSVictor Perevertkin
505*3088717bSVictor Perevertkin SrbControl is the buffer used to build the SRB_IO_CONTROL and pass
506*3088717bSVictor Perevertkin any input parameters. It also returns the output parameters.
507*3088717bSVictor Perevertkin
508*3088717bSVictor Perevertkin *BufferSize on entry has total size of SrbControl and on return has
509*3088717bSVictor Perevertkin the size used in SrbControl.
510*3088717bSVictor Perevertkin
511*3088717bSVictor Perevertkin
512*3088717bSVictor Perevertkin
513*3088717bSVictor Perevertkin Return Value:
514*3088717bSVictor Perevertkin
515*3088717bSVictor Perevertkin status
516*3088717bSVictor Perevertkin
517*3088717bSVictor Perevertkin --*/
518*3088717bSVictor Perevertkin {
519*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
520*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
521*3088717bSVictor Perevertkin PUCHAR buffer;
522*3088717bSVictor Perevertkin PSENDCMDINPARAMS cmdInParameters;
523*3088717bSVictor Perevertkin NTSTATUS status;
524*3088717bSVictor Perevertkin ULONG availableBufferSize;
525*3088717bSVictor Perevertkin KEVENT event;
526*3088717bSVictor Perevertkin PIRP irp;
527*3088717bSVictor Perevertkin IO_STATUS_BLOCK ioStatus = { 0 };
528*3088717bSVictor Perevertkin SCSI_REQUEST_BLOCK srb = {0};
529*3088717bSVictor Perevertkin LARGE_INTEGER startingOffset;
530*3088717bSVictor Perevertkin ULONG length;
531*3088717bSVictor Perevertkin PIO_STACK_LOCATION irpStack;
532*3088717bSVictor Perevertkin UCHAR srbExBuffer[CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE] = {0};
533*3088717bSVictor Perevertkin PSTORAGE_REQUEST_BLOCK srbEx = (PSTORAGE_REQUEST_BLOCK)srbExBuffer;
534*3088717bSVictor Perevertkin PSTOR_ADDR_BTL8 storAddrBtl8;
535*3088717bSVictor Perevertkin
536*3088717bSVictor Perevertkin PAGED_CODE();
537*3088717bSVictor Perevertkin
538*3088717bSVictor Perevertkin //
539*3088717bSVictor Perevertkin // Point to the 'buffer' portion of the SRB_CONTROL and compute how
540*3088717bSVictor Perevertkin // much room we have left in the srb control. Abort if the buffer
541*3088717bSVictor Perevertkin // isn't at least the size of SRB_IO_CONTROL.
542*3088717bSVictor Perevertkin //
543*3088717bSVictor Perevertkin
544*3088717bSVictor Perevertkin buffer = (PUCHAR)SrbControl + sizeof(SRB_IO_CONTROL);
545*3088717bSVictor Perevertkin
546*3088717bSVictor Perevertkin cmdInParameters = (PSENDCMDINPARAMS)buffer;
547*3088717bSVictor Perevertkin
548*3088717bSVictor Perevertkin if (*BufferSize >= sizeof(SRB_IO_CONTROL)) {
549*3088717bSVictor Perevertkin availableBufferSize = *BufferSize - sizeof(SRB_IO_CONTROL);
550*3088717bSVictor Perevertkin } else {
551*3088717bSVictor Perevertkin return STATUS_BUFFER_TOO_SMALL;
552*3088717bSVictor Perevertkin }
553*3088717bSVictor Perevertkin
554*3088717bSVictor Perevertkin #if DBG
555*3088717bSVictor Perevertkin
556*3088717bSVictor Perevertkin //
557*3088717bSVictor Perevertkin // Ensure control codes and buffer lengths passed are correct
558*3088717bSVictor Perevertkin //
559*3088717bSVictor Perevertkin {
560*3088717bSVictor Perevertkin ULONG controlCode = 0;
561*3088717bSVictor Perevertkin ULONG lengthNeeded = sizeof(SENDCMDINPARAMS);
562*3088717bSVictor Perevertkin
563*3088717bSVictor Perevertkin if (Command == SMART_CMD)
564*3088717bSVictor Perevertkin {
565*3088717bSVictor Perevertkin switch (Feature)
566*3088717bSVictor Perevertkin {
567*3088717bSVictor Perevertkin case ENABLE_SMART:
568*3088717bSVictor Perevertkin {
569*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
570*3088717bSVictor Perevertkin break;
571*3088717bSVictor Perevertkin }
572*3088717bSVictor Perevertkin
573*3088717bSVictor Perevertkin case DISABLE_SMART:
574*3088717bSVictor Perevertkin {
575*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
576*3088717bSVictor Perevertkin break;
577*3088717bSVictor Perevertkin }
578*3088717bSVictor Perevertkin
579*3088717bSVictor Perevertkin case RETURN_SMART_STATUS:
580*3088717bSVictor Perevertkin {
581*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
582*3088717bSVictor Perevertkin lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS) );
583*3088717bSVictor Perevertkin break;
584*3088717bSVictor Perevertkin }
585*3088717bSVictor Perevertkin
586*3088717bSVictor Perevertkin case ENABLE_DISABLE_AUTOSAVE:
587*3088717bSVictor Perevertkin {
588*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
589*3088717bSVictor Perevertkin break;
590*3088717bSVictor Perevertkin }
591*3088717bSVictor Perevertkin
592*3088717bSVictor Perevertkin case SAVE_ATTRIBUTE_VALUES:
593*3088717bSVictor Perevertkin {
594*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
595*3088717bSVictor Perevertkin break;
596*3088717bSVictor Perevertkin }
597*3088717bSVictor Perevertkin
598*3088717bSVictor Perevertkin
599*3088717bSVictor Perevertkin case EXECUTE_OFFLINE_DIAGS:
600*3088717bSVictor Perevertkin {
601*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
602*3088717bSVictor Perevertkin break;
603*3088717bSVictor Perevertkin }
604*3088717bSVictor Perevertkin
605*3088717bSVictor Perevertkin case READ_ATTRIBUTES:
606*3088717bSVictor Perevertkin {
607*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS;
608*3088717bSVictor Perevertkin lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE );
609*3088717bSVictor Perevertkin break;
610*3088717bSVictor Perevertkin }
611*3088717bSVictor Perevertkin
612*3088717bSVictor Perevertkin case READ_THRESHOLDS:
613*3088717bSVictor Perevertkin {
614*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS;
615*3088717bSVictor Perevertkin lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE );
616*3088717bSVictor Perevertkin break;
617*3088717bSVictor Perevertkin }
618*3088717bSVictor Perevertkin
619*3088717bSVictor Perevertkin case SMART_READ_LOG:
620*3088717bSVictor Perevertkin {
621*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_LOG;
622*3088717bSVictor Perevertkin lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + (SectorCount * SMART_LOG_SECTOR_SIZE) );
623*3088717bSVictor Perevertkin break;
624*3088717bSVictor Perevertkin }
625*3088717bSVictor Perevertkin
626*3088717bSVictor Perevertkin case SMART_WRITE_LOG:
627*3088717bSVictor Perevertkin {
628*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG;
629*3088717bSVictor Perevertkin lengthNeeded = lengthNeeded - 1 + (SectorCount * SMART_LOG_SECTOR_SIZE);
630*3088717bSVictor Perevertkin break;
631*3088717bSVictor Perevertkin }
632*3088717bSVictor Perevertkin
633*3088717bSVictor Perevertkin }
634*3088717bSVictor Perevertkin
635*3088717bSVictor Perevertkin } else if (Command == ID_CMD) {
636*3088717bSVictor Perevertkin
637*3088717bSVictor Perevertkin controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
638*3088717bSVictor Perevertkin lengthNeeded = max( lengthNeeded, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE );
639*3088717bSVictor Perevertkin
640*3088717bSVictor Perevertkin } else {
641*3088717bSVictor Perevertkin
642*3088717bSVictor Perevertkin NT_ASSERT(FALSE);
643*3088717bSVictor Perevertkin }
644*3088717bSVictor Perevertkin
645*3088717bSVictor Perevertkin NT_ASSERT(controlCode == SrbControlCode);
646*3088717bSVictor Perevertkin NT_ASSERT(availableBufferSize >= lengthNeeded);
647*3088717bSVictor Perevertkin }
648*3088717bSVictor Perevertkin
649*3088717bSVictor Perevertkin #endif
650*3088717bSVictor Perevertkin
651*3088717bSVictor Perevertkin //
652*3088717bSVictor Perevertkin // Build SrbControl and input to SMART command
653*3088717bSVictor Perevertkin //
654*3088717bSVictor Perevertkin SrbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
655*3088717bSVictor Perevertkin RtlMoveMemory (SrbControl->Signature, "SCSIDISK", 8);
656*3088717bSVictor Perevertkin SrbControl->Timeout = FdoExtension->TimeOutValue;
657*3088717bSVictor Perevertkin SrbControl->Length = availableBufferSize;
658*3088717bSVictor Perevertkin SrbControl->ControlCode = SrbControlCode;
659*3088717bSVictor Perevertkin
660*3088717bSVictor Perevertkin cmdInParameters->cBufferSize = sizeof(SENDCMDINPARAMS);
661*3088717bSVictor Perevertkin cmdInParameters->bDriveNumber = diskData->ScsiAddress.TargetId;
662*3088717bSVictor Perevertkin cmdInParameters->irDriveRegs.bFeaturesReg = Feature;
663*3088717bSVictor Perevertkin cmdInParameters->irDriveRegs.bSectorCountReg = SectorCount;
664*3088717bSVictor Perevertkin cmdInParameters->irDriveRegs.bSectorNumberReg = SectorNumber;
665*3088717bSVictor Perevertkin cmdInParameters->irDriveRegs.bCylLowReg = SMART_CYL_LOW;
666*3088717bSVictor Perevertkin cmdInParameters->irDriveRegs.bCylHighReg = SMART_CYL_HI;
667*3088717bSVictor Perevertkin cmdInParameters->irDriveRegs.bCommandReg = Command;
668*3088717bSVictor Perevertkin
669*3088717bSVictor Perevertkin //
670*3088717bSVictor Perevertkin // Create and send irp
671*3088717bSVictor Perevertkin //
672*3088717bSVictor Perevertkin KeInitializeEvent(&event, NotificationEvent, FALSE);
673*3088717bSVictor Perevertkin
674*3088717bSVictor Perevertkin startingOffset.QuadPart = (LONGLONG) 1;
675*3088717bSVictor Perevertkin
676*3088717bSVictor Perevertkin length = SrbControl->HeaderLength + SrbControl->Length;
677*3088717bSVictor Perevertkin
678*3088717bSVictor Perevertkin irp = IoBuildSynchronousFsdRequest(
679*3088717bSVictor Perevertkin IRP_MJ_SCSI,
680*3088717bSVictor Perevertkin commonExtension->LowerDeviceObject,
681*3088717bSVictor Perevertkin SrbControl,
682*3088717bSVictor Perevertkin length,
683*3088717bSVictor Perevertkin &startingOffset,
684*3088717bSVictor Perevertkin &event,
685*3088717bSVictor Perevertkin &ioStatus);
686*3088717bSVictor Perevertkin
687*3088717bSVictor Perevertkin if (irp == NULL) {
688*3088717bSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
689*3088717bSVictor Perevertkin }
690*3088717bSVictor Perevertkin
691*3088717bSVictor Perevertkin irpStack = IoGetNextIrpStackLocation(irp);
692*3088717bSVictor Perevertkin
693*3088717bSVictor Perevertkin //
694*3088717bSVictor Perevertkin // Set major and minor codes.
695*3088717bSVictor Perevertkin //
696*3088717bSVictor Perevertkin
697*3088717bSVictor Perevertkin irpStack->MajorFunction = IRP_MJ_SCSI;
698*3088717bSVictor Perevertkin irpStack->MinorFunction = 1;
699*3088717bSVictor Perevertkin
700*3088717bSVictor Perevertkin //
701*3088717bSVictor Perevertkin // Fill in SRB fields.
702*3088717bSVictor Perevertkin //
703*3088717bSVictor Perevertkin
704*3088717bSVictor Perevertkin if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
705*3088717bSVictor Perevertkin irpStack->Parameters.Others.Argument1 = srbEx;
706*3088717bSVictor Perevertkin
707*3088717bSVictor Perevertkin //
708*3088717bSVictor Perevertkin // Set up STORAGE_REQUEST_BLOCK fields
709*3088717bSVictor Perevertkin //
710*3088717bSVictor Perevertkin
711*3088717bSVictor Perevertkin srbEx->Length = FIELD_OFFSET(STORAGE_REQUEST_BLOCK, Signature);
712*3088717bSVictor Perevertkin srbEx->Function = SRB_FUNCTION_STORAGE_REQUEST_BLOCK;
713*3088717bSVictor Perevertkin srbEx->Signature = SRB_SIGNATURE;
714*3088717bSVictor Perevertkin srbEx->Version = STORAGE_REQUEST_BLOCK_VERSION_1;
715*3088717bSVictor Perevertkin srbEx->SrbLength = sizeof(srbExBuffer);
716*3088717bSVictor Perevertkin srbEx->SrbFunction = SRB_FUNCTION_IO_CONTROL;
717*3088717bSVictor Perevertkin srbEx->RequestPriority = IoGetIoPriorityHint(irp);
718*3088717bSVictor Perevertkin srbEx->AddressOffset = sizeof(STORAGE_REQUEST_BLOCK);
719*3088717bSVictor Perevertkin
720*3088717bSVictor Perevertkin srbEx->SrbFlags = FdoExtension->SrbFlags;
721*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DATA_IN);
722*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
723*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
724*3088717bSVictor Perevertkin
725*3088717bSVictor Perevertkin srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
726*3088717bSVictor Perevertkin srbEx->RequestTag = SP_UNTAGGED;
727*3088717bSVictor Perevertkin
728*3088717bSVictor Perevertkin srbEx->OriginalRequest = irp;
729*3088717bSVictor Perevertkin
730*3088717bSVictor Perevertkin //
731*3088717bSVictor Perevertkin // Set timeout to requested value.
732*3088717bSVictor Perevertkin //
733*3088717bSVictor Perevertkin
734*3088717bSVictor Perevertkin srbEx->TimeOutValue = SrbControl->Timeout;
735*3088717bSVictor Perevertkin
736*3088717bSVictor Perevertkin //
737*3088717bSVictor Perevertkin // Set the data buffer.
738*3088717bSVictor Perevertkin //
739*3088717bSVictor Perevertkin
740*3088717bSVictor Perevertkin srbEx->DataBuffer = SrbControl;
741*3088717bSVictor Perevertkin srbEx->DataTransferLength = length;
742*3088717bSVictor Perevertkin
743*3088717bSVictor Perevertkin //
744*3088717bSVictor Perevertkin // Set up address fields
745*3088717bSVictor Perevertkin //
746*3088717bSVictor Perevertkin
747*3088717bSVictor Perevertkin storAddrBtl8 = (PSTOR_ADDR_BTL8) ((PUCHAR)srbEx + srbEx->AddressOffset);
748*3088717bSVictor Perevertkin storAddrBtl8->Type = STOR_ADDRESS_TYPE_BTL8;
749*3088717bSVictor Perevertkin storAddrBtl8->AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
750*3088717bSVictor Perevertkin storAddrBtl8->Path = diskData->ScsiAddress.PathId;
751*3088717bSVictor Perevertkin storAddrBtl8->Target = diskData->ScsiAddress.TargetId;
752*3088717bSVictor Perevertkin storAddrBtl8->Lun = srb.Lun = diskData->ScsiAddress.Lun;
753*3088717bSVictor Perevertkin
754*3088717bSVictor Perevertkin } else {
755*3088717bSVictor Perevertkin irpStack->Parameters.Others.Argument1 = &srb;
756*3088717bSVictor Perevertkin
757*3088717bSVictor Perevertkin srb.PathId = diskData->ScsiAddress.PathId;
758*3088717bSVictor Perevertkin srb.TargetId = diskData->ScsiAddress.TargetId;
759*3088717bSVictor Perevertkin srb.Lun = diskData->ScsiAddress.Lun;
760*3088717bSVictor Perevertkin
761*3088717bSVictor Perevertkin srb.Function = SRB_FUNCTION_IO_CONTROL;
762*3088717bSVictor Perevertkin srb.Length = sizeof(SCSI_REQUEST_BLOCK);
763*3088717bSVictor Perevertkin
764*3088717bSVictor Perevertkin srb.SrbFlags = FdoExtension->SrbFlags;
765*3088717bSVictor Perevertkin SET_FLAG(srb.SrbFlags, SRB_FLAGS_DATA_IN);
766*3088717bSVictor Perevertkin SET_FLAG(srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
767*3088717bSVictor Perevertkin SET_FLAG(srb.SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
768*3088717bSVictor Perevertkin
769*3088717bSVictor Perevertkin srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
770*3088717bSVictor Perevertkin srb.QueueTag = SP_UNTAGGED;
771*3088717bSVictor Perevertkin
772*3088717bSVictor Perevertkin srb.OriginalRequest = irp;
773*3088717bSVictor Perevertkin
774*3088717bSVictor Perevertkin //
775*3088717bSVictor Perevertkin // Set timeout to requested value.
776*3088717bSVictor Perevertkin //
777*3088717bSVictor Perevertkin
778*3088717bSVictor Perevertkin srb.TimeOutValue = SrbControl->Timeout;
779*3088717bSVictor Perevertkin
780*3088717bSVictor Perevertkin //
781*3088717bSVictor Perevertkin // Set the data buffer.
782*3088717bSVictor Perevertkin //
783*3088717bSVictor Perevertkin
784*3088717bSVictor Perevertkin srb.DataBuffer = SrbControl;
785*3088717bSVictor Perevertkin srb.DataTransferLength = length;
786*3088717bSVictor Perevertkin }
787*3088717bSVictor Perevertkin
788*3088717bSVictor Perevertkin //
789*3088717bSVictor Perevertkin // Flush the data buffer for output. This will insure that the data is
790*3088717bSVictor Perevertkin // written back to memory. Since the data-in flag is the the port driver
791*3088717bSVictor Perevertkin // will flush the data again for input which will ensure the data is not
792*3088717bSVictor Perevertkin // in the cache.
793*3088717bSVictor Perevertkin //
794*3088717bSVictor Perevertkin
795*3088717bSVictor Perevertkin KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
796*3088717bSVictor Perevertkin
797*3088717bSVictor Perevertkin //
798*3088717bSVictor Perevertkin // Call port driver to handle this request.
799*3088717bSVictor Perevertkin //
800*3088717bSVictor Perevertkin
801*3088717bSVictor Perevertkin status = IoCallDriver(commonExtension->LowerDeviceObject, irp);
802*3088717bSVictor Perevertkin
803*3088717bSVictor Perevertkin if (status == STATUS_PENDING) {
804*3088717bSVictor Perevertkin KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
805*3088717bSVictor Perevertkin status = ioStatus.Status;
806*3088717bSVictor Perevertkin }
807*3088717bSVictor Perevertkin
808*3088717bSVictor Perevertkin return status;
809*3088717bSVictor Perevertkin }
810*3088717bSVictor Perevertkin
811*3088717bSVictor Perevertkin
812*3088717bSVictor Perevertkin NTSTATUS
DiskGetIdentifyInfo(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PBOOLEAN SupportSmart)813*3088717bSVictor Perevertkin DiskGetIdentifyInfo(
814*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
815*3088717bSVictor Perevertkin PBOOLEAN SupportSmart
816*3088717bSVictor Perevertkin )
817*3088717bSVictor Perevertkin {
818*3088717bSVictor Perevertkin UCHAR outBuffer[sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE )] = {0};
819*3088717bSVictor Perevertkin ULONG outBufferSize = sizeof(outBuffer);
820*3088717bSVictor Perevertkin NTSTATUS status;
821*3088717bSVictor Perevertkin
822*3088717bSVictor Perevertkin PAGED_CODE();
823*3088717bSVictor Perevertkin
824*3088717bSVictor Perevertkin status = DiskGetIdentifyData(FdoExtension,
825*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)outBuffer,
826*3088717bSVictor Perevertkin &outBufferSize);
827*3088717bSVictor Perevertkin
828*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
829*3088717bSVictor Perevertkin {
830*3088717bSVictor Perevertkin PUSHORT identifyData = (PUSHORT)&(outBuffer[sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDOUTPARAMS) - 1]);
831*3088717bSVictor Perevertkin USHORT commandSetSupported = identifyData[82];
832*3088717bSVictor Perevertkin
833*3088717bSVictor Perevertkin *SupportSmart = ((commandSetSupported != 0xffff) &&
834*3088717bSVictor Perevertkin (commandSetSupported != 0) &&
835*3088717bSVictor Perevertkin ((commandSetSupported & 1) == 1));
836*3088717bSVictor Perevertkin } else {
837*3088717bSVictor Perevertkin *SupportSmart = FALSE;
838*3088717bSVictor Perevertkin }
839*3088717bSVictor Perevertkin
840*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DiskGetIdentifyInfo: SMART %s supported for device %p, status %lx\n",
841*3088717bSVictor Perevertkin *SupportSmart ? "is" : "is not",
842*3088717bSVictor Perevertkin FdoExtension->DeviceObject,
843*3088717bSVictor Perevertkin status));
844*3088717bSVictor Perevertkin
845*3088717bSVictor Perevertkin return status;
846*3088717bSVictor Perevertkin }
847*3088717bSVictor Perevertkin
848*3088717bSVictor Perevertkin
849*3088717bSVictor Perevertkin //
850*3088717bSVictor Perevertkin // FP Ioctl specific routines
851*3088717bSVictor Perevertkin //
852*3088717bSVictor Perevertkin
853*3088717bSVictor Perevertkin NTSTATUS
DiskSendFailurePredictIoctl(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PSTORAGE_PREDICT_FAILURE checkFailure)854*3088717bSVictor Perevertkin DiskSendFailurePredictIoctl(
855*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
856*3088717bSVictor Perevertkin PSTORAGE_PREDICT_FAILURE checkFailure
857*3088717bSVictor Perevertkin )
858*3088717bSVictor Perevertkin {
859*3088717bSVictor Perevertkin KEVENT event;
860*3088717bSVictor Perevertkin PDEVICE_OBJECT deviceObject;
861*3088717bSVictor Perevertkin IO_STATUS_BLOCK ioStatus = { 0 };
862*3088717bSVictor Perevertkin PIRP irp;
863*3088717bSVictor Perevertkin NTSTATUS status;
864*3088717bSVictor Perevertkin
865*3088717bSVictor Perevertkin PAGED_CODE();
866*3088717bSVictor Perevertkin
867*3088717bSVictor Perevertkin KeInitializeEvent(&event, SynchronizationEvent, FALSE);
868*3088717bSVictor Perevertkin
869*3088717bSVictor Perevertkin deviceObject = IoGetAttachedDeviceReference(FdoExtension->DeviceObject);
870*3088717bSVictor Perevertkin
871*3088717bSVictor Perevertkin irp = IoBuildDeviceIoControlRequest(
872*3088717bSVictor Perevertkin IOCTL_STORAGE_PREDICT_FAILURE,
873*3088717bSVictor Perevertkin deviceObject,
874*3088717bSVictor Perevertkin NULL,
875*3088717bSVictor Perevertkin 0,
876*3088717bSVictor Perevertkin checkFailure,
877*3088717bSVictor Perevertkin sizeof(STORAGE_PREDICT_FAILURE),
878*3088717bSVictor Perevertkin FALSE,
879*3088717bSVictor Perevertkin &event,
880*3088717bSVictor Perevertkin &ioStatus);
881*3088717bSVictor Perevertkin
882*3088717bSVictor Perevertkin if (irp != NULL)
883*3088717bSVictor Perevertkin {
884*3088717bSVictor Perevertkin status = IoCallDriver(deviceObject, irp);
885*3088717bSVictor Perevertkin if (status == STATUS_PENDING)
886*3088717bSVictor Perevertkin {
887*3088717bSVictor Perevertkin KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
888*3088717bSVictor Perevertkin status = ioStatus.Status;
889*3088717bSVictor Perevertkin }
890*3088717bSVictor Perevertkin
891*3088717bSVictor Perevertkin } else {
892*3088717bSVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
893*3088717bSVictor Perevertkin }
894*3088717bSVictor Perevertkin
895*3088717bSVictor Perevertkin ObDereferenceObject(deviceObject);
896*3088717bSVictor Perevertkin
897*3088717bSVictor Perevertkin return status;
898*3088717bSVictor Perevertkin }
899*3088717bSVictor Perevertkin
900*3088717bSVictor Perevertkin #if (NTDDI_VERSION >= NTDDI_WINBLUE)
901*3088717bSVictor Perevertkin
902*3088717bSVictor Perevertkin NTSTATUS
DiskGetModePage(_In_ PDEVICE_OBJECT Fdo,_In_ UCHAR PageMode,_In_ UCHAR PageControl,_In_ PMODE_PARAMETER_HEADER ModeData,_Inout_ PULONG ModeDataSize,_Out_ PVOID * PageData)903*3088717bSVictor Perevertkin DiskGetModePage(
904*3088717bSVictor Perevertkin _In_ PDEVICE_OBJECT Fdo,
905*3088717bSVictor Perevertkin _In_ UCHAR PageMode,
906*3088717bSVictor Perevertkin _In_ UCHAR PageControl,
907*3088717bSVictor Perevertkin _In_ PMODE_PARAMETER_HEADER ModeData,
908*3088717bSVictor Perevertkin _Inout_ PULONG ModeDataSize,
909*3088717bSVictor Perevertkin _Out_ PVOID* PageData
910*3088717bSVictor Perevertkin )
911*3088717bSVictor Perevertkin {
912*3088717bSVictor Perevertkin ULONG size = 0;
913*3088717bSVictor Perevertkin PVOID pageData = NULL;
914*3088717bSVictor Perevertkin
915*3088717bSVictor Perevertkin PAGED_CODE();
916*3088717bSVictor Perevertkin
917*3088717bSVictor Perevertkin if (ModeData == NULL ||
918*3088717bSVictor Perevertkin ModeDataSize == NULL ||
919*3088717bSVictor Perevertkin *ModeDataSize < sizeof(MODE_PARAMETER_HEADER) ||
920*3088717bSVictor Perevertkin PageData == NULL) {
921*3088717bSVictor Perevertkin return STATUS_INVALID_PARAMETER;
922*3088717bSVictor Perevertkin }
923*3088717bSVictor Perevertkin
924*3088717bSVictor Perevertkin RtlZeroMemory (ModeData, *ModeDataSize);
925*3088717bSVictor Perevertkin
926*3088717bSVictor Perevertkin size = ClassModeSenseEx(Fdo,
927*3088717bSVictor Perevertkin (PCHAR) ModeData,
928*3088717bSVictor Perevertkin *ModeDataSize,
929*3088717bSVictor Perevertkin PageMode,
930*3088717bSVictor Perevertkin PageControl);
931*3088717bSVictor Perevertkin
932*3088717bSVictor Perevertkin if (size < sizeof(MODE_PARAMETER_HEADER)) {
933*3088717bSVictor Perevertkin
934*3088717bSVictor Perevertkin //
935*3088717bSVictor Perevertkin // Retry the request in case of a check condition.
936*3088717bSVictor Perevertkin //
937*3088717bSVictor Perevertkin size = ClassModeSenseEx(Fdo,
938*3088717bSVictor Perevertkin (PCHAR) ModeData,
939*3088717bSVictor Perevertkin *ModeDataSize,
940*3088717bSVictor Perevertkin PageMode,
941*3088717bSVictor Perevertkin PageControl);
942*3088717bSVictor Perevertkin
943*3088717bSVictor Perevertkin if (size < sizeof(MODE_PARAMETER_HEADER)) {
944*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_WMI, "DiskGetModePage: Mode Sense for Page Mode %d with Page Control %d failed\n",
945*3088717bSVictor Perevertkin PageMode, PageControl));
946*3088717bSVictor Perevertkin *ModeDataSize = 0;
947*3088717bSVictor Perevertkin return STATUS_IO_DEVICE_ERROR;
948*3088717bSVictor Perevertkin }
949*3088717bSVictor Perevertkin }
950*3088717bSVictor Perevertkin
951*3088717bSVictor Perevertkin //
952*3088717bSVictor Perevertkin // If the length is greater than length indicated by the mode data reset
953*3088717bSVictor Perevertkin // the data to the mode data.
954*3088717bSVictor Perevertkin //
955*3088717bSVictor Perevertkin if (size > (ULONG) (ModeData->ModeDataLength + 1)) {
956*3088717bSVictor Perevertkin size = ModeData->ModeDataLength + 1;
957*3088717bSVictor Perevertkin }
958*3088717bSVictor Perevertkin
959*3088717bSVictor Perevertkin *ModeDataSize = size;
960*3088717bSVictor Perevertkin
961*3088717bSVictor Perevertkin //
962*3088717bSVictor Perevertkin // Find the mode page
963*3088717bSVictor Perevertkin //
964*3088717bSVictor Perevertkin pageData = ClassFindModePage((PCHAR) ModeData,
965*3088717bSVictor Perevertkin size,
966*3088717bSVictor Perevertkin PageMode,
967*3088717bSVictor Perevertkin TRUE);
968*3088717bSVictor Perevertkin
969*3088717bSVictor Perevertkin if (pageData) {
970*3088717bSVictor Perevertkin *PageData = pageData;
971*3088717bSVictor Perevertkin return STATUS_SUCCESS;
972*3088717bSVictor Perevertkin } else {
973*3088717bSVictor Perevertkin *PageData = NULL;
974*3088717bSVictor Perevertkin return STATUS_NOT_SUPPORTED;
975*3088717bSVictor Perevertkin }
976*3088717bSVictor Perevertkin }
977*3088717bSVictor Perevertkin
978*3088717bSVictor Perevertkin NTSTATUS
DiskEnableInfoExceptions(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ BOOLEAN Enable)979*3088717bSVictor Perevertkin DiskEnableInfoExceptions(
980*3088717bSVictor Perevertkin _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
981*3088717bSVictor Perevertkin _In_ BOOLEAN Enable
982*3088717bSVictor Perevertkin )
983*3088717bSVictor Perevertkin {
984*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(FdoExtension->CommonExtension.DriverData);
985*3088717bSVictor Perevertkin NTSTATUS status = STATUS_NOT_SUPPORTED;
986*3088717bSVictor Perevertkin PMODE_PARAMETER_HEADER modeData;
987*3088717bSVictor Perevertkin PMODE_INFO_EXCEPTIONS pageData;
988*3088717bSVictor Perevertkin MODE_INFO_EXCEPTIONS changeablePageData;
989*3088717bSVictor Perevertkin ULONG modeDataSize;
990*3088717bSVictor Perevertkin
991*3088717bSVictor Perevertkin PAGED_CODE();
992*3088717bSVictor Perevertkin
993*3088717bSVictor Perevertkin modeDataSize = MODE_DATA_SIZE;
994*3088717bSVictor Perevertkin
995*3088717bSVictor Perevertkin modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
996*3088717bSVictor Perevertkin modeDataSize,
997*3088717bSVictor Perevertkin DISK_TAG_INFO_EXCEPTION);
998*3088717bSVictor Perevertkin
999*3088717bSVictor Perevertkin if (modeData == NULL) {
1000*3088717bSVictor Perevertkin
1001*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: Unable to allocate mode "
1002*3088717bSVictor Perevertkin "data buffer\n"));
1003*3088717bSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1004*3088717bSVictor Perevertkin }
1005*3088717bSVictor Perevertkin
1006*3088717bSVictor Perevertkin //
1007*3088717bSVictor Perevertkin // First see which data is actually changeable.
1008*3088717bSVictor Perevertkin //
1009*3088717bSVictor Perevertkin status = DiskGetModePage(FdoExtension->DeviceObject,
1010*3088717bSVictor Perevertkin MODE_PAGE_FAULT_REPORTING,
1011*3088717bSVictor Perevertkin 1, // Page Control = 1 indicates we want changeable values.
1012*3088717bSVictor Perevertkin modeData,
1013*3088717bSVictor Perevertkin &modeDataSize,
1014*3088717bSVictor Perevertkin (PVOID*)&pageData);
1015*3088717bSVictor Perevertkin
1016*3088717bSVictor Perevertkin if (!NT_SUCCESS(status) || pageData == NULL) {
1017*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: does NOT support SMART for device %p\n",
1018*3088717bSVictor Perevertkin FdoExtension->DeviceObject));
1019*3088717bSVictor Perevertkin FREE_POOL(modeData);
1020*3088717bSVictor Perevertkin return STATUS_NOT_SUPPORTED;
1021*3088717bSVictor Perevertkin }
1022*3088717bSVictor Perevertkin
1023*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: DOES support SMART for device %p\n",
1024*3088717bSVictor Perevertkin FdoExtension->DeviceObject));
1025*3088717bSVictor Perevertkin
1026*3088717bSVictor Perevertkin //
1027*3088717bSVictor Perevertkin // At the very least, the DEXCPT bit must be changeable.
1028*3088717bSVictor Perevertkin // If it's not, bail out now.
1029*3088717bSVictor Perevertkin //
1030*3088717bSVictor Perevertkin if (pageData->Dexcpt == 0) {
1031*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: does NOT support DEXCPT bit for device %p\n",
1032*3088717bSVictor Perevertkin FdoExtension->DeviceObject));
1033*3088717bSVictor Perevertkin FREE_POOL(modeData);
1034*3088717bSVictor Perevertkin return STATUS_NOT_SUPPORTED;
1035*3088717bSVictor Perevertkin }
1036*3088717bSVictor Perevertkin
1037*3088717bSVictor Perevertkin //
1038*3088717bSVictor Perevertkin // Cache away which values are changeable.
1039*3088717bSVictor Perevertkin //
1040*3088717bSVictor Perevertkin RtlCopyMemory(&changeablePageData, pageData, sizeof(MODE_INFO_EXCEPTIONS));
1041*3088717bSVictor Perevertkin
1042*3088717bSVictor Perevertkin //
1043*3088717bSVictor Perevertkin // Now get the current values.
1044*3088717bSVictor Perevertkin //
1045*3088717bSVictor Perevertkin status = DiskGetModePage(FdoExtension->DeviceObject,
1046*3088717bSVictor Perevertkin MODE_PAGE_FAULT_REPORTING,
1047*3088717bSVictor Perevertkin 0, // Page Control = 0 indicates we want current values.
1048*3088717bSVictor Perevertkin modeData,
1049*3088717bSVictor Perevertkin &modeDataSize,
1050*3088717bSVictor Perevertkin (PVOID*)&pageData);
1051*3088717bSVictor Perevertkin
1052*3088717bSVictor Perevertkin if (!NT_SUCCESS(status) || pageData == NULL) {
1053*3088717bSVictor Perevertkin //
1054*3088717bSVictor Perevertkin // At this point we know the device supports this mode page so
1055*3088717bSVictor Perevertkin // assert if something goes wrong here.
1056*3088717bSVictor Perevertkin //
1057*3088717bSVictor Perevertkin NT_ASSERT(NT_SUCCESS(status) && pageData);
1058*3088717bSVictor Perevertkin FREE_POOL(modeData);
1059*3088717bSVictor Perevertkin return STATUS_NOT_SUPPORTED;
1060*3088717bSVictor Perevertkin }
1061*3088717bSVictor Perevertkin
1062*3088717bSVictor Perevertkin //
1063*3088717bSVictor Perevertkin // If the device is currently configured to not report any informational
1064*3088717bSVictor Perevertkin // exceptions and we cannot change the value of that field, there's
1065*3088717bSVictor Perevertkin // nothing to be done.
1066*3088717bSVictor Perevertkin //
1067*3088717bSVictor Perevertkin if (pageData->ReportMethod == 0 && changeablePageData.ReportMethod == 0) {
1068*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskEnableInfoExceptions: MRIE field is 0 and is not changeable for device %p\n",
1069*3088717bSVictor Perevertkin FdoExtension->DeviceObject));
1070*3088717bSVictor Perevertkin FREE_POOL(modeData);
1071*3088717bSVictor Perevertkin return STATUS_NOT_SUPPORTED;
1072*3088717bSVictor Perevertkin }
1073*3088717bSVictor Perevertkin
1074*3088717bSVictor Perevertkin //
1075*3088717bSVictor Perevertkin // If the PERF bit is changeable, set it now.
1076*3088717bSVictor Perevertkin //
1077*3088717bSVictor Perevertkin if (changeablePageData.Perf) {
1078*3088717bSVictor Perevertkin pageData->Perf = diskData->AllowFPPerfHit ? 0 : 1;
1079*3088717bSVictor Perevertkin }
1080*3088717bSVictor Perevertkin
1081*3088717bSVictor Perevertkin //
1082*3088717bSVictor Perevertkin // If the MRIE field is changeable, set it to 4 so that informational
1083*3088717bSVictor Perevertkin // exceptions get reported with the "Recovered Error" sense key.
1084*3088717bSVictor Perevertkin //
1085*3088717bSVictor Perevertkin if (changeablePageData.ReportMethod) {
1086*3088717bSVictor Perevertkin pageData->ReportMethod = 4;
1087*3088717bSVictor Perevertkin }
1088*3088717bSVictor Perevertkin
1089*3088717bSVictor Perevertkin //
1090*3088717bSVictor Perevertkin // Finally, set the DEXCPT bit appropriately to enable/disable
1091*3088717bSVictor Perevertkin // informational exception reporting and send the Mode Select.
1092*3088717bSVictor Perevertkin //
1093*3088717bSVictor Perevertkin pageData->Dexcpt = !Enable;
1094*3088717bSVictor Perevertkin
1095*3088717bSVictor Perevertkin status = ClassModeSelect(FdoExtension->DeviceObject,
1096*3088717bSVictor Perevertkin (PCHAR)modeData,
1097*3088717bSVictor Perevertkin modeDataSize,
1098*3088717bSVictor Perevertkin pageData->PSBit);
1099*3088717bSVictor Perevertkin
1100*3088717bSVictor Perevertkin //
1101*3088717bSVictor Perevertkin // Update the failure prediction state. Note that for this particular
1102*3088717bSVictor Perevertkin // mode FailurePredictionNone is used when it's not enabled.
1103*3088717bSVictor Perevertkin //
1104*3088717bSVictor Perevertkin if (NT_SUCCESS(status)) {
1105*3088717bSVictor Perevertkin if (Enable) {
1106*3088717bSVictor Perevertkin diskData->FailurePredictionCapability = FailurePredictionSense;
1107*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = TRUE;
1108*3088717bSVictor Perevertkin } else {
1109*3088717bSVictor Perevertkin diskData->FailurePredictionCapability = FailurePredictionNone;
1110*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = FALSE;
1111*3088717bSVictor Perevertkin }
1112*3088717bSVictor Perevertkin }
1113*3088717bSVictor Perevertkin
1114*3088717bSVictor Perevertkin FREE_POOL(modeData);
1115*3088717bSVictor Perevertkin
1116*3088717bSVictor Perevertkin return status;
1117*3088717bSVictor Perevertkin }
1118*3088717bSVictor Perevertkin #endif
1119*3088717bSVictor Perevertkin
1120*3088717bSVictor Perevertkin
1121*3088717bSVictor Perevertkin //
1122*3088717bSVictor Perevertkin // FP type independent routines
1123*3088717bSVictor Perevertkin //
1124*3088717bSVictor Perevertkin
1125*3088717bSVictor Perevertkin NTSTATUS
DiskEnableDisableFailurePrediction(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,BOOLEAN Enable)1126*3088717bSVictor Perevertkin DiskEnableDisableFailurePrediction(
1127*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1128*3088717bSVictor Perevertkin BOOLEAN Enable
1129*3088717bSVictor Perevertkin )
1130*3088717bSVictor Perevertkin /*++
1131*3088717bSVictor Perevertkin
1132*3088717bSVictor Perevertkin Routine Description:
1133*3088717bSVictor Perevertkin
1134*3088717bSVictor Perevertkin Enable or disable failure prediction at the hardware level
1135*3088717bSVictor Perevertkin
1136*3088717bSVictor Perevertkin Arguments:
1137*3088717bSVictor Perevertkin
1138*3088717bSVictor Perevertkin FdoExtension
1139*3088717bSVictor Perevertkin
1140*3088717bSVictor Perevertkin Enable
1141*3088717bSVictor Perevertkin
1142*3088717bSVictor Perevertkin Return Value:
1143*3088717bSVictor Perevertkin
1144*3088717bSVictor Perevertkin NT Status
1145*3088717bSVictor Perevertkin
1146*3088717bSVictor Perevertkin --*/
1147*3088717bSVictor Perevertkin {
1148*3088717bSVictor Perevertkin NTSTATUS status;
1149*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
1150*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1151*3088717bSVictor Perevertkin
1152*3088717bSVictor Perevertkin PAGED_CODE();
1153*3088717bSVictor Perevertkin
1154*3088717bSVictor Perevertkin switch(diskData->FailurePredictionCapability)
1155*3088717bSVictor Perevertkin {
1156*3088717bSVictor Perevertkin case FailurePredictionSmart:
1157*3088717bSVictor Perevertkin {
1158*3088717bSVictor Perevertkin if (Enable)
1159*3088717bSVictor Perevertkin {
1160*3088717bSVictor Perevertkin status = DiskEnableSmart(FdoExtension);
1161*3088717bSVictor Perevertkin } else {
1162*3088717bSVictor Perevertkin status = DiskDisableSmart(FdoExtension);
1163*3088717bSVictor Perevertkin }
1164*3088717bSVictor Perevertkin
1165*3088717bSVictor Perevertkin if (NT_SUCCESS(status)) {
1166*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = Enable;
1167*3088717bSVictor Perevertkin }
1168*3088717bSVictor Perevertkin
1169*3088717bSVictor Perevertkin break;
1170*3088717bSVictor Perevertkin }
1171*3088717bSVictor Perevertkin
1172*3088717bSVictor Perevertkin case FailurePredictionSense:
1173*3088717bSVictor Perevertkin case FailurePredictionIoctl:
1174*3088717bSVictor Perevertkin {
1175*3088717bSVictor Perevertkin //
1176*3088717bSVictor Perevertkin // We assume that the drive is already setup properly for
1177*3088717bSVictor Perevertkin // failure prediction
1178*3088717bSVictor Perevertkin //
1179*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
1180*3088717bSVictor Perevertkin break;
1181*3088717bSVictor Perevertkin }
1182*3088717bSVictor Perevertkin
1183*3088717bSVictor Perevertkin default:
1184*3088717bSVictor Perevertkin {
1185*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
1186*3088717bSVictor Perevertkin }
1187*3088717bSVictor Perevertkin }
1188*3088717bSVictor Perevertkin return status;
1189*3088717bSVictor Perevertkin }
1190*3088717bSVictor Perevertkin
1191*3088717bSVictor Perevertkin
1192*3088717bSVictor Perevertkin NTSTATUS
DiskEnableDisableFailurePredictPolling(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,BOOLEAN Enable,ULONG PollTimeInSeconds)1193*3088717bSVictor Perevertkin DiskEnableDisableFailurePredictPolling(
1194*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1195*3088717bSVictor Perevertkin BOOLEAN Enable,
1196*3088717bSVictor Perevertkin ULONG PollTimeInSeconds
1197*3088717bSVictor Perevertkin )
1198*3088717bSVictor Perevertkin /*++
1199*3088717bSVictor Perevertkin
1200*3088717bSVictor Perevertkin Routine Description:
1201*3088717bSVictor Perevertkin
1202*3088717bSVictor Perevertkin Enable or disable polling for hardware failure detection
1203*3088717bSVictor Perevertkin
1204*3088717bSVictor Perevertkin Arguments:
1205*3088717bSVictor Perevertkin
1206*3088717bSVictor Perevertkin FdoExtension
1207*3088717bSVictor Perevertkin
1208*3088717bSVictor Perevertkin Enable
1209*3088717bSVictor Perevertkin
1210*3088717bSVictor Perevertkin PollTimeInSeconds - if 0 then no change to current polling timer
1211*3088717bSVictor Perevertkin
1212*3088717bSVictor Perevertkin Return Value:
1213*3088717bSVictor Perevertkin
1214*3088717bSVictor Perevertkin NT Status
1215*3088717bSVictor Perevertkin
1216*3088717bSVictor Perevertkin --*/
1217*3088717bSVictor Perevertkin {
1218*3088717bSVictor Perevertkin NTSTATUS status;
1219*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
1220*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1221*3088717bSVictor Perevertkin
1222*3088717bSVictor Perevertkin PAGED_CODE();
1223*3088717bSVictor Perevertkin
1224*3088717bSVictor Perevertkin if (Enable)
1225*3088717bSVictor Perevertkin {
1226*3088717bSVictor Perevertkin status = DiskEnableDisableFailurePrediction(FdoExtension,
1227*3088717bSVictor Perevertkin Enable);
1228*3088717bSVictor Perevertkin } else {
1229*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
1230*3088717bSVictor Perevertkin }
1231*3088717bSVictor Perevertkin
1232*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
1233*3088717bSVictor Perevertkin {
1234*3088717bSVictor Perevertkin status = ClassSetFailurePredictionPoll(FdoExtension,
1235*3088717bSVictor Perevertkin Enable ? diskData->FailurePredictionCapability :
1236*3088717bSVictor Perevertkin FailurePredictionNone,
1237*3088717bSVictor Perevertkin PollTimeInSeconds);
1238*3088717bSVictor Perevertkin
1239*3088717bSVictor Perevertkin //
1240*3088717bSVictor Perevertkin // Even if this failed we do not want to disable FP on the
1241*3088717bSVictor Perevertkin // hardware. FP is only ever disabled on the hardware by
1242*3088717bSVictor Perevertkin // specific command of the user.
1243*3088717bSVictor Perevertkin //
1244*3088717bSVictor Perevertkin }
1245*3088717bSVictor Perevertkin
1246*3088717bSVictor Perevertkin return status;
1247*3088717bSVictor Perevertkin }
1248*3088717bSVictor Perevertkin
1249*3088717bSVictor Perevertkin
1250*3088717bSVictor Perevertkin NTSTATUS
DiskReadFailurePredictStatus(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus)1251*3088717bSVictor Perevertkin DiskReadFailurePredictStatus(
1252*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1253*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus
1254*3088717bSVictor Perevertkin )
1255*3088717bSVictor Perevertkin /*++
1256*3088717bSVictor Perevertkin
1257*3088717bSVictor Perevertkin Routine Description:
1258*3088717bSVictor Perevertkin
1259*3088717bSVictor Perevertkin Obtains current failure prediction status
1260*3088717bSVictor Perevertkin
1261*3088717bSVictor Perevertkin Arguments:
1262*3088717bSVictor Perevertkin
1263*3088717bSVictor Perevertkin FdoExtension
1264*3088717bSVictor Perevertkin
1265*3088717bSVictor Perevertkin DiskSmartStatus
1266*3088717bSVictor Perevertkin
1267*3088717bSVictor Perevertkin Return Value:
1268*3088717bSVictor Perevertkin
1269*3088717bSVictor Perevertkin NT Status
1270*3088717bSVictor Perevertkin
1271*3088717bSVictor Perevertkin --*/
1272*3088717bSVictor Perevertkin {
1273*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
1274*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1275*3088717bSVictor Perevertkin NTSTATUS status;
1276*3088717bSVictor Perevertkin
1277*3088717bSVictor Perevertkin PAGED_CODE();
1278*3088717bSVictor Perevertkin
1279*3088717bSVictor Perevertkin DiskSmartStatus->PredictFailure = FALSE;
1280*3088717bSVictor Perevertkin
1281*3088717bSVictor Perevertkin switch(diskData->FailurePredictionCapability)
1282*3088717bSVictor Perevertkin {
1283*3088717bSVictor Perevertkin case FailurePredictionSmart:
1284*3088717bSVictor Perevertkin {
1285*3088717bSVictor Perevertkin UCHAR outBuffer[sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS) )] = {0};
1286*3088717bSVictor Perevertkin ULONG outBufferSize = sizeof(outBuffer);
1287*3088717bSVictor Perevertkin PSENDCMDOUTPARAMS cmdOutParameters;
1288*3088717bSVictor Perevertkin
1289*3088717bSVictor Perevertkin status = DiskReadSmartStatus(FdoExtension,
1290*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)outBuffer,
1291*3088717bSVictor Perevertkin &outBufferSize);
1292*3088717bSVictor Perevertkin
1293*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
1294*3088717bSVictor Perevertkin {
1295*3088717bSVictor Perevertkin cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
1296*3088717bSVictor Perevertkin sizeof(SRB_IO_CONTROL));
1297*3088717bSVictor Perevertkin
1298*3088717bSVictor Perevertkin DiskSmartStatus->Reason = 0; // Unknown;
1299*3088717bSVictor Perevertkin DiskSmartStatus->PredictFailure = ((cmdOutParameters->bBuffer[3] == 0xf4) &&
1300*3088717bSVictor Perevertkin (cmdOutParameters->bBuffer[4] == 0x2c));
1301*3088717bSVictor Perevertkin }
1302*3088717bSVictor Perevertkin break;
1303*3088717bSVictor Perevertkin }
1304*3088717bSVictor Perevertkin
1305*3088717bSVictor Perevertkin case FailurePredictionSense:
1306*3088717bSVictor Perevertkin {
1307*3088717bSVictor Perevertkin DiskSmartStatus->Reason = FdoExtension->FailureReason;
1308*3088717bSVictor Perevertkin DiskSmartStatus->PredictFailure = FdoExtension->FailurePredicted;
1309*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
1310*3088717bSVictor Perevertkin break;
1311*3088717bSVictor Perevertkin }
1312*3088717bSVictor Perevertkin
1313*3088717bSVictor Perevertkin case FailurePredictionIoctl:
1314*3088717bSVictor Perevertkin case FailurePredictionNone:
1315*3088717bSVictor Perevertkin default:
1316*3088717bSVictor Perevertkin {
1317*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
1318*3088717bSVictor Perevertkin break;
1319*3088717bSVictor Perevertkin }
1320*3088717bSVictor Perevertkin }
1321*3088717bSVictor Perevertkin
1322*3088717bSVictor Perevertkin return status;
1323*3088717bSVictor Perevertkin }
1324*3088717bSVictor Perevertkin
1325*3088717bSVictor Perevertkin
1326*3088717bSVictor Perevertkin NTSTATUS
DiskReadFailurePredictData(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData)1327*3088717bSVictor Perevertkin DiskReadFailurePredictData(
1328*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1329*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData
1330*3088717bSVictor Perevertkin )
1331*3088717bSVictor Perevertkin /*++
1332*3088717bSVictor Perevertkin
1333*3088717bSVictor Perevertkin Routine Description:
1334*3088717bSVictor Perevertkin
1335*3088717bSVictor Perevertkin Obtains current failure prediction data. Not available for
1336*3088717bSVictor Perevertkin FAILURE_PREDICT_SENSE types.
1337*3088717bSVictor Perevertkin
1338*3088717bSVictor Perevertkin Arguments:
1339*3088717bSVictor Perevertkin
1340*3088717bSVictor Perevertkin FdoExtension
1341*3088717bSVictor Perevertkin
1342*3088717bSVictor Perevertkin DiskSmartData
1343*3088717bSVictor Perevertkin
1344*3088717bSVictor Perevertkin Return Value:
1345*3088717bSVictor Perevertkin
1346*3088717bSVictor Perevertkin NT Status
1347*3088717bSVictor Perevertkin
1348*3088717bSVictor Perevertkin --*/
1349*3088717bSVictor Perevertkin {
1350*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
1351*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1352*3088717bSVictor Perevertkin NTSTATUS status;
1353*3088717bSVictor Perevertkin
1354*3088717bSVictor Perevertkin PAGED_CODE();
1355*3088717bSVictor Perevertkin
1356*3088717bSVictor Perevertkin switch(diskData->FailurePredictionCapability)
1357*3088717bSVictor Perevertkin {
1358*3088717bSVictor Perevertkin case FailurePredictionSmart:
1359*3088717bSVictor Perevertkin {
1360*3088717bSVictor Perevertkin PUCHAR outBuffer;
1361*3088717bSVictor Perevertkin ULONG outBufferSize;
1362*3088717bSVictor Perevertkin PSENDCMDOUTPARAMS cmdOutParameters;
1363*3088717bSVictor Perevertkin
1364*3088717bSVictor Perevertkin outBufferSize = sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE );
1365*3088717bSVictor Perevertkin
1366*3088717bSVictor Perevertkin outBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
1367*3088717bSVictor Perevertkin outBufferSize,
1368*3088717bSVictor Perevertkin DISK_TAG_SMART);
1369*3088717bSVictor Perevertkin
1370*3088717bSVictor Perevertkin if (outBuffer != NULL)
1371*3088717bSVictor Perevertkin {
1372*3088717bSVictor Perevertkin status = DiskReadSmartData(FdoExtension,
1373*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)outBuffer,
1374*3088717bSVictor Perevertkin &outBufferSize);
1375*3088717bSVictor Perevertkin
1376*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
1377*3088717bSVictor Perevertkin {
1378*3088717bSVictor Perevertkin cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
1379*3088717bSVictor Perevertkin sizeof(SRB_IO_CONTROL));
1380*3088717bSVictor Perevertkin
1381*3088717bSVictor Perevertkin DiskSmartData->Length = READ_ATTRIBUTE_BUFFER_SIZE;
1382*3088717bSVictor Perevertkin RtlCopyMemory(DiskSmartData->VendorSpecific,
1383*3088717bSVictor Perevertkin cmdOutParameters->bBuffer,
1384*3088717bSVictor Perevertkin min(READ_ATTRIBUTE_BUFFER_SIZE, sizeof(DiskSmartData->VendorSpecific)));
1385*3088717bSVictor Perevertkin }
1386*3088717bSVictor Perevertkin FREE_POOL(outBuffer);
1387*3088717bSVictor Perevertkin } else {
1388*3088717bSVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
1389*3088717bSVictor Perevertkin }
1390*3088717bSVictor Perevertkin
1391*3088717bSVictor Perevertkin break;
1392*3088717bSVictor Perevertkin }
1393*3088717bSVictor Perevertkin
1394*3088717bSVictor Perevertkin case FailurePredictionSense:
1395*3088717bSVictor Perevertkin {
1396*3088717bSVictor Perevertkin DiskSmartData->Length = sizeof(ULONG);
1397*3088717bSVictor Perevertkin *((PULONG)DiskSmartData->VendorSpecific) = FdoExtension->FailureReason;
1398*3088717bSVictor Perevertkin
1399*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
1400*3088717bSVictor Perevertkin break;
1401*3088717bSVictor Perevertkin }
1402*3088717bSVictor Perevertkin
1403*3088717bSVictor Perevertkin case FailurePredictionIoctl:
1404*3088717bSVictor Perevertkin case FailurePredictionNone:
1405*3088717bSVictor Perevertkin default:
1406*3088717bSVictor Perevertkin {
1407*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
1408*3088717bSVictor Perevertkin break;
1409*3088717bSVictor Perevertkin }
1410*3088717bSVictor Perevertkin }
1411*3088717bSVictor Perevertkin
1412*3088717bSVictor Perevertkin return status;
1413*3088717bSVictor Perevertkin }
1414*3088717bSVictor Perevertkin
1415*3088717bSVictor Perevertkin
1416*3088717bSVictor Perevertkin NTSTATUS
DiskReadFailurePredictThresholds(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds)1417*3088717bSVictor Perevertkin DiskReadFailurePredictThresholds(
1418*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1419*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_THRESHOLDS DiskSmartThresholds
1420*3088717bSVictor Perevertkin )
1421*3088717bSVictor Perevertkin /*++
1422*3088717bSVictor Perevertkin
1423*3088717bSVictor Perevertkin Routine Description:
1424*3088717bSVictor Perevertkin
1425*3088717bSVictor Perevertkin Obtains current failure prediction thresholds. Not available for
1426*3088717bSVictor Perevertkin FAILURE_PREDICT_SENSE types.
1427*3088717bSVictor Perevertkin
1428*3088717bSVictor Perevertkin Arguments:
1429*3088717bSVictor Perevertkin
1430*3088717bSVictor Perevertkin FdoExtension
1431*3088717bSVictor Perevertkin
1432*3088717bSVictor Perevertkin DiskSmartData
1433*3088717bSVictor Perevertkin
1434*3088717bSVictor Perevertkin Return Value:
1435*3088717bSVictor Perevertkin
1436*3088717bSVictor Perevertkin NT Status
1437*3088717bSVictor Perevertkin
1438*3088717bSVictor Perevertkin --*/
1439*3088717bSVictor Perevertkin {
1440*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
1441*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1442*3088717bSVictor Perevertkin NTSTATUS status;
1443*3088717bSVictor Perevertkin
1444*3088717bSVictor Perevertkin PAGED_CODE();
1445*3088717bSVictor Perevertkin
1446*3088717bSVictor Perevertkin switch(diskData->FailurePredictionCapability)
1447*3088717bSVictor Perevertkin {
1448*3088717bSVictor Perevertkin case FailurePredictionSmart:
1449*3088717bSVictor Perevertkin {
1450*3088717bSVictor Perevertkin PUCHAR outBuffer;
1451*3088717bSVictor Perevertkin PSENDCMDOUTPARAMS cmdOutParameters;
1452*3088717bSVictor Perevertkin ULONG outBufferSize;
1453*3088717bSVictor Perevertkin
1454*3088717bSVictor Perevertkin outBufferSize = sizeof(SRB_IO_CONTROL) + max( sizeof(SENDCMDINPARAMS), sizeof(SENDCMDOUTPARAMS) - 1 + READ_THRESHOLD_BUFFER_SIZE );
1455*3088717bSVictor Perevertkin
1456*3088717bSVictor Perevertkin outBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
1457*3088717bSVictor Perevertkin outBufferSize,
1458*3088717bSVictor Perevertkin DISK_TAG_SMART);
1459*3088717bSVictor Perevertkin
1460*3088717bSVictor Perevertkin if (outBuffer != NULL)
1461*3088717bSVictor Perevertkin {
1462*3088717bSVictor Perevertkin status = DiskReadSmartThresholds(FdoExtension,
1463*3088717bSVictor Perevertkin (PSRB_IO_CONTROL)outBuffer,
1464*3088717bSVictor Perevertkin &outBufferSize);
1465*3088717bSVictor Perevertkin
1466*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
1467*3088717bSVictor Perevertkin {
1468*3088717bSVictor Perevertkin cmdOutParameters = (PSENDCMDOUTPARAMS)(outBuffer +
1469*3088717bSVictor Perevertkin sizeof(SRB_IO_CONTROL));
1470*3088717bSVictor Perevertkin
1471*3088717bSVictor Perevertkin RtlCopyMemory(DiskSmartThresholds->VendorSpecific,
1472*3088717bSVictor Perevertkin cmdOutParameters->bBuffer,
1473*3088717bSVictor Perevertkin min(READ_THRESHOLD_BUFFER_SIZE, sizeof(DiskSmartThresholds->VendorSpecific)));
1474*3088717bSVictor Perevertkin }
1475*3088717bSVictor Perevertkin FREE_POOL(outBuffer);
1476*3088717bSVictor Perevertkin } else {
1477*3088717bSVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
1478*3088717bSVictor Perevertkin }
1479*3088717bSVictor Perevertkin
1480*3088717bSVictor Perevertkin break;
1481*3088717bSVictor Perevertkin }
1482*3088717bSVictor Perevertkin
1483*3088717bSVictor Perevertkin case FailurePredictionSense:
1484*3088717bSVictor Perevertkin case FailurePredictionIoctl:
1485*3088717bSVictor Perevertkin case FailurePredictionNone:
1486*3088717bSVictor Perevertkin default:
1487*3088717bSVictor Perevertkin {
1488*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
1489*3088717bSVictor Perevertkin break;
1490*3088717bSVictor Perevertkin }
1491*3088717bSVictor Perevertkin }
1492*3088717bSVictor Perevertkin
1493*3088717bSVictor Perevertkin return status;
1494*3088717bSVictor Perevertkin }
1495*3088717bSVictor Perevertkin
1496*3088717bSVictor Perevertkin
1497*3088717bSVictor Perevertkin VOID
1498*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskReregWorker(IN PDEVICE_OBJECT DevObject,IN PVOID Context)1499*3088717bSVictor Perevertkin DiskReregWorker(
1500*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DevObject,
1501*3088717bSVictor Perevertkin IN PVOID Context
1502*3088717bSVictor Perevertkin )
1503*3088717bSVictor Perevertkin {
1504*3088717bSVictor Perevertkin PDISKREREGREQUEST reregRequest;
1505*3088717bSVictor Perevertkin NTSTATUS status;
1506*3088717bSVictor Perevertkin PDEVICE_OBJECT deviceObject;
1507*3088717bSVictor Perevertkin PIRP irp;
1508*3088717bSVictor Perevertkin
1509*3088717bSVictor Perevertkin PAGED_CODE();
1510*3088717bSVictor Perevertkin UNREFERENCED_PARAMETER(DevObject);
1511*3088717bSVictor Perevertkin
1512*3088717bSVictor Perevertkin NT_ASSERT(Context != NULL);
1513*3088717bSVictor Perevertkin _Analysis_assume_(Context != NULL);
1514*3088717bSVictor Perevertkin
1515*3088717bSVictor Perevertkin do
1516*3088717bSVictor Perevertkin {
1517*3088717bSVictor Perevertkin reregRequest = (PDISKREREGREQUEST)ExInterlockedPopEntryList(
1518*3088717bSVictor Perevertkin &DiskReregHead,
1519*3088717bSVictor Perevertkin &DiskReregSpinlock);
1520*3088717bSVictor Perevertkin
1521*3088717bSVictor Perevertkin if (reregRequest != NULL)
1522*3088717bSVictor Perevertkin {
1523*3088717bSVictor Perevertkin deviceObject = reregRequest->DeviceObject;
1524*3088717bSVictor Perevertkin irp = reregRequest->Irp;
1525*3088717bSVictor Perevertkin
1526*3088717bSVictor Perevertkin status = IoWMIRegistrationControl(deviceObject,
1527*3088717bSVictor Perevertkin WMIREG_ACTION_UPDATE_GUIDS);
1528*3088717bSVictor Perevertkin
1529*3088717bSVictor Perevertkin //
1530*3088717bSVictor Perevertkin // Release remove lock and free irp, now that we are done
1531*3088717bSVictor Perevertkin // processing this
1532*3088717bSVictor Perevertkin //
1533*3088717bSVictor Perevertkin ClassReleaseRemoveLock(deviceObject, irp);
1534*3088717bSVictor Perevertkin
1535*3088717bSVictor Perevertkin IoFreeMdl(irp->MdlAddress);
1536*3088717bSVictor Perevertkin IoFreeIrp(irp);
1537*3088717bSVictor Perevertkin
1538*3088717bSVictor Perevertkin FREE_POOL(reregRequest);
1539*3088717bSVictor Perevertkin
1540*3088717bSVictor Perevertkin } else {
1541*3088717bSVictor Perevertkin
1542*3088717bSVictor Perevertkin NT_ASSERTMSG("Disk Re-registration request list should not be empty", FALSE);
1543*3088717bSVictor Perevertkin
1544*3088717bSVictor Perevertkin status = STATUS_INTERNAL_ERROR;
1545*3088717bSVictor Perevertkin }
1546*3088717bSVictor Perevertkin
1547*3088717bSVictor Perevertkin if (!NT_SUCCESS(status))
1548*3088717bSVictor Perevertkin {
1549*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskReregWorker: Reregistration failed %x\n",
1550*3088717bSVictor Perevertkin status));
1551*3088717bSVictor Perevertkin }
1552*3088717bSVictor Perevertkin
1553*3088717bSVictor Perevertkin } while (InterlockedDecrement(&DiskReregWorkItems));
1554*3088717bSVictor Perevertkin
1555*3088717bSVictor Perevertkin IoFreeWorkItem((PIO_WORKITEM)Context);
1556*3088717bSVictor Perevertkin }
1557*3088717bSVictor Perevertkin
1558*3088717bSVictor Perevertkin
1559*3088717bSVictor Perevertkin NTSTATUS
DiskInitializeReregistration(VOID)1560*3088717bSVictor Perevertkin DiskInitializeReregistration(
1561*3088717bSVictor Perevertkin VOID
1562*3088717bSVictor Perevertkin )
1563*3088717bSVictor Perevertkin {
1564*3088717bSVictor Perevertkin PAGED_CODE();
1565*3088717bSVictor Perevertkin
1566*3088717bSVictor Perevertkin //
1567*3088717bSVictor Perevertkin // Initialize the spinlock used to manage the
1568*3088717bSVictor Perevertkin // list of disks reregistering their guids
1569*3088717bSVictor Perevertkin //
1570*3088717bSVictor Perevertkin KeInitializeSpinLock(&DiskReregSpinlock);
1571*3088717bSVictor Perevertkin
1572*3088717bSVictor Perevertkin return(STATUS_SUCCESS);
1573*3088717bSVictor Perevertkin }
1574*3088717bSVictor Perevertkin
1575*3088717bSVictor Perevertkin
1576*3088717bSVictor Perevertkin NTSTATUS
DiskPostReregisterRequest(PDEVICE_OBJECT DeviceObject,PIRP Irp)1577*3088717bSVictor Perevertkin DiskPostReregisterRequest(
1578*3088717bSVictor Perevertkin PDEVICE_OBJECT DeviceObject,
1579*3088717bSVictor Perevertkin PIRP Irp
1580*3088717bSVictor Perevertkin )
1581*3088717bSVictor Perevertkin {
1582*3088717bSVictor Perevertkin PDISKREREGREQUEST reregRequest;
1583*3088717bSVictor Perevertkin PIO_WORKITEM workItem;
1584*3088717bSVictor Perevertkin NTSTATUS status;
1585*3088717bSVictor Perevertkin
1586*3088717bSVictor Perevertkin workItem = IoAllocateWorkItem(DeviceObject);
1587*3088717bSVictor Perevertkin
1588*3088717bSVictor Perevertkin if (!workItem) {
1589*3088717bSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
1590*3088717bSVictor Perevertkin }
1591*3088717bSVictor Perevertkin
1592*3088717bSVictor Perevertkin reregRequest = ExAllocatePoolWithTag(NonPagedPoolNx,
1593*3088717bSVictor Perevertkin sizeof(DISKREREGREQUEST),
1594*3088717bSVictor Perevertkin DISK_TAG_SMART);
1595*3088717bSVictor Perevertkin if (reregRequest != NULL)
1596*3088717bSVictor Perevertkin {
1597*3088717bSVictor Perevertkin //
1598*3088717bSVictor Perevertkin // add the disk that needs reregistration to the stack of disks
1599*3088717bSVictor Perevertkin // to reregister. If the list is transitioning from empty to
1600*3088717bSVictor Perevertkin // non empty then also kick off the work item so that the
1601*3088717bSVictor Perevertkin // reregistration worker can do the reregister.
1602*3088717bSVictor Perevertkin //
1603*3088717bSVictor Perevertkin reregRequest->DeviceObject = DeviceObject;
1604*3088717bSVictor Perevertkin reregRequest->Irp = Irp;
1605*3088717bSVictor Perevertkin ExInterlockedPushEntryList(
1606*3088717bSVictor Perevertkin &DiskReregHead,
1607*3088717bSVictor Perevertkin &reregRequest->Next,
1608*3088717bSVictor Perevertkin &DiskReregSpinlock);
1609*3088717bSVictor Perevertkin
1610*3088717bSVictor Perevertkin if (InterlockedIncrement(&DiskReregWorkItems) == 1)
1611*3088717bSVictor Perevertkin {
1612*3088717bSVictor Perevertkin //
1613*3088717bSVictor Perevertkin // There is no worker routine running, queue this one.
1614*3088717bSVictor Perevertkin // When the work item runs, it will process the reregistration
1615*3088717bSVictor Perevertkin // list.
1616*3088717bSVictor Perevertkin //
1617*3088717bSVictor Perevertkin
1618*3088717bSVictor Perevertkin IoQueueWorkItem(workItem,
1619*3088717bSVictor Perevertkin DiskReregWorker,
1620*3088717bSVictor Perevertkin DelayedWorkQueue,
1621*3088717bSVictor Perevertkin workItem);
1622*3088717bSVictor Perevertkin } else {
1623*3088717bSVictor Perevertkin
1624*3088717bSVictor Perevertkin //
1625*3088717bSVictor Perevertkin // There is a worker routine already running, so we
1626*3088717bSVictor Perevertkin // can free this unused work item.
1627*3088717bSVictor Perevertkin //
1628*3088717bSVictor Perevertkin
1629*3088717bSVictor Perevertkin IoFreeWorkItem(workItem);
1630*3088717bSVictor Perevertkin }
1631*3088717bSVictor Perevertkin
1632*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
1633*3088717bSVictor Perevertkin
1634*3088717bSVictor Perevertkin } else {
1635*3088717bSVictor Perevertkin
1636*3088717bSVictor Perevertkin IoFreeWorkItem(workItem);
1637*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskPostReregisterRequest: could not allocate reregRequest for %p\n",
1638*3088717bSVictor Perevertkin DeviceObject));
1639*3088717bSVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
1640*3088717bSVictor Perevertkin }
1641*3088717bSVictor Perevertkin
1642*3088717bSVictor Perevertkin return(status);
1643*3088717bSVictor Perevertkin }
1644*3088717bSVictor Perevertkin
1645*3088717bSVictor Perevertkin
1646*3088717bSVictor Perevertkin NTSTATUS
1647*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskInfoExceptionComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)1648*3088717bSVictor Perevertkin DiskInfoExceptionComplete(
1649*3088717bSVictor Perevertkin PDEVICE_OBJECT DeviceObject,
1650*3088717bSVictor Perevertkin PIRP Irp,
1651*3088717bSVictor Perevertkin PVOID Context
1652*3088717bSVictor Perevertkin )
1653*3088717bSVictor Perevertkin {
1654*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1655*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
1656*3088717bSVictor Perevertkin PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
1657*3088717bSVictor Perevertkin PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
1658*3088717bSVictor Perevertkin PSCSI_REQUEST_BLOCK srb = Context;
1659*3088717bSVictor Perevertkin NTSTATUS status;
1660*3088717bSVictor Perevertkin BOOLEAN retry;
1661*3088717bSVictor Perevertkin ULONG retryInterval;
1662*3088717bSVictor Perevertkin ULONG srbStatus;
1663*3088717bSVictor Perevertkin BOOLEAN freeLockAndIrp = TRUE;
1664*3088717bSVictor Perevertkin PVOID originalSenseInfoBuffer = irpStack->Parameters.Others.Argument3;
1665*3088717bSVictor Perevertkin PSTORAGE_REQUEST_BLOCK srbEx = NULL;
1666*3088717bSVictor Perevertkin PVOID dataBuffer = NULL;
1667*3088717bSVictor Perevertkin ULONG dataLength = 0;
1668*3088717bSVictor Perevertkin PVOID senseBuffer = NULL;
1669*3088717bSVictor Perevertkin UCHAR cdbLength8 = 0;
1670*3088717bSVictor Perevertkin ULONG cdbLength32 = 0;
1671*3088717bSVictor Perevertkin UCHAR senseBufferLength = 0;
1672*3088717bSVictor Perevertkin
1673*3088717bSVictor Perevertkin srbStatus = SRB_STATUS(srb->SrbStatus);
1674*3088717bSVictor Perevertkin
1675*3088717bSVictor Perevertkin if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) {
1676*3088717bSVictor Perevertkin srbEx = (PSTORAGE_REQUEST_BLOCK)srb;
1677*3088717bSVictor Perevertkin dataBuffer = srbEx->DataBuffer;
1678*3088717bSVictor Perevertkin dataLength = srbEx->DataTransferLength;
1679*3088717bSVictor Perevertkin if ((srbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) &&
1680*3088717bSVictor Perevertkin (srbEx->NumSrbExData > 0)) {
1681*3088717bSVictor Perevertkin (void)GetSrbScsiData(srbEx, &cdbLength8, &cdbLength32, NULL, &senseBuffer, &senseBufferLength);
1682*3088717bSVictor Perevertkin }
1683*3088717bSVictor Perevertkin } else {
1684*3088717bSVictor Perevertkin dataBuffer = srb->DataBuffer;
1685*3088717bSVictor Perevertkin dataLength = srb->DataTransferLength;
1686*3088717bSVictor Perevertkin senseBuffer = srb->SenseInfoBuffer;
1687*3088717bSVictor Perevertkin }
1688*3088717bSVictor Perevertkin
1689*3088717bSVictor Perevertkin //
1690*3088717bSVictor Perevertkin // Check SRB status for success of completing request.
1691*3088717bSVictor Perevertkin // SRB_STATUS_DATA_OVERRUN also indicates success.
1692*3088717bSVictor Perevertkin //
1693*3088717bSVictor Perevertkin if ((srbStatus != SRB_STATUS_SUCCESS) &&
1694*3088717bSVictor Perevertkin (srbStatus != SRB_STATUS_DATA_OVERRUN))
1695*3088717bSVictor Perevertkin {
1696*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskInfoExceptionComplete: IRP %p, SRB %p\n", Irp, srb));
1697*3088717bSVictor Perevertkin
1698*3088717bSVictor Perevertkin if (TEST_FLAG(srb->SrbStatus, SRB_STATUS_QUEUE_FROZEN))
1699*3088717bSVictor Perevertkin {
1700*3088717bSVictor Perevertkin ClassReleaseQueue(DeviceObject);
1701*3088717bSVictor Perevertkin }
1702*3088717bSVictor Perevertkin
1703*3088717bSVictor Perevertkin retry = ClassInterpretSenseInfo(
1704*3088717bSVictor Perevertkin DeviceObject,
1705*3088717bSVictor Perevertkin srb,
1706*3088717bSVictor Perevertkin irpStack->MajorFunction,
1707*3088717bSVictor Perevertkin 0,
1708*3088717bSVictor Perevertkin MAXIMUM_RETRIES -
1709*3088717bSVictor Perevertkin ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
1710*3088717bSVictor Perevertkin &status,
1711*3088717bSVictor Perevertkin &retryInterval);
1712*3088717bSVictor Perevertkin
1713*3088717bSVictor Perevertkin //
1714*3088717bSVictor Perevertkin // If the status is verified required and the this request
1715*3088717bSVictor Perevertkin // should bypass verify required then retry the request.
1716*3088717bSVictor Perevertkin //
1717*3088717bSVictor Perevertkin
1718*3088717bSVictor Perevertkin if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
1719*3088717bSVictor Perevertkin status == STATUS_VERIFY_REQUIRED)
1720*3088717bSVictor Perevertkin {
1721*3088717bSVictor Perevertkin status = STATUS_IO_DEVICE_ERROR;
1722*3088717bSVictor Perevertkin retry = TRUE;
1723*3088717bSVictor Perevertkin }
1724*3088717bSVictor Perevertkin
1725*3088717bSVictor Perevertkin retry = retry && irpStack->Parameters.Others.Argument4;
1726*3088717bSVictor Perevertkin
1727*3088717bSVictor Perevertkin irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4 - 1);
1728*3088717bSVictor Perevertkin
1729*3088717bSVictor Perevertkin if (retry)
1730*3088717bSVictor Perevertkin {
1731*3088717bSVictor Perevertkin //
1732*3088717bSVictor Perevertkin // Retry request.
1733*3088717bSVictor Perevertkin //
1734*3088717bSVictor Perevertkin
1735*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskInfoExceptionComplete: Retry request %p\n", Irp));
1736*3088717bSVictor Perevertkin
1737*3088717bSVictor Perevertkin NT_ASSERT(dataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
1738*3088717bSVictor Perevertkin
1739*3088717bSVictor Perevertkin if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) {
1740*3088717bSVictor Perevertkin
1741*3088717bSVictor Perevertkin //
1742*3088717bSVictor Perevertkin // Reset byte count of transfer in SRB Extension.
1743*3088717bSVictor Perevertkin //
1744*3088717bSVictor Perevertkin srbEx->DataTransferLength = Irp->MdlAddress->ByteCount;
1745*3088717bSVictor Perevertkin
1746*3088717bSVictor Perevertkin //
1747*3088717bSVictor Perevertkin // Zero SRB statuses.
1748*3088717bSVictor Perevertkin //
1749*3088717bSVictor Perevertkin
1750*3088717bSVictor Perevertkin srbEx->SrbStatus = 0;
1751*3088717bSVictor Perevertkin if ((srbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) &&
1752*3088717bSVictor Perevertkin (srbEx->NumSrbExData > 0)) {
1753*3088717bSVictor Perevertkin SetSrbScsiData(srbEx, cdbLength8, cdbLength32, 0, senseBuffer, senseBufferLength);
1754*3088717bSVictor Perevertkin }
1755*3088717bSVictor Perevertkin
1756*3088717bSVictor Perevertkin //
1757*3088717bSVictor Perevertkin // Set the no disconnect flag, disable synchronous data transfers and
1758*3088717bSVictor Perevertkin // disable tagged queuing. This fixes some errors.
1759*3088717bSVictor Perevertkin //
1760*3088717bSVictor Perevertkin
1761*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
1762*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
1763*3088717bSVictor Perevertkin CLEAR_FLAG(srbEx->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
1764*3088717bSVictor Perevertkin
1765*3088717bSVictor Perevertkin srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
1766*3088717bSVictor Perevertkin srbEx->RequestTag = SP_UNTAGGED;
1767*3088717bSVictor Perevertkin
1768*3088717bSVictor Perevertkin } else {
1769*3088717bSVictor Perevertkin
1770*3088717bSVictor Perevertkin //
1771*3088717bSVictor Perevertkin // Reset byte count of transfer in SRB Extension.
1772*3088717bSVictor Perevertkin //
1773*3088717bSVictor Perevertkin srb->DataTransferLength = Irp->MdlAddress->ByteCount;
1774*3088717bSVictor Perevertkin
1775*3088717bSVictor Perevertkin //
1776*3088717bSVictor Perevertkin // Zero SRB statuses.
1777*3088717bSVictor Perevertkin //
1778*3088717bSVictor Perevertkin
1779*3088717bSVictor Perevertkin srb->SrbStatus = srb->ScsiStatus = 0;
1780*3088717bSVictor Perevertkin
1781*3088717bSVictor Perevertkin //
1782*3088717bSVictor Perevertkin // Set the no disconnect flag, disable synchronous data transfers and
1783*3088717bSVictor Perevertkin // disable tagged queuing. This fixes some errors.
1784*3088717bSVictor Perevertkin //
1785*3088717bSVictor Perevertkin
1786*3088717bSVictor Perevertkin SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
1787*3088717bSVictor Perevertkin SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
1788*3088717bSVictor Perevertkin CLEAR_FLAG(srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
1789*3088717bSVictor Perevertkin
1790*3088717bSVictor Perevertkin srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
1791*3088717bSVictor Perevertkin srb->QueueTag = SP_UNTAGGED;
1792*3088717bSVictor Perevertkin }
1793*3088717bSVictor Perevertkin
1794*3088717bSVictor Perevertkin //
1795*3088717bSVictor Perevertkin // Set up major SCSI function.
1796*3088717bSVictor Perevertkin //
1797*3088717bSVictor Perevertkin
1798*3088717bSVictor Perevertkin nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1799*3088717bSVictor Perevertkin
1800*3088717bSVictor Perevertkin //
1801*3088717bSVictor Perevertkin // Save SRB address in next stack for port driver.
1802*3088717bSVictor Perevertkin //
1803*3088717bSVictor Perevertkin
1804*3088717bSVictor Perevertkin nextIrpStack->Parameters.Scsi.Srb = srb;
1805*3088717bSVictor Perevertkin
1806*3088717bSVictor Perevertkin
1807*3088717bSVictor Perevertkin IoSetCompletionRoutine(Irp,
1808*3088717bSVictor Perevertkin DiskInfoExceptionComplete,
1809*3088717bSVictor Perevertkin srb,
1810*3088717bSVictor Perevertkin TRUE, TRUE, TRUE);
1811*3088717bSVictor Perevertkin
1812*3088717bSVictor Perevertkin (VOID)IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1813*3088717bSVictor Perevertkin
1814*3088717bSVictor Perevertkin return STATUS_MORE_PROCESSING_REQUIRED;
1815*3088717bSVictor Perevertkin }
1816*3088717bSVictor Perevertkin
1817*3088717bSVictor Perevertkin } else {
1818*3088717bSVictor Perevertkin
1819*3088717bSVictor Perevertkin //
1820*3088717bSVictor Perevertkin // Get the results from the mode sense
1821*3088717bSVictor Perevertkin //
1822*3088717bSVictor Perevertkin PMODE_INFO_EXCEPTIONS pageData;
1823*3088717bSVictor Perevertkin PMODE_PARAMETER_HEADER modeData;
1824*3088717bSVictor Perevertkin ULONG modeDataLength;
1825*3088717bSVictor Perevertkin
1826*3088717bSVictor Perevertkin modeData = dataBuffer;
1827*3088717bSVictor Perevertkin modeDataLength = dataLength;
1828*3088717bSVictor Perevertkin
1829*3088717bSVictor Perevertkin pageData = ClassFindModePage((PCHAR)modeData,
1830*3088717bSVictor Perevertkin modeDataLength,
1831*3088717bSVictor Perevertkin MODE_PAGE_FAULT_REPORTING,
1832*3088717bSVictor Perevertkin TRUE);
1833*3088717bSVictor Perevertkin if (pageData != NULL)
1834*3088717bSVictor Perevertkin {
1835*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskInfoExceptionComplete: %p supports SMART\n",
1836*3088717bSVictor Perevertkin DeviceObject));
1837*3088717bSVictor Perevertkin
1838*3088717bSVictor Perevertkin diskData->ScsiInfoExceptionsSupported = TRUE;
1839*3088717bSVictor Perevertkin
1840*3088717bSVictor Perevertkin //
1841*3088717bSVictor Perevertkin // The DEXCPT bit must be 0 and the MRIE field must be valid.
1842*3088717bSVictor Perevertkin //
1843*3088717bSVictor Perevertkin if (pageData->Dexcpt == 0 &&
1844*3088717bSVictor Perevertkin pageData->ReportMethod >= 2 &&
1845*3088717bSVictor Perevertkin pageData->ReportMethod <= 6)
1846*3088717bSVictor Perevertkin {
1847*3088717bSVictor Perevertkin diskData->FailurePredictionCapability = FailurePredictionSense;
1848*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = TRUE;
1849*3088717bSVictor Perevertkin status = DiskPostReregisterRequest(DeviceObject, Irp);
1850*3088717bSVictor Perevertkin
1851*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
1852*3088717bSVictor Perevertkin {
1853*3088717bSVictor Perevertkin //
1854*3088717bSVictor Perevertkin // Make sure we won't free the remove lock and the irp
1855*3088717bSVictor Perevertkin // since we need to keep these until after the work
1856*3088717bSVictor Perevertkin // item has completed running
1857*3088717bSVictor Perevertkin //
1858*3088717bSVictor Perevertkin freeLockAndIrp = FALSE;
1859*3088717bSVictor Perevertkin }
1860*3088717bSVictor Perevertkin } else {
1861*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionComplete: %p is not enabled for SMART\n",
1862*3088717bSVictor Perevertkin DeviceObject));
1863*3088717bSVictor Perevertkin
1864*3088717bSVictor Perevertkin }
1865*3088717bSVictor Perevertkin
1866*3088717bSVictor Perevertkin } else {
1867*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionComplete: %p does not supports SMART\n",
1868*3088717bSVictor Perevertkin DeviceObject));
1869*3088717bSVictor Perevertkin
1870*3088717bSVictor Perevertkin }
1871*3088717bSVictor Perevertkin
1872*3088717bSVictor Perevertkin //
1873*3088717bSVictor Perevertkin // Set status for successful request
1874*3088717bSVictor Perevertkin //
1875*3088717bSVictor Perevertkin
1876*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
1877*3088717bSVictor Perevertkin
1878*3088717bSVictor Perevertkin } // end if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)
1879*3088717bSVictor Perevertkin
1880*3088717bSVictor Perevertkin //
1881*3088717bSVictor Perevertkin // Free the srb
1882*3088717bSVictor Perevertkin //
1883*3088717bSVictor Perevertkin if (senseBuffer != originalSenseInfoBuffer)
1884*3088717bSVictor Perevertkin {
1885*3088717bSVictor Perevertkin //
1886*3088717bSVictor Perevertkin // Free the original sense info buffer in case the port driver has overwritten it
1887*3088717bSVictor Perevertkin //
1888*3088717bSVictor Perevertkin FREE_POOL(originalSenseInfoBuffer);
1889*3088717bSVictor Perevertkin }
1890*3088717bSVictor Perevertkin
1891*3088717bSVictor Perevertkin FREE_POOL(senseBuffer);
1892*3088717bSVictor Perevertkin FREE_POOL(dataBuffer);
1893*3088717bSVictor Perevertkin FREE_POOL(srb);
1894*3088717bSVictor Perevertkin
1895*3088717bSVictor Perevertkin if (freeLockAndIrp)
1896*3088717bSVictor Perevertkin {
1897*3088717bSVictor Perevertkin //
1898*3088717bSVictor Perevertkin // Set status in completing IRP.
1899*3088717bSVictor Perevertkin //
1900*3088717bSVictor Perevertkin
1901*3088717bSVictor Perevertkin Irp->IoStatus.Status = status;
1902*3088717bSVictor Perevertkin
1903*3088717bSVictor Perevertkin //
1904*3088717bSVictor Perevertkin // If pending has be returned for this irp then mark the current stack as
1905*3088717bSVictor Perevertkin // pending.
1906*3088717bSVictor Perevertkin //
1907*3088717bSVictor Perevertkin
1908*3088717bSVictor Perevertkin if (Irp->PendingReturned) {
1909*3088717bSVictor Perevertkin IoMarkIrpPending(Irp);
1910*3088717bSVictor Perevertkin }
1911*3088717bSVictor Perevertkin
1912*3088717bSVictor Perevertkin ClassReleaseRemoveLock(DeviceObject, Irp);
1913*3088717bSVictor Perevertkin IoFreeMdl(Irp->MdlAddress);
1914*3088717bSVictor Perevertkin IoFreeIrp(Irp);
1915*3088717bSVictor Perevertkin }
1916*3088717bSVictor Perevertkin
1917*3088717bSVictor Perevertkin return(STATUS_MORE_PROCESSING_REQUIRED);
1918*3088717bSVictor Perevertkin }
1919*3088717bSVictor Perevertkin
1920*3088717bSVictor Perevertkin
1921*3088717bSVictor Perevertkin NTSTATUS
DiskInfoExceptionCheck(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)1922*3088717bSVictor Perevertkin DiskInfoExceptionCheck(
1923*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1924*3088717bSVictor Perevertkin )
1925*3088717bSVictor Perevertkin {
1926*3088717bSVictor Perevertkin PUCHAR modeData;
1927*3088717bSVictor Perevertkin PSCSI_REQUEST_BLOCK srb;
1928*3088717bSVictor Perevertkin PCDB cdb;
1929*3088717bSVictor Perevertkin PIRP irp;
1930*3088717bSVictor Perevertkin PIO_STACK_LOCATION irpStack;
1931*3088717bSVictor Perevertkin PVOID senseInfoBuffer = NULL;
1932*3088717bSVictor Perevertkin UCHAR senseInfoBufferLength = 0;
1933*3088717bSVictor Perevertkin ULONG isRemoved;
1934*3088717bSVictor Perevertkin ULONG srbSize;
1935*3088717bSVictor Perevertkin PSTORAGE_REQUEST_BLOCK srbEx = NULL;
1936*3088717bSVictor Perevertkin PSTOR_ADDR_BTL8 storAddrBtl8 = NULL;
1937*3088717bSVictor Perevertkin PSRBEX_DATA_SCSI_CDB16 srbExDataCdb16 = NULL;
1938*3088717bSVictor Perevertkin
1939*3088717bSVictor Perevertkin modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
1940*3088717bSVictor Perevertkin MODE_DATA_SIZE,
1941*3088717bSVictor Perevertkin DISK_TAG_INFO_EXCEPTION);
1942*3088717bSVictor Perevertkin if (modeData == NULL)
1943*3088717bSVictor Perevertkin {
1944*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate mode data "
1945*3088717bSVictor Perevertkin "buffer\n"));
1946*3088717bSVictor Perevertkin return(STATUS_INSUFFICIENT_RESOURCES);
1947*3088717bSVictor Perevertkin }
1948*3088717bSVictor Perevertkin
1949*3088717bSVictor Perevertkin if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1950*3088717bSVictor Perevertkin srbSize = CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE;
1951*3088717bSVictor Perevertkin } else {
1952*3088717bSVictor Perevertkin srbSize = SCSI_REQUEST_BLOCK_SIZE;
1953*3088717bSVictor Perevertkin }
1954*3088717bSVictor Perevertkin srb = ExAllocatePoolWithTag(NonPagedPoolNx,
1955*3088717bSVictor Perevertkin srbSize,
1956*3088717bSVictor Perevertkin DISK_TAG_SRB);
1957*3088717bSVictor Perevertkin if (srb == NULL)
1958*3088717bSVictor Perevertkin {
1959*3088717bSVictor Perevertkin FREE_POOL(modeData);
1960*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate srb "
1961*3088717bSVictor Perevertkin "buffer\n"));
1962*3088717bSVictor Perevertkin return(STATUS_INSUFFICIENT_RESOURCES);
1963*3088717bSVictor Perevertkin }
1964*3088717bSVictor Perevertkin RtlZeroMemory(srb, srbSize);
1965*3088717bSVictor Perevertkin
1966*3088717bSVictor Perevertkin //
1967*3088717bSVictor Perevertkin // Sense buffer is in aligned nonpaged pool.
1968*3088717bSVictor Perevertkin //
1969*3088717bSVictor Perevertkin
1970*3088717bSVictor Perevertkin senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
1971*3088717bSVictor Perevertkin SENSE_BUFFER_SIZE_EX,
1972*3088717bSVictor Perevertkin '7CcS');
1973*3088717bSVictor Perevertkin
1974*3088717bSVictor Perevertkin if (senseInfoBuffer == NULL)
1975*3088717bSVictor Perevertkin {
1976*3088717bSVictor Perevertkin FREE_POOL(srb);
1977*3088717bSVictor Perevertkin FREE_POOL(modeData);
1978*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate request sense "
1979*3088717bSVictor Perevertkin "buffer\n"));
1980*3088717bSVictor Perevertkin return(STATUS_INSUFFICIENT_RESOURCES);
1981*3088717bSVictor Perevertkin }
1982*3088717bSVictor Perevertkin
1983*3088717bSVictor Perevertkin senseInfoBufferLength = SENSE_BUFFER_SIZE_EX;
1984*3088717bSVictor Perevertkin
1985*3088717bSVictor Perevertkin //
1986*3088717bSVictor Perevertkin // Build device I/O control request with METHOD_NEITHER data transfer.
1987*3088717bSVictor Perevertkin // We'll queue a completion routine to cleanup the MDL's and such ourself.
1988*3088717bSVictor Perevertkin //
1989*3088717bSVictor Perevertkin
1990*3088717bSVictor Perevertkin irp = IoAllocateIrp(
1991*3088717bSVictor Perevertkin (CCHAR) (FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1),
1992*3088717bSVictor Perevertkin FALSE);
1993*3088717bSVictor Perevertkin
1994*3088717bSVictor Perevertkin if (irp == NULL)
1995*3088717bSVictor Perevertkin {
1996*3088717bSVictor Perevertkin FREE_POOL(senseInfoBuffer);
1997*3088717bSVictor Perevertkin FREE_POOL(srb);
1998*3088717bSVictor Perevertkin FREE_POOL(modeData);
1999*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: Can't allocate Irp\n"));
2000*3088717bSVictor Perevertkin return(STATUS_INSUFFICIENT_RESOURCES);
2001*3088717bSVictor Perevertkin }
2002*3088717bSVictor Perevertkin
2003*3088717bSVictor Perevertkin isRemoved = ClassAcquireRemoveLock(FdoExtension->DeviceObject, irp);
2004*3088717bSVictor Perevertkin
2005*3088717bSVictor Perevertkin if (isRemoved)
2006*3088717bSVictor Perevertkin {
2007*3088717bSVictor Perevertkin ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2008*3088717bSVictor Perevertkin IoFreeIrp(irp);
2009*3088717bSVictor Perevertkin FREE_POOL(senseInfoBuffer);
2010*3088717bSVictor Perevertkin FREE_POOL(srb);
2011*3088717bSVictor Perevertkin FREE_POOL(modeData);
2012*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskInfoExceptionCheck: RemoveLock says isRemoved\n"));
2013*3088717bSVictor Perevertkin return(STATUS_DEVICE_DOES_NOT_EXIST);
2014*3088717bSVictor Perevertkin }
2015*3088717bSVictor Perevertkin
2016*3088717bSVictor Perevertkin //
2017*3088717bSVictor Perevertkin // Get next stack location.
2018*3088717bSVictor Perevertkin //
2019*3088717bSVictor Perevertkin
2020*3088717bSVictor Perevertkin IoSetNextIrpStackLocation(irp);
2021*3088717bSVictor Perevertkin irpStack = IoGetCurrentIrpStackLocation(irp);
2022*3088717bSVictor Perevertkin irpStack->DeviceObject = FdoExtension->DeviceObject;
2023*3088717bSVictor Perevertkin
2024*3088717bSVictor Perevertkin //
2025*3088717bSVictor Perevertkin // Save retry count in current Irp stack.
2026*3088717bSVictor Perevertkin //
2027*3088717bSVictor Perevertkin irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
2028*3088717bSVictor Perevertkin
2029*3088717bSVictor Perevertkin //
2030*3088717bSVictor Perevertkin // Save allocated sense info buffer in case the port driver overwrites it
2031*3088717bSVictor Perevertkin //
2032*3088717bSVictor Perevertkin irpStack->Parameters.Others.Argument3 = senseInfoBuffer;
2033*3088717bSVictor Perevertkin
2034*3088717bSVictor Perevertkin irpStack = IoGetNextIrpStackLocation(irp);
2035*3088717bSVictor Perevertkin
2036*3088717bSVictor Perevertkin //
2037*3088717bSVictor Perevertkin // Set up SRB for execute scsi request. Save SRB address in next stack
2038*3088717bSVictor Perevertkin // for the port driver.
2039*3088717bSVictor Perevertkin //
2040*3088717bSVictor Perevertkin
2041*3088717bSVictor Perevertkin irpStack->MajorFunction = IRP_MJ_SCSI;
2042*3088717bSVictor Perevertkin irpStack->Parameters.Scsi.Srb = srb;
2043*3088717bSVictor Perevertkin
2044*3088717bSVictor Perevertkin IoSetCompletionRoutine(irp,
2045*3088717bSVictor Perevertkin DiskInfoExceptionComplete,
2046*3088717bSVictor Perevertkin srb,
2047*3088717bSVictor Perevertkin TRUE,
2048*3088717bSVictor Perevertkin TRUE,
2049*3088717bSVictor Perevertkin TRUE);
2050*3088717bSVictor Perevertkin
2051*3088717bSVictor Perevertkin irp->MdlAddress = IoAllocateMdl( modeData,
2052*3088717bSVictor Perevertkin MODE_DATA_SIZE,
2053*3088717bSVictor Perevertkin FALSE,
2054*3088717bSVictor Perevertkin FALSE,
2055*3088717bSVictor Perevertkin irp );
2056*3088717bSVictor Perevertkin if (irp->MdlAddress == NULL)
2057*3088717bSVictor Perevertkin {
2058*3088717bSVictor Perevertkin ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2059*3088717bSVictor Perevertkin FREE_POOL(srb);
2060*3088717bSVictor Perevertkin FREE_POOL(modeData);
2061*3088717bSVictor Perevertkin FREE_POOL(senseInfoBuffer);
2062*3088717bSVictor Perevertkin IoFreeIrp( irp );
2063*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskINfoExceptionCheck: Can't allocate MDL\n"));
2064*3088717bSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
2065*3088717bSVictor Perevertkin }
2066*3088717bSVictor Perevertkin
2067*3088717bSVictor Perevertkin MmBuildMdlForNonPagedPool(irp->MdlAddress);
2068*3088717bSVictor Perevertkin
2069*3088717bSVictor Perevertkin //
2070*3088717bSVictor Perevertkin // Build the MODE SENSE CDB.
2071*3088717bSVictor Perevertkin //
2072*3088717bSVictor Perevertkin
2073*3088717bSVictor Perevertkin if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
2074*3088717bSVictor Perevertkin
2075*3088717bSVictor Perevertkin //
2076*3088717bSVictor Perevertkin // Set up STORAGE_REQUEST_BLOCK fields
2077*3088717bSVictor Perevertkin //
2078*3088717bSVictor Perevertkin
2079*3088717bSVictor Perevertkin srbEx = (PSTORAGE_REQUEST_BLOCK)srb;
2080*3088717bSVictor Perevertkin srbEx->Length = FIELD_OFFSET(STORAGE_REQUEST_BLOCK, Signature);
2081*3088717bSVictor Perevertkin srbEx->Function = SRB_FUNCTION_STORAGE_REQUEST_BLOCK;
2082*3088717bSVictor Perevertkin srbEx->Signature = SRB_SIGNATURE;
2083*3088717bSVictor Perevertkin srbEx->Version = STORAGE_REQUEST_BLOCK_VERSION_1;
2084*3088717bSVictor Perevertkin srbEx->SrbLength = srbSize;
2085*3088717bSVictor Perevertkin srbEx->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
2086*3088717bSVictor Perevertkin srbEx->RequestPriority = IoGetIoPriorityHint(irp);
2087*3088717bSVictor Perevertkin srbEx->AddressOffset = sizeof(STORAGE_REQUEST_BLOCK);
2088*3088717bSVictor Perevertkin srbEx->NumSrbExData = 1;
2089*3088717bSVictor Perevertkin
2090*3088717bSVictor Perevertkin // Set timeout value from device extension.
2091*3088717bSVictor Perevertkin srbEx->TimeOutValue = FdoExtension->TimeOutValue;
2092*3088717bSVictor Perevertkin
2093*3088717bSVictor Perevertkin // Set the transfer length.
2094*3088717bSVictor Perevertkin srbEx->DataTransferLength = MODE_DATA_SIZE;
2095*3088717bSVictor Perevertkin srbEx->DataBuffer = modeData;
2096*3088717bSVictor Perevertkin
2097*3088717bSVictor Perevertkin srbEx->SrbFlags = FdoExtension->SrbFlags;
2098*3088717bSVictor Perevertkin
2099*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DATA_IN);
2100*3088717bSVictor Perevertkin
2101*3088717bSVictor Perevertkin //
2102*3088717bSVictor Perevertkin // Disable synchronous transfer for these requests.
2103*3088717bSVictor Perevertkin //
2104*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
2105*3088717bSVictor Perevertkin
2106*3088717bSVictor Perevertkin //
2107*3088717bSVictor Perevertkin // Don't freeze the queue on an error
2108*3088717bSVictor Perevertkin //
2109*3088717bSVictor Perevertkin SET_FLAG(srbEx->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
2110*3088717bSVictor Perevertkin
2111*3088717bSVictor Perevertkin srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
2112*3088717bSVictor Perevertkin srbEx->RequestTag = SP_UNTAGGED;
2113*3088717bSVictor Perevertkin
2114*3088717bSVictor Perevertkin // Set up IRP Address.
2115*3088717bSVictor Perevertkin srbEx->OriginalRequest = irp;
2116*3088717bSVictor Perevertkin
2117*3088717bSVictor Perevertkin //
2118*3088717bSVictor Perevertkin // Set up address fields
2119*3088717bSVictor Perevertkin //
2120*3088717bSVictor Perevertkin
2121*3088717bSVictor Perevertkin storAddrBtl8 = (PSTOR_ADDR_BTL8) ((PUCHAR)srbEx + srbEx->AddressOffset);
2122*3088717bSVictor Perevertkin storAddrBtl8->Type = STOR_ADDRESS_TYPE_BTL8;
2123*3088717bSVictor Perevertkin storAddrBtl8->AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH;
2124*3088717bSVictor Perevertkin
2125*3088717bSVictor Perevertkin //
2126*3088717bSVictor Perevertkin // Set up SCSI SRB extended data fields
2127*3088717bSVictor Perevertkin //
2128*3088717bSVictor Perevertkin
2129*3088717bSVictor Perevertkin srbEx->SrbExDataOffset[0] = sizeof(STORAGE_REQUEST_BLOCK) +
2130*3088717bSVictor Perevertkin sizeof(STOR_ADDR_BTL8);
2131*3088717bSVictor Perevertkin if ((srbEx->SrbExDataOffset[0] + sizeof(SRBEX_DATA_SCSI_CDB16)) <= srbEx->SrbLength) {
2132*3088717bSVictor Perevertkin srbExDataCdb16 = (PSRBEX_DATA_SCSI_CDB16)((PUCHAR)srbEx + srbEx->SrbExDataOffset[0]);
2133*3088717bSVictor Perevertkin srbExDataCdb16->Type = SrbExDataTypeScsiCdb16;
2134*3088717bSVictor Perevertkin srbExDataCdb16->Length = SRBEX_DATA_SCSI_CDB16_LENGTH;
2135*3088717bSVictor Perevertkin srbExDataCdb16->CdbLength = 6;
2136*3088717bSVictor Perevertkin
2137*3088717bSVictor Perevertkin // Enable auto request sense.
2138*3088717bSVictor Perevertkin srbExDataCdb16->SenseInfoBufferLength = senseInfoBufferLength;
2139*3088717bSVictor Perevertkin srbExDataCdb16->SenseInfoBuffer = senseInfoBuffer;
2140*3088717bSVictor Perevertkin
2141*3088717bSVictor Perevertkin cdb = (PCDB)srbExDataCdb16->Cdb;
2142*3088717bSVictor Perevertkin } else {
2143*3088717bSVictor Perevertkin // Should not happen
2144*3088717bSVictor Perevertkin NT_ASSERT(FALSE);
2145*3088717bSVictor Perevertkin
2146*3088717bSVictor Perevertkin ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2147*3088717bSVictor Perevertkin FREE_POOL(srb);
2148*3088717bSVictor Perevertkin FREE_POOL(modeData);
2149*3088717bSVictor Perevertkin FREE_POOL(senseInfoBuffer);
2150*3088717bSVictor Perevertkin IoFreeIrp( irp );
2151*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "DiskINfoExceptionCheck: Insufficient extended SRB size\n"));
2152*3088717bSVictor Perevertkin return STATUS_INTERNAL_ERROR;
2153*3088717bSVictor Perevertkin }
2154*3088717bSVictor Perevertkin
2155*3088717bSVictor Perevertkin } else {
2156*3088717bSVictor Perevertkin
2157*3088717bSVictor Perevertkin //
2158*3088717bSVictor Perevertkin // Write length to SRB.
2159*3088717bSVictor Perevertkin //
2160*3088717bSVictor Perevertkin srb->Length = SCSI_REQUEST_BLOCK_SIZE;
2161*3088717bSVictor Perevertkin
2162*3088717bSVictor Perevertkin //
2163*3088717bSVictor Perevertkin // Set SCSI bus address.
2164*3088717bSVictor Perevertkin //
2165*3088717bSVictor Perevertkin
2166*3088717bSVictor Perevertkin srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2167*3088717bSVictor Perevertkin
2168*3088717bSVictor Perevertkin //
2169*3088717bSVictor Perevertkin // Enable auto request sense.
2170*3088717bSVictor Perevertkin //
2171*3088717bSVictor Perevertkin
2172*3088717bSVictor Perevertkin srb->SenseInfoBufferLength = senseInfoBufferLength;
2173*3088717bSVictor Perevertkin srb->SenseInfoBuffer = senseInfoBuffer;
2174*3088717bSVictor Perevertkin
2175*3088717bSVictor Perevertkin //
2176*3088717bSVictor Perevertkin // Set timeout value from device extension.
2177*3088717bSVictor Perevertkin //
2178*3088717bSVictor Perevertkin srb->TimeOutValue = FdoExtension->TimeOutValue;
2179*3088717bSVictor Perevertkin
2180*3088717bSVictor Perevertkin //
2181*3088717bSVictor Perevertkin // Set the transfer length.
2182*3088717bSVictor Perevertkin //
2183*3088717bSVictor Perevertkin srb->DataTransferLength = MODE_DATA_SIZE;
2184*3088717bSVictor Perevertkin srb->DataBuffer = modeData;
2185*3088717bSVictor Perevertkin
2186*3088717bSVictor Perevertkin srb->SrbFlags = FdoExtension->SrbFlags;
2187*3088717bSVictor Perevertkin
2188*3088717bSVictor Perevertkin SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN);
2189*3088717bSVictor Perevertkin
2190*3088717bSVictor Perevertkin //
2191*3088717bSVictor Perevertkin // Disable synchronous transfer for these requests.
2192*3088717bSVictor Perevertkin //
2193*3088717bSVictor Perevertkin SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
2194*3088717bSVictor Perevertkin
2195*3088717bSVictor Perevertkin //
2196*3088717bSVictor Perevertkin // Don't freeze the queue on an error
2197*3088717bSVictor Perevertkin //
2198*3088717bSVictor Perevertkin SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
2199*3088717bSVictor Perevertkin
2200*3088717bSVictor Perevertkin srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
2201*3088717bSVictor Perevertkin srb->QueueTag = SP_UNTAGGED;
2202*3088717bSVictor Perevertkin
2203*3088717bSVictor Perevertkin //
2204*3088717bSVictor Perevertkin // Set up IRP Address.
2205*3088717bSVictor Perevertkin //
2206*3088717bSVictor Perevertkin srb->OriginalRequest = irp;
2207*3088717bSVictor Perevertkin
2208*3088717bSVictor Perevertkin srb->CdbLength = 6;
2209*3088717bSVictor Perevertkin cdb = (PCDB)srb->Cdb;
2210*3088717bSVictor Perevertkin
2211*3088717bSVictor Perevertkin }
2212*3088717bSVictor Perevertkin
2213*3088717bSVictor Perevertkin cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2214*3088717bSVictor Perevertkin cdb->MODE_SENSE.PageCode = MODE_PAGE_FAULT_REPORTING;
2215*3088717bSVictor Perevertkin cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
2216*3088717bSVictor Perevertkin
2217*3088717bSVictor Perevertkin //
2218*3088717bSVictor Perevertkin // Call the port driver with the request and wait for it to complete.
2219*3088717bSVictor Perevertkin //
2220*3088717bSVictor Perevertkin
2221*3088717bSVictor Perevertkin IoMarkIrpPending(irp);
2222*3088717bSVictor Perevertkin IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject,
2223*3088717bSVictor Perevertkin irp);
2224*3088717bSVictor Perevertkin
2225*3088717bSVictor Perevertkin return(STATUS_PENDING);
2226*3088717bSVictor Perevertkin }
2227*3088717bSVictor Perevertkin
2228*3088717bSVictor Perevertkin
2229*3088717bSVictor Perevertkin NTSTATUS
DiskDetectFailurePrediction(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,PFAILURE_PREDICTION_METHOD FailurePredictCapability,BOOLEAN ScsiAddressAvailable)2230*3088717bSVictor Perevertkin DiskDetectFailurePrediction(
2231*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2232*3088717bSVictor Perevertkin PFAILURE_PREDICTION_METHOD FailurePredictCapability,
2233*3088717bSVictor Perevertkin BOOLEAN ScsiAddressAvailable
2234*3088717bSVictor Perevertkin )
2235*3088717bSVictor Perevertkin /*++
2236*3088717bSVictor Perevertkin
2237*3088717bSVictor Perevertkin Routine Description:
2238*3088717bSVictor Perevertkin
2239*3088717bSVictor Perevertkin Detect if device has any failure prediction capabilities. First we
2240*3088717bSVictor Perevertkin check for IDE SMART capability. This is done by sending the drive an
2241*3088717bSVictor Perevertkin IDENTIFY command and checking if the SMART command set bit is set.
2242*3088717bSVictor Perevertkin
2243*3088717bSVictor Perevertkin Next we check if SCSI SMART (aka Information Exception Control Page,
2244*3088717bSVictor Perevertkin X3T10/94-190 Rev 4). This is done by querying for the Information
2245*3088717bSVictor Perevertkin Exception mode page.
2246*3088717bSVictor Perevertkin
2247*3088717bSVictor Perevertkin Lastly we check if the device has IOCTL failure prediction. This mechanism
2248*3088717bSVictor Perevertkin a filter driver implements IOCTL_STORAGE_PREDICT_FAILURE and will respond
2249*3088717bSVictor Perevertkin with the information in the IOCTL. We do this by sending the ioctl and
2250*3088717bSVictor Perevertkin if the status returned is STATUS_SUCCESS we assume that it is supported.
2251*3088717bSVictor Perevertkin
2252*3088717bSVictor Perevertkin Arguments:
2253*3088717bSVictor Perevertkin
2254*3088717bSVictor Perevertkin FdoExtension
2255*3088717bSVictor Perevertkin
2256*3088717bSVictor Perevertkin *FailurePredictCapability
2257*3088717bSVictor Perevertkin
2258*3088717bSVictor Perevertkin ScsiAddressAvailable TRUE if there is a valid SCSI_ADDRESS available
2259*3088717bSVictor Perevertkin for this device, FALSE otherwise.
2260*3088717bSVictor Perevertkin If FALSE we do not allow SMART IOCTLs (FailurePredictionSmart capability)
2261*3088717bSVictor Perevertkin which require a valid SCSI_ADDRESS. The other capabilities
2262*3088717bSVictor Perevertkin <FailurePredictionIoctl, FailurePredictionSense) do not requere
2263*3088717bSVictor Perevertkin SCSI_ADDRESS so we'll still try to initialize them.
2264*3088717bSVictor Perevertkin
2265*3088717bSVictor Perevertkin Return Value:
2266*3088717bSVictor Perevertkin
2267*3088717bSVictor Perevertkin NT Status
2268*3088717bSVictor Perevertkin
2269*3088717bSVictor Perevertkin --*/
2270*3088717bSVictor Perevertkin {
2271*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION)FdoExtension;
2272*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2273*3088717bSVictor Perevertkin BOOLEAN supportFP;
2274*3088717bSVictor Perevertkin NTSTATUS status;
2275*3088717bSVictor Perevertkin STORAGE_PREDICT_FAILURE checkFailure;
2276*3088717bSVictor Perevertkin STORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;
2277*3088717bSVictor Perevertkin
2278*3088717bSVictor Perevertkin PAGED_CODE();
2279*3088717bSVictor Perevertkin
2280*3088717bSVictor Perevertkin //
2281*3088717bSVictor Perevertkin // Assume no failure predict mechanisms
2282*3088717bSVictor Perevertkin //
2283*3088717bSVictor Perevertkin *FailurePredictCapability = FailurePredictionNone;
2284*3088717bSVictor Perevertkin
2285*3088717bSVictor Perevertkin //
2286*3088717bSVictor Perevertkin // See if this is an IDE drive that supports SMART. If so enable SMART
2287*3088717bSVictor Perevertkin // and then ensure that it suports the SMART READ STATUS command
2288*3088717bSVictor Perevertkin //
2289*3088717bSVictor Perevertkin
2290*3088717bSVictor Perevertkin if (ScsiAddressAvailable)
2291*3088717bSVictor Perevertkin {
2292*3088717bSVictor Perevertkin DiskGetIdentifyInfo(FdoExtension, &supportFP);
2293*3088717bSVictor Perevertkin
2294*3088717bSVictor Perevertkin if (supportFP)
2295*3088717bSVictor Perevertkin {
2296*3088717bSVictor Perevertkin status = DiskEnableSmart(FdoExtension);
2297*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
2298*3088717bSVictor Perevertkin {
2299*3088717bSVictor Perevertkin *FailurePredictCapability = FailurePredictionSmart;
2300*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = TRUE;
2301*3088717bSVictor Perevertkin
2302*3088717bSVictor Perevertkin status = DiskReadFailurePredictStatus(FdoExtension,
2303*3088717bSVictor Perevertkin &diskSmartStatus);
2304*3088717bSVictor Perevertkin
2305*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: Device %p %s IDE SMART\n",
2306*3088717bSVictor Perevertkin FdoExtension->DeviceObject,
2307*3088717bSVictor Perevertkin NT_SUCCESS(status) ? "does" : "does not"));
2308*3088717bSVictor Perevertkin
2309*3088717bSVictor Perevertkin if (!NT_SUCCESS(status))
2310*3088717bSVictor Perevertkin {
2311*3088717bSVictor Perevertkin *FailurePredictCapability = FailurePredictionNone;
2312*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = FALSE;
2313*3088717bSVictor Perevertkin }
2314*3088717bSVictor Perevertkin }
2315*3088717bSVictor Perevertkin return(status);
2316*3088717bSVictor Perevertkin }
2317*3088717bSVictor Perevertkin }
2318*3088717bSVictor Perevertkin //
2319*3088717bSVictor Perevertkin // See if there is a a filter driver to intercept
2320*3088717bSVictor Perevertkin // IOCTL_STORAGE_PREDICT_FAILURE
2321*3088717bSVictor Perevertkin //
2322*3088717bSVictor Perevertkin status = DiskSendFailurePredictIoctl(FdoExtension,
2323*3088717bSVictor Perevertkin &checkFailure);
2324*3088717bSVictor Perevertkin
2325*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: Device %p %s IOCTL_STORAGE_FAILURE_PREDICT\n",
2326*3088717bSVictor Perevertkin FdoExtension->DeviceObject,
2327*3088717bSVictor Perevertkin NT_SUCCESS(status) ? "does" : "does not"));
2328*3088717bSVictor Perevertkin
2329*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
2330*3088717bSVictor Perevertkin {
2331*3088717bSVictor Perevertkin *FailurePredictCapability = FailurePredictionIoctl;
2332*3088717bSVictor Perevertkin diskData->FailurePredictionEnabled = TRUE;
2333*3088717bSVictor Perevertkin if (checkFailure.PredictFailure)
2334*3088717bSVictor Perevertkin {
2335*3088717bSVictor Perevertkin checkFailure.PredictFailure = 512;
2336*3088717bSVictor Perevertkin ClassNotifyFailurePredicted(FdoExtension,
2337*3088717bSVictor Perevertkin (PUCHAR)&checkFailure,
2338*3088717bSVictor Perevertkin sizeof(checkFailure),
2339*3088717bSVictor Perevertkin (BOOLEAN)(FdoExtension->FailurePredicted == FALSE),
2340*3088717bSVictor Perevertkin 0x11,
2341*3088717bSVictor Perevertkin diskData->ScsiAddress.PathId,
2342*3088717bSVictor Perevertkin diskData->ScsiAddress.TargetId,
2343*3088717bSVictor Perevertkin diskData->ScsiAddress.Lun);
2344*3088717bSVictor Perevertkin
2345*3088717bSVictor Perevertkin FdoExtension->FailurePredicted = TRUE;
2346*3088717bSVictor Perevertkin }
2347*3088717bSVictor Perevertkin return(status);
2348*3088717bSVictor Perevertkin }
2349*3088717bSVictor Perevertkin
2350*3088717bSVictor Perevertkin //
2351*3088717bSVictor Perevertkin // Finally we assume it will not be a scsi smart drive. but
2352*3088717bSVictor Perevertkin // we'll also send off an asynchronous mode sense so that if
2353*3088717bSVictor Perevertkin // it is SMART we'll reregister the device object
2354*3088717bSVictor Perevertkin //
2355*3088717bSVictor Perevertkin
2356*3088717bSVictor Perevertkin *FailurePredictCapability = FailurePredictionNone;
2357*3088717bSVictor Perevertkin
2358*3088717bSVictor Perevertkin DiskInfoExceptionCheck(FdoExtension);
2359*3088717bSVictor Perevertkin
2360*3088717bSVictor Perevertkin return(STATUS_SUCCESS);
2361*3088717bSVictor Perevertkin }
2362*3088717bSVictor Perevertkin
2363*3088717bSVictor Perevertkin
2364*3088717bSVictor Perevertkin NTSTATUS
2365*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskWmiFunctionControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN CLASSENABLEDISABLEFUNCTION Function,IN BOOLEAN Enable)2366*3088717bSVictor Perevertkin DiskWmiFunctionControl(
2367*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
2368*3088717bSVictor Perevertkin IN PIRP Irp,
2369*3088717bSVictor Perevertkin IN ULONG GuidIndex,
2370*3088717bSVictor Perevertkin IN CLASSENABLEDISABLEFUNCTION Function,
2371*3088717bSVictor Perevertkin IN BOOLEAN Enable
2372*3088717bSVictor Perevertkin )
2373*3088717bSVictor Perevertkin /*++
2374*3088717bSVictor Perevertkin
2375*3088717bSVictor Perevertkin Routine Description:
2376*3088717bSVictor Perevertkin
2377*3088717bSVictor Perevertkin This routine is a callback into the driver to enabled or disable event
2378*3088717bSVictor Perevertkin generation or data block collection. A device should only expect a
2379*3088717bSVictor Perevertkin single enable when the first event or data consumer enables events or
2380*3088717bSVictor Perevertkin data collection and a single disable when the last event or data
2381*3088717bSVictor Perevertkin consumer disables events or data collection. Data blocks will only
2382*3088717bSVictor Perevertkin receive collection enable/disable if they were registered as requiring
2383*3088717bSVictor Perevertkin it.
2384*3088717bSVictor Perevertkin
2385*3088717bSVictor Perevertkin
2386*3088717bSVictor Perevertkin When NT boots, failure prediction is not automatically enabled, although
2387*3088717bSVictor Perevertkin it may have been persistantly enabled on a previous boot. Polling is also
2388*3088717bSVictor Perevertkin not automatically enabled. When the first data block that accesses SMART
2389*3088717bSVictor Perevertkin such as SmartStatusGuid, SmartDataGuid, SmartPerformFunction, or
2390*3088717bSVictor Perevertkin SmartEventGuid is accessed then SMART is automatically enabled in the
2391*3088717bSVictor Perevertkin hardware. Polling is enabled when SmartEventGuid is enabled and disabled
2392*3088717bSVictor Perevertkin when it is disabled. Hardware SMART is only disabled when the DisableSmart
2393*3088717bSVictor Perevertkin method is called. Polling is also disabled when this is called regardless
2394*3088717bSVictor Perevertkin of the status of the other guids or events.
2395*3088717bSVictor Perevertkin
2396*3088717bSVictor Perevertkin Arguments:
2397*3088717bSVictor Perevertkin
2398*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
2399*3088717bSVictor Perevertkin
2400*3088717bSVictor Perevertkin GuidIndex is the index into the list of guids provided when the
2401*3088717bSVictor Perevertkin device registered
2402*3088717bSVictor Perevertkin
2403*3088717bSVictor Perevertkin Function specifies which functionality is being enabled or disabled
2404*3088717bSVictor Perevertkin
2405*3088717bSVictor Perevertkin Enable is TRUE then the function is being enabled else disabled
2406*3088717bSVictor Perevertkin
2407*3088717bSVictor Perevertkin Return Value:
2408*3088717bSVictor Perevertkin
2409*3088717bSVictor Perevertkin status
2410*3088717bSVictor Perevertkin
2411*3088717bSVictor Perevertkin --*/
2412*3088717bSVictor Perevertkin {
2413*3088717bSVictor Perevertkin NTSTATUS status = STATUS_SUCCESS;
2414*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2415*3088717bSVictor Perevertkin
2416*3088717bSVictor Perevertkin PAGED_CODE();
2417*3088717bSVictor Perevertkin
2418*3088717bSVictor Perevertkin if ((Function == DataBlockCollection) && Enable)
2419*3088717bSVictor Perevertkin {
2420*3088717bSVictor Perevertkin if ((GuidIndex == SmartStatusGuid) ||
2421*3088717bSVictor Perevertkin (GuidIndex == SmartDataGuid) ||
2422*3088717bSVictor Perevertkin (GuidIndex == SmartThresholdsGuid) ||
2423*3088717bSVictor Perevertkin (GuidIndex == SmartPerformFunction))
2424*3088717bSVictor Perevertkin {
2425*3088717bSVictor Perevertkin status = DiskEnableDisableFailurePrediction(fdoExtension,
2426*3088717bSVictor Perevertkin TRUE);
2427*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p Enable -> %lx\n",
2428*3088717bSVictor Perevertkin DeviceObject,
2429*3088717bSVictor Perevertkin Irp,
2430*3088717bSVictor Perevertkin status));
2431*3088717bSVictor Perevertkin
2432*3088717bSVictor Perevertkin } else {
2433*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for Collection\n",
2434*3088717bSVictor Perevertkin DeviceObject, Irp,
2435*3088717bSVictor Perevertkin GuidIndex,
2436*3088717bSVictor Perevertkin Enable ? "Enabled" : "Disabled"));
2437*3088717bSVictor Perevertkin }
2438*3088717bSVictor Perevertkin } else if (Function == EventGeneration) {
2439*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for Event Generation\n",
2440*3088717bSVictor Perevertkin DeviceObject, Irp,
2441*3088717bSVictor Perevertkin GuidIndex,
2442*3088717bSVictor Perevertkin Enable ? "Enabled" : "Disabled"));
2443*3088717bSVictor Perevertkin
2444*3088717bSVictor Perevertkin
2445*3088717bSVictor Perevertkin if ((GuidIndex == SmartEventGuid) && Enable)
2446*3088717bSVictor Perevertkin {
2447*3088717bSVictor Perevertkin status = DiskEnableDisableFailurePredictPolling(fdoExtension,
2448*3088717bSVictor Perevertkin Enable,
2449*3088717bSVictor Perevertkin 0);
2450*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p %s -> %lx\n",
2451*3088717bSVictor Perevertkin DeviceObject,
2452*3088717bSVictor Perevertkin Irp,
2453*3088717bSVictor Perevertkin Enable ? "DiskEnableSmartPolling" : "DiskDisableSmartPolling",
2454*3088717bSVictor Perevertkin status));
2455*3088717bSVictor Perevertkin }
2456*3088717bSVictor Perevertkin
2457*3088717bSVictor Perevertkin #if DBG
2458*3088717bSVictor Perevertkin } else {
2459*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DeviceObject %p, Irp %p, GuidIndex %d %s for function %d\n",
2460*3088717bSVictor Perevertkin DeviceObject, Irp,
2461*3088717bSVictor Perevertkin GuidIndex,
2462*3088717bSVictor Perevertkin Enable ? "Enabled" : "Disabled",
2463*3088717bSVictor Perevertkin Function));
2464*3088717bSVictor Perevertkin #endif
2465*3088717bSVictor Perevertkin }
2466*3088717bSVictor Perevertkin
2467*3088717bSVictor Perevertkin status = ClassWmiCompleteRequest(DeviceObject,
2468*3088717bSVictor Perevertkin Irp,
2469*3088717bSVictor Perevertkin status,
2470*3088717bSVictor Perevertkin 0,
2471*3088717bSVictor Perevertkin IO_NO_INCREMENT);
2472*3088717bSVictor Perevertkin return status;
2473*3088717bSVictor Perevertkin }
2474*3088717bSVictor Perevertkin
2475*3088717bSVictor Perevertkin
2476*3088717bSVictor Perevertkin
2477*3088717bSVictor Perevertkin NTSTATUS
2478*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskFdoQueryWmiRegInfo(IN PDEVICE_OBJECT DeviceObject,OUT ULONG * RegFlags,OUT PUNICODE_STRING InstanceName)2479*3088717bSVictor Perevertkin DiskFdoQueryWmiRegInfo(
2480*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
2481*3088717bSVictor Perevertkin OUT ULONG *RegFlags,
2482*3088717bSVictor Perevertkin OUT PUNICODE_STRING InstanceName
2483*3088717bSVictor Perevertkin )
2484*3088717bSVictor Perevertkin /*++
2485*3088717bSVictor Perevertkin
2486*3088717bSVictor Perevertkin Routine Description:
2487*3088717bSVictor Perevertkin
2488*3088717bSVictor Perevertkin This routine is a callback into the driver to retrieve the list of
2489*3088717bSVictor Perevertkin guids or data blocks that the driver wants to register with WMI. This
2490*3088717bSVictor Perevertkin routine may not pend or block. Driver should NOT call
2491*3088717bSVictor Perevertkin ClassWmiCompleteRequest.
2492*3088717bSVictor Perevertkin
2493*3088717bSVictor Perevertkin Arguments:
2494*3088717bSVictor Perevertkin
2495*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
2496*3088717bSVictor Perevertkin
2497*3088717bSVictor Perevertkin *RegFlags returns with a set of flags that describe the guids being
2498*3088717bSVictor Perevertkin registered for this device. If the device wants enable and disable
2499*3088717bSVictor Perevertkin collection callbacks before receiving queries for the registered
2500*3088717bSVictor Perevertkin guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
2501*3088717bSVictor Perevertkin returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
2502*3088717bSVictor Perevertkin the instance name is determined from the PDO associated with the
2503*3088717bSVictor Perevertkin device object. Note that the PDO must have an associated devnode. If
2504*3088717bSVictor Perevertkin WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
2505*3088717bSVictor Perevertkin name for the device.
2506*3088717bSVictor Perevertkin
2507*3088717bSVictor Perevertkin InstanceName returns with the instance name for the guids if
2508*3088717bSVictor Perevertkin WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
2509*3088717bSVictor Perevertkin caller will call ExFreePool with the buffer returned.
2510*3088717bSVictor Perevertkin
2511*3088717bSVictor Perevertkin
2512*3088717bSVictor Perevertkin Return Value:
2513*3088717bSVictor Perevertkin
2514*3088717bSVictor Perevertkin status
2515*3088717bSVictor Perevertkin
2516*3088717bSVictor Perevertkin --*/
2517*3088717bSVictor Perevertkin {
2518*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2519*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2520*3088717bSVictor Perevertkin
2521*3088717bSVictor Perevertkin PAGED_CODE();
2522*3088717bSVictor Perevertkin UNREFERENCED_PARAMETER(InstanceName);
2523*3088717bSVictor Perevertkin
2524*3088717bSVictor Perevertkin SET_FLAG(DiskWmiFdoGuidList[SmartThresholdsGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2525*3088717bSVictor Perevertkin SET_FLAG(DiskWmiFdoGuidList[ScsiInfoExceptionsGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2526*3088717bSVictor Perevertkin
2527*3088717bSVictor Perevertkin switch (diskData->FailurePredictionCapability)
2528*3088717bSVictor Perevertkin {
2529*3088717bSVictor Perevertkin case FailurePredictionSmart:
2530*3088717bSVictor Perevertkin {
2531*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartThresholdsGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2532*3088717bSVictor Perevertkin //
2533*3088717bSVictor Perevertkin // Fall Through
2534*3088717bSVictor Perevertkin //
2535*3088717bSVictor Perevertkin }
2536*3088717bSVictor Perevertkin case FailurePredictionIoctl:
2537*3088717bSVictor Perevertkin {
2538*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartStatusGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2539*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartDataGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2540*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartEventGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2541*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartPerformFunction].Flags, WMIREG_FLAG_REMOVE_GUID);
2542*3088717bSVictor Perevertkin
2543*3088717bSVictor Perevertkin break;
2544*3088717bSVictor Perevertkin }
2545*3088717bSVictor Perevertkin
2546*3088717bSVictor Perevertkin case FailurePredictionSense:
2547*3088717bSVictor Perevertkin {
2548*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartStatusGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2549*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartEventGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2550*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[SmartPerformFunction].Flags, WMIREG_FLAG_REMOVE_GUID);
2551*3088717bSVictor Perevertkin CLEAR_FLAG(DiskWmiFdoGuidList[ScsiInfoExceptionsGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2552*3088717bSVictor Perevertkin SET_FLAG (DiskWmiFdoGuidList[SmartDataGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2553*3088717bSVictor Perevertkin break;
2554*3088717bSVictor Perevertkin }
2555*3088717bSVictor Perevertkin
2556*3088717bSVictor Perevertkin
2557*3088717bSVictor Perevertkin default:
2558*3088717bSVictor Perevertkin {
2559*3088717bSVictor Perevertkin SET_FLAG (DiskWmiFdoGuidList[SmartStatusGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2560*3088717bSVictor Perevertkin SET_FLAG (DiskWmiFdoGuidList[SmartDataGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2561*3088717bSVictor Perevertkin SET_FLAG (DiskWmiFdoGuidList[SmartEventGuid].Flags, WMIREG_FLAG_REMOVE_GUID);
2562*3088717bSVictor Perevertkin SET_FLAG (DiskWmiFdoGuidList[SmartPerformFunction].Flags, WMIREG_FLAG_REMOVE_GUID);
2563*3088717bSVictor Perevertkin break;
2564*3088717bSVictor Perevertkin }
2565*3088717bSVictor Perevertkin }
2566*3088717bSVictor Perevertkin
2567*3088717bSVictor Perevertkin //
2568*3088717bSVictor Perevertkin // Use devnode for FDOs
2569*3088717bSVictor Perevertkin *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
2570*3088717bSVictor Perevertkin
2571*3088717bSVictor Perevertkin return STATUS_SUCCESS;
2572*3088717bSVictor Perevertkin }
2573*3088717bSVictor Perevertkin
2574*3088717bSVictor Perevertkin
2575*3088717bSVictor Perevertkin NTSTATUS
2576*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskFdoQueryWmiRegInfoEx(IN PDEVICE_OBJECT DeviceObject,OUT ULONG * RegFlags,OUT PUNICODE_STRING InstanceName,OUT PUNICODE_STRING MofName)2577*3088717bSVictor Perevertkin DiskFdoQueryWmiRegInfoEx(
2578*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
2579*3088717bSVictor Perevertkin OUT ULONG *RegFlags,
2580*3088717bSVictor Perevertkin OUT PUNICODE_STRING InstanceName,
2581*3088717bSVictor Perevertkin OUT PUNICODE_STRING MofName
2582*3088717bSVictor Perevertkin )
2583*3088717bSVictor Perevertkin /*++
2584*3088717bSVictor Perevertkin
2585*3088717bSVictor Perevertkin Routine Description:
2586*3088717bSVictor Perevertkin
2587*3088717bSVictor Perevertkin This routine is a callback into the driver to retrieve the list of
2588*3088717bSVictor Perevertkin guids or data blocks that the driver wants to register with WMI. This
2589*3088717bSVictor Perevertkin routine may not pend or block. Driver should NOT call
2590*3088717bSVictor Perevertkin ClassWmiCompleteRequest.
2591*3088717bSVictor Perevertkin
2592*3088717bSVictor Perevertkin Arguments:
2593*3088717bSVictor Perevertkin
2594*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
2595*3088717bSVictor Perevertkin
2596*3088717bSVictor Perevertkin *RegFlags returns with a set of flags that describe the guids being
2597*3088717bSVictor Perevertkin registered for this device. If the device wants enable and disable
2598*3088717bSVictor Perevertkin collection callbacks before receiving queries for the registered
2599*3088717bSVictor Perevertkin guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
2600*3088717bSVictor Perevertkin returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
2601*3088717bSVictor Perevertkin the instance name is determined from the PDO associated with the
2602*3088717bSVictor Perevertkin device object. Note that the PDO must have an associated devnode. If
2603*3088717bSVictor Perevertkin WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
2604*3088717bSVictor Perevertkin name for the device.
2605*3088717bSVictor Perevertkin
2606*3088717bSVictor Perevertkin InstanceName returns with the instance name for the guids if
2607*3088717bSVictor Perevertkin WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
2608*3088717bSVictor Perevertkin caller will call ExFreePool with the buffer returned.
2609*3088717bSVictor Perevertkin
2610*3088717bSVictor Perevertkin MofName returns initialized with the mof resource name for the
2611*3088717bSVictor Perevertkin binary mof resource attached to the driver's image file. If the
2612*3088717bSVictor Perevertkin driver does not have a mof resource then it should leave this
2613*3088717bSVictor Perevertkin parameter untouched.
2614*3088717bSVictor Perevertkin
2615*3088717bSVictor Perevertkin Return Value:
2616*3088717bSVictor Perevertkin
2617*3088717bSVictor Perevertkin status
2618*3088717bSVictor Perevertkin
2619*3088717bSVictor Perevertkin --*/
2620*3088717bSVictor Perevertkin {
2621*3088717bSVictor Perevertkin NTSTATUS status;
2622*3088717bSVictor Perevertkin
2623*3088717bSVictor Perevertkin UNREFERENCED_PARAMETER(MofName);
2624*3088717bSVictor Perevertkin
2625*3088717bSVictor Perevertkin status = DiskFdoQueryWmiRegInfo(DeviceObject,
2626*3088717bSVictor Perevertkin RegFlags,
2627*3088717bSVictor Perevertkin InstanceName);
2628*3088717bSVictor Perevertkin
2629*3088717bSVictor Perevertkin //
2630*3088717bSVictor Perevertkin // Leave MofName alone since disk doesn't have one
2631*3088717bSVictor Perevertkin //
2632*3088717bSVictor Perevertkin return(status);
2633*3088717bSVictor Perevertkin }
2634*3088717bSVictor Perevertkin
2635*3088717bSVictor Perevertkin
2636*3088717bSVictor Perevertkin NTSTATUS
2637*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskFdoQueryWmiDataBlock(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG BufferAvail,OUT PUCHAR Buffer)2638*3088717bSVictor Perevertkin DiskFdoQueryWmiDataBlock(
2639*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
2640*3088717bSVictor Perevertkin IN PIRP Irp,
2641*3088717bSVictor Perevertkin IN ULONG GuidIndex,
2642*3088717bSVictor Perevertkin IN ULONG BufferAvail,
2643*3088717bSVictor Perevertkin OUT PUCHAR Buffer
2644*3088717bSVictor Perevertkin )
2645*3088717bSVictor Perevertkin /*++
2646*3088717bSVictor Perevertkin
2647*3088717bSVictor Perevertkin Routine Description:
2648*3088717bSVictor Perevertkin
2649*3088717bSVictor Perevertkin This routine is a callback into the driver to query for the contents of
2650*3088717bSVictor Perevertkin a data block. When the driver has finished filling the data block it
2651*3088717bSVictor Perevertkin must call ClassWmiCompleteRequest to complete the irp. The driver can
2652*3088717bSVictor Perevertkin return STATUS_PENDING if the irp cannot be completed immediately.
2653*3088717bSVictor Perevertkin
2654*3088717bSVictor Perevertkin Arguments:
2655*3088717bSVictor Perevertkin
2656*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
2657*3088717bSVictor Perevertkin
2658*3088717bSVictor Perevertkin Irp is the Irp that makes this request
2659*3088717bSVictor Perevertkin
2660*3088717bSVictor Perevertkin GuidIndex is the index into the list of guids provided when the
2661*3088717bSVictor Perevertkin device registered
2662*3088717bSVictor Perevertkin
2663*3088717bSVictor Perevertkin BufferAvail on has the maximum size available to write the data
2664*3088717bSVictor Perevertkin block.
2665*3088717bSVictor Perevertkin
2666*3088717bSVictor Perevertkin Buffer on return is filled with the returned data block
2667*3088717bSVictor Perevertkin
2668*3088717bSVictor Perevertkin
2669*3088717bSVictor Perevertkin Return Value:
2670*3088717bSVictor Perevertkin
2671*3088717bSVictor Perevertkin status
2672*3088717bSVictor Perevertkin
2673*3088717bSVictor Perevertkin --*/
2674*3088717bSVictor Perevertkin {
2675*3088717bSVictor Perevertkin NTSTATUS status;
2676*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2677*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2678*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2679*3088717bSVictor Perevertkin ULONG sizeNeeded;
2680*3088717bSVictor Perevertkin
2681*3088717bSVictor Perevertkin PAGED_CODE();
2682*3088717bSVictor Perevertkin
2683*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskQueryWmiDataBlock, Device %p, Irp %p, GuiIndex %d\n"
2684*3088717bSVictor Perevertkin " BufferAvail %lx Buffer %p\n",
2685*3088717bSVictor Perevertkin DeviceObject, Irp,
2686*3088717bSVictor Perevertkin GuidIndex, BufferAvail, Buffer));
2687*3088717bSVictor Perevertkin
2688*3088717bSVictor Perevertkin switch (GuidIndex)
2689*3088717bSVictor Perevertkin {
2690*3088717bSVictor Perevertkin case DiskGeometryGuid:
2691*3088717bSVictor Perevertkin {
2692*3088717bSVictor Perevertkin sizeNeeded = sizeof(DISK_GEOMETRY);
2693*3088717bSVictor Perevertkin if (BufferAvail >= sizeNeeded)
2694*3088717bSVictor Perevertkin {
2695*3088717bSVictor Perevertkin if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
2696*3088717bSVictor Perevertkin {
2697*3088717bSVictor Perevertkin //
2698*3088717bSVictor Perevertkin // Issue ReadCapacity to update device extension
2699*3088717bSVictor Perevertkin // with information for current media.
2700*3088717bSVictor Perevertkin status = DiskReadDriveCapacity(commonExtension->PartitionZeroExtension->DeviceObject);
2701*3088717bSVictor Perevertkin
2702*3088717bSVictor Perevertkin //
2703*3088717bSVictor Perevertkin // Note whether the drive is ready.
2704*3088717bSVictor Perevertkin diskData->ReadyStatus = status;
2705*3088717bSVictor Perevertkin
2706*3088717bSVictor Perevertkin if (!NT_SUCCESS(status))
2707*3088717bSVictor Perevertkin {
2708*3088717bSVictor Perevertkin break;
2709*3088717bSVictor Perevertkin }
2710*3088717bSVictor Perevertkin }
2711*3088717bSVictor Perevertkin
2712*3088717bSVictor Perevertkin //
2713*3088717bSVictor Perevertkin // Copy drive geometry information from device extension.
2714*3088717bSVictor Perevertkin RtlMoveMemory(Buffer,
2715*3088717bSVictor Perevertkin &(fdoExtension->DiskGeometry),
2716*3088717bSVictor Perevertkin sizeof(DISK_GEOMETRY));
2717*3088717bSVictor Perevertkin
2718*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
2719*3088717bSVictor Perevertkin } else {
2720*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
2721*3088717bSVictor Perevertkin }
2722*3088717bSVictor Perevertkin break;
2723*3088717bSVictor Perevertkin }
2724*3088717bSVictor Perevertkin
2725*3088717bSVictor Perevertkin case SmartStatusGuid:
2726*3088717bSVictor Perevertkin {
2727*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;
2728*3088717bSVictor Perevertkin
2729*3088717bSVictor Perevertkin NT_ASSERT(diskData->FailurePredictionCapability != FailurePredictionNone);
2730*3088717bSVictor Perevertkin
2731*3088717bSVictor Perevertkin sizeNeeded = sizeof(STORAGE_FAILURE_PREDICT_STATUS);
2732*3088717bSVictor Perevertkin if (BufferAvail >= sizeNeeded)
2733*3088717bSVictor Perevertkin {
2734*3088717bSVictor Perevertkin STORAGE_PREDICT_FAILURE checkFailure;
2735*3088717bSVictor Perevertkin
2736*3088717bSVictor Perevertkin diskSmartStatus = (PSTORAGE_FAILURE_PREDICT_STATUS)Buffer;
2737*3088717bSVictor Perevertkin
2738*3088717bSVictor Perevertkin status = DiskSendFailurePredictIoctl(fdoExtension,
2739*3088717bSVictor Perevertkin &checkFailure);
2740*3088717bSVictor Perevertkin
2741*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
2742*3088717bSVictor Perevertkin {
2743*3088717bSVictor Perevertkin if (diskData->FailurePredictionCapability ==
2744*3088717bSVictor Perevertkin FailurePredictionSense)
2745*3088717bSVictor Perevertkin {
2746*3088717bSVictor Perevertkin diskSmartStatus->Reason = *((PULONG)checkFailure.VendorSpecific);
2747*3088717bSVictor Perevertkin } else {
2748*3088717bSVictor Perevertkin diskSmartStatus->Reason = 0; // unknown
2749*3088717bSVictor Perevertkin }
2750*3088717bSVictor Perevertkin
2751*3088717bSVictor Perevertkin diskSmartStatus->PredictFailure = (checkFailure.PredictFailure != 0);
2752*3088717bSVictor Perevertkin }
2753*3088717bSVictor Perevertkin } else {
2754*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
2755*3088717bSVictor Perevertkin }
2756*3088717bSVictor Perevertkin break;
2757*3088717bSVictor Perevertkin }
2758*3088717bSVictor Perevertkin
2759*3088717bSVictor Perevertkin case SmartDataGuid:
2760*3088717bSVictor Perevertkin {
2761*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_DATA diskSmartData;
2762*3088717bSVictor Perevertkin
2763*3088717bSVictor Perevertkin NT_ASSERT((diskData->FailurePredictionCapability ==
2764*3088717bSVictor Perevertkin FailurePredictionSmart) ||
2765*3088717bSVictor Perevertkin (diskData->FailurePredictionCapability ==
2766*3088717bSVictor Perevertkin FailurePredictionIoctl));
2767*3088717bSVictor Perevertkin
2768*3088717bSVictor Perevertkin sizeNeeded = sizeof(STORAGE_FAILURE_PREDICT_DATA);
2769*3088717bSVictor Perevertkin if (BufferAvail >= sizeNeeded)
2770*3088717bSVictor Perevertkin {
2771*3088717bSVictor Perevertkin PSTORAGE_PREDICT_FAILURE checkFailure = (PSTORAGE_PREDICT_FAILURE)Buffer;
2772*3088717bSVictor Perevertkin
2773*3088717bSVictor Perevertkin diskSmartData = (PSTORAGE_FAILURE_PREDICT_DATA)Buffer;
2774*3088717bSVictor Perevertkin
2775*3088717bSVictor Perevertkin status = DiskSendFailurePredictIoctl(fdoExtension,
2776*3088717bSVictor Perevertkin checkFailure);
2777*3088717bSVictor Perevertkin
2778*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
2779*3088717bSVictor Perevertkin {
2780*3088717bSVictor Perevertkin diskSmartData->Length = 512;
2781*3088717bSVictor Perevertkin }
2782*3088717bSVictor Perevertkin } else {
2783*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
2784*3088717bSVictor Perevertkin }
2785*3088717bSVictor Perevertkin
2786*3088717bSVictor Perevertkin break;
2787*3088717bSVictor Perevertkin }
2788*3088717bSVictor Perevertkin
2789*3088717bSVictor Perevertkin case SmartThresholdsGuid:
2790*3088717bSVictor Perevertkin {
2791*3088717bSVictor Perevertkin PSTORAGE_FAILURE_PREDICT_THRESHOLDS diskSmartThresholds;
2792*3088717bSVictor Perevertkin
2793*3088717bSVictor Perevertkin NT_ASSERT((diskData->FailurePredictionCapability ==
2794*3088717bSVictor Perevertkin FailurePredictionSmart));
2795*3088717bSVictor Perevertkin
2796*3088717bSVictor Perevertkin sizeNeeded = sizeof(STORAGE_FAILURE_PREDICT_THRESHOLDS);
2797*3088717bSVictor Perevertkin if (BufferAvail >= sizeNeeded)
2798*3088717bSVictor Perevertkin {
2799*3088717bSVictor Perevertkin diskSmartThresholds = (PSTORAGE_FAILURE_PREDICT_THRESHOLDS)Buffer;
2800*3088717bSVictor Perevertkin status = DiskReadFailurePredictThresholds(fdoExtension,
2801*3088717bSVictor Perevertkin diskSmartThresholds);
2802*3088717bSVictor Perevertkin } else {
2803*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
2804*3088717bSVictor Perevertkin }
2805*3088717bSVictor Perevertkin
2806*3088717bSVictor Perevertkin break;
2807*3088717bSVictor Perevertkin }
2808*3088717bSVictor Perevertkin
2809*3088717bSVictor Perevertkin case SmartPerformFunction:
2810*3088717bSVictor Perevertkin {
2811*3088717bSVictor Perevertkin sizeNeeded = 0;
2812*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
2813*3088717bSVictor Perevertkin break;
2814*3088717bSVictor Perevertkin }
2815*3088717bSVictor Perevertkin
2816*3088717bSVictor Perevertkin case ScsiInfoExceptionsGuid:
2817*3088717bSVictor Perevertkin {
2818*3088717bSVictor Perevertkin PSTORAGE_SCSI_INFO_EXCEPTIONS infoExceptions;
2819*3088717bSVictor Perevertkin MODE_INFO_EXCEPTIONS modeInfo;
2820*3088717bSVictor Perevertkin
2821*3088717bSVictor Perevertkin NT_ASSERT((diskData->FailurePredictionCapability ==
2822*3088717bSVictor Perevertkin FailurePredictionSense));
2823*3088717bSVictor Perevertkin
2824*3088717bSVictor Perevertkin sizeNeeded = sizeof(STORAGE_SCSI_INFO_EXCEPTIONS);
2825*3088717bSVictor Perevertkin if (BufferAvail >= sizeNeeded)
2826*3088717bSVictor Perevertkin {
2827*3088717bSVictor Perevertkin infoExceptions = (PSTORAGE_SCSI_INFO_EXCEPTIONS)Buffer;
2828*3088717bSVictor Perevertkin status = DiskGetInfoExceptionInformation(fdoExtension,
2829*3088717bSVictor Perevertkin &modeInfo);
2830*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
2831*3088717bSVictor Perevertkin {
2832*3088717bSVictor Perevertkin infoExceptions->PageSavable = modeInfo.PSBit;
2833*3088717bSVictor Perevertkin infoExceptions->Flags = modeInfo.Flags;
2834*3088717bSVictor Perevertkin infoExceptions->MRIE = modeInfo.ReportMethod;
2835*3088717bSVictor Perevertkin infoExceptions->Padding = 0;
2836*3088717bSVictor Perevertkin REVERSE_BYTES(&infoExceptions->IntervalTimer,
2837*3088717bSVictor Perevertkin &modeInfo.IntervalTimer);
2838*3088717bSVictor Perevertkin REVERSE_BYTES(&infoExceptions->ReportCount,
2839*3088717bSVictor Perevertkin &modeInfo.ReportCount)
2840*3088717bSVictor Perevertkin }
2841*3088717bSVictor Perevertkin } else {
2842*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
2843*3088717bSVictor Perevertkin }
2844*3088717bSVictor Perevertkin
2845*3088717bSVictor Perevertkin break;
2846*3088717bSVictor Perevertkin }
2847*3088717bSVictor Perevertkin
2848*3088717bSVictor Perevertkin default:
2849*3088717bSVictor Perevertkin {
2850*3088717bSVictor Perevertkin sizeNeeded = 0;
2851*3088717bSVictor Perevertkin status = STATUS_WMI_GUID_NOT_FOUND;
2852*3088717bSVictor Perevertkin }
2853*3088717bSVictor Perevertkin }
2854*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskQueryWmiDataBlock Device %p, Irp %p returns %lx\n",
2855*3088717bSVictor Perevertkin DeviceObject, Irp, status));
2856*3088717bSVictor Perevertkin
2857*3088717bSVictor Perevertkin status = ClassWmiCompleteRequest(DeviceObject,
2858*3088717bSVictor Perevertkin Irp,
2859*3088717bSVictor Perevertkin status,
2860*3088717bSVictor Perevertkin sizeNeeded,
2861*3088717bSVictor Perevertkin IO_NO_INCREMENT);
2862*3088717bSVictor Perevertkin
2863*3088717bSVictor Perevertkin return status;
2864*3088717bSVictor Perevertkin }
2865*3088717bSVictor Perevertkin
2866*3088717bSVictor Perevertkin
2867*3088717bSVictor Perevertkin NTSTATUS
2868*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskFdoSetWmiDataBlock(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG BufferSize,IN PUCHAR Buffer)2869*3088717bSVictor Perevertkin DiskFdoSetWmiDataBlock(
2870*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
2871*3088717bSVictor Perevertkin IN PIRP Irp,
2872*3088717bSVictor Perevertkin IN ULONG GuidIndex,
2873*3088717bSVictor Perevertkin IN ULONG BufferSize,
2874*3088717bSVictor Perevertkin IN PUCHAR Buffer
2875*3088717bSVictor Perevertkin )
2876*3088717bSVictor Perevertkin /*++
2877*3088717bSVictor Perevertkin
2878*3088717bSVictor Perevertkin Routine Description:
2879*3088717bSVictor Perevertkin
2880*3088717bSVictor Perevertkin This routine is a callback into the driver to query for the contents of
2881*3088717bSVictor Perevertkin a data block. When the driver has finished filling the data block it
2882*3088717bSVictor Perevertkin must call ClassWmiCompleteRequest to complete the irp. The driver can
2883*3088717bSVictor Perevertkin return STATUS_PENDING if the irp cannot be completed immediately.
2884*3088717bSVictor Perevertkin
2885*3088717bSVictor Perevertkin Arguments:
2886*3088717bSVictor Perevertkin
2887*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
2888*3088717bSVictor Perevertkin
2889*3088717bSVictor Perevertkin Irp is the Irp that makes this request
2890*3088717bSVictor Perevertkin
2891*3088717bSVictor Perevertkin GuidIndex is the index into the list of guids provided when the
2892*3088717bSVictor Perevertkin device registered
2893*3088717bSVictor Perevertkin
2894*3088717bSVictor Perevertkin BufferSize has the size of the data block passed
2895*3088717bSVictor Perevertkin
2896*3088717bSVictor Perevertkin Buffer has the new values for the data block
2897*3088717bSVictor Perevertkin
2898*3088717bSVictor Perevertkin
2899*3088717bSVictor Perevertkin Return Value:
2900*3088717bSVictor Perevertkin
2901*3088717bSVictor Perevertkin status
2902*3088717bSVictor Perevertkin
2903*3088717bSVictor Perevertkin --*/
2904*3088717bSVictor Perevertkin {
2905*3088717bSVictor Perevertkin NTSTATUS status;
2906*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2907*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2908*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
2909*3088717bSVictor Perevertkin
2910*3088717bSVictor Perevertkin PAGED_CODE();
2911*3088717bSVictor Perevertkin
2912*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataBlock, Device %p, Irp %p, GuiIndex %d\n"
2913*3088717bSVictor Perevertkin " BufferSize %#x Buffer %p\n",
2914*3088717bSVictor Perevertkin DeviceObject, Irp,
2915*3088717bSVictor Perevertkin GuidIndex, BufferSize, Buffer));
2916*3088717bSVictor Perevertkin
2917*3088717bSVictor Perevertkin if (GuidIndex == ScsiInfoExceptionsGuid)
2918*3088717bSVictor Perevertkin {
2919*3088717bSVictor Perevertkin PSTORAGE_SCSI_INFO_EXCEPTIONS infoExceptions;
2920*3088717bSVictor Perevertkin MODE_INFO_EXCEPTIONS modeInfo = {0};
2921*3088717bSVictor Perevertkin
2922*3088717bSVictor Perevertkin if (BufferSize >= sizeof(STORAGE_SCSI_INFO_EXCEPTIONS))
2923*3088717bSVictor Perevertkin {
2924*3088717bSVictor Perevertkin infoExceptions = (PSTORAGE_SCSI_INFO_EXCEPTIONS)Buffer;
2925*3088717bSVictor Perevertkin
2926*3088717bSVictor Perevertkin modeInfo.PageCode = MODE_PAGE_FAULT_REPORTING;
2927*3088717bSVictor Perevertkin modeInfo.PageLength = sizeof(MODE_INFO_EXCEPTIONS) - 2;
2928*3088717bSVictor Perevertkin
2929*3088717bSVictor Perevertkin modeInfo.PSBit = 0;
2930*3088717bSVictor Perevertkin modeInfo.Flags = infoExceptions->Flags;
2931*3088717bSVictor Perevertkin
2932*3088717bSVictor Perevertkin modeInfo.ReportMethod = infoExceptions->MRIE;
2933*3088717bSVictor Perevertkin
2934*3088717bSVictor Perevertkin REVERSE_BYTES(&modeInfo.IntervalTimer[0],
2935*3088717bSVictor Perevertkin &infoExceptions->IntervalTimer);
2936*3088717bSVictor Perevertkin
2937*3088717bSVictor Perevertkin REVERSE_BYTES(&modeInfo.ReportCount[0],
2938*3088717bSVictor Perevertkin &infoExceptions->ReportCount);
2939*3088717bSVictor Perevertkin
2940*3088717bSVictor Perevertkin if (modeInfo.Perf == 1)
2941*3088717bSVictor Perevertkin {
2942*3088717bSVictor Perevertkin diskData->AllowFPPerfHit = FALSE;
2943*3088717bSVictor Perevertkin } else {
2944*3088717bSVictor Perevertkin diskData->AllowFPPerfHit = TRUE;
2945*3088717bSVictor Perevertkin }
2946*3088717bSVictor Perevertkin
2947*3088717bSVictor Perevertkin status = DiskSetInfoExceptionInformation(fdoExtension,
2948*3088717bSVictor Perevertkin &modeInfo);
2949*3088717bSVictor Perevertkin } else {
2950*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
2951*3088717bSVictor Perevertkin }
2952*3088717bSVictor Perevertkin
2953*3088717bSVictor Perevertkin } else if (GuidIndex <= SmartThresholdsGuid)
2954*3088717bSVictor Perevertkin {
2955*3088717bSVictor Perevertkin status = STATUS_WMI_READ_ONLY;
2956*3088717bSVictor Perevertkin } else {
2957*3088717bSVictor Perevertkin status = STATUS_WMI_GUID_NOT_FOUND;
2958*3088717bSVictor Perevertkin }
2959*3088717bSVictor Perevertkin
2960*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataBlock Device %p, Irp %p returns %lx\n",
2961*3088717bSVictor Perevertkin DeviceObject, Irp, status));
2962*3088717bSVictor Perevertkin
2963*3088717bSVictor Perevertkin status = ClassWmiCompleteRequest(DeviceObject,
2964*3088717bSVictor Perevertkin Irp,
2965*3088717bSVictor Perevertkin status,
2966*3088717bSVictor Perevertkin 0,
2967*3088717bSVictor Perevertkin IO_NO_INCREMENT);
2968*3088717bSVictor Perevertkin
2969*3088717bSVictor Perevertkin return status;
2970*3088717bSVictor Perevertkin }
2971*3088717bSVictor Perevertkin
2972*3088717bSVictor Perevertkin
2973*3088717bSVictor Perevertkin NTSTATUS
2974*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskFdoSetWmiDataItem(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG DataItemId,IN ULONG BufferSize,IN PUCHAR Buffer)2975*3088717bSVictor Perevertkin DiskFdoSetWmiDataItem(
2976*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
2977*3088717bSVictor Perevertkin IN PIRP Irp,
2978*3088717bSVictor Perevertkin IN ULONG GuidIndex,
2979*3088717bSVictor Perevertkin IN ULONG DataItemId,
2980*3088717bSVictor Perevertkin IN ULONG BufferSize,
2981*3088717bSVictor Perevertkin IN PUCHAR Buffer
2982*3088717bSVictor Perevertkin )
2983*3088717bSVictor Perevertkin /*++
2984*3088717bSVictor Perevertkin
2985*3088717bSVictor Perevertkin Routine Description:
2986*3088717bSVictor Perevertkin
2987*3088717bSVictor Perevertkin This routine is a callback into the driver to query for the contents of
2988*3088717bSVictor Perevertkin a data block. When the driver has finished filling the data block it
2989*3088717bSVictor Perevertkin must call ClassWmiCompleteRequest to complete the irp. The driver can
2990*3088717bSVictor Perevertkin return STATUS_PENDING if the irp cannot be completed immediately.
2991*3088717bSVictor Perevertkin
2992*3088717bSVictor Perevertkin Arguments:
2993*3088717bSVictor Perevertkin
2994*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
2995*3088717bSVictor Perevertkin
2996*3088717bSVictor Perevertkin Irp is the Irp that makes this request
2997*3088717bSVictor Perevertkin
2998*3088717bSVictor Perevertkin GuidIndex is the index into the list of guids provided when the
2999*3088717bSVictor Perevertkin device registered
3000*3088717bSVictor Perevertkin
3001*3088717bSVictor Perevertkin DataItemId has the id of the data item being set
3002*3088717bSVictor Perevertkin
3003*3088717bSVictor Perevertkin BufferSize has the size of the data item passed
3004*3088717bSVictor Perevertkin
3005*3088717bSVictor Perevertkin Buffer has the new values for the data item
3006*3088717bSVictor Perevertkin
3007*3088717bSVictor Perevertkin
3008*3088717bSVictor Perevertkin Return Value:
3009*3088717bSVictor Perevertkin
3010*3088717bSVictor Perevertkin status
3011*3088717bSVictor Perevertkin
3012*3088717bSVictor Perevertkin --*/
3013*3088717bSVictor Perevertkin {
3014*3088717bSVictor Perevertkin NTSTATUS status;
3015*3088717bSVictor Perevertkin
3016*3088717bSVictor Perevertkin PAGED_CODE();
3017*3088717bSVictor Perevertkin
3018*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataItem, Device %p, Irp %p, GuiIndex %d, DataId %d\n"
3019*3088717bSVictor Perevertkin " BufferSize %#x Buffer %p\n",
3020*3088717bSVictor Perevertkin DeviceObject, Irp,
3021*3088717bSVictor Perevertkin GuidIndex, DataItemId, BufferSize, Buffer));
3022*3088717bSVictor Perevertkin
3023*3088717bSVictor Perevertkin if (GuidIndex <= SmartThresholdsGuid)
3024*3088717bSVictor Perevertkin {
3025*3088717bSVictor Perevertkin status = STATUS_WMI_READ_ONLY;
3026*3088717bSVictor Perevertkin } else {
3027*3088717bSVictor Perevertkin status = STATUS_WMI_GUID_NOT_FOUND;
3028*3088717bSVictor Perevertkin }
3029*3088717bSVictor Perevertkin
3030*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskSetWmiDataItem Device %p, Irp %p returns %lx\n",
3031*3088717bSVictor Perevertkin DeviceObject, Irp, status));
3032*3088717bSVictor Perevertkin
3033*3088717bSVictor Perevertkin status = ClassWmiCompleteRequest(DeviceObject,
3034*3088717bSVictor Perevertkin Irp,
3035*3088717bSVictor Perevertkin status,
3036*3088717bSVictor Perevertkin 0,
3037*3088717bSVictor Perevertkin IO_NO_INCREMENT);
3038*3088717bSVictor Perevertkin
3039*3088717bSVictor Perevertkin return status;
3040*3088717bSVictor Perevertkin }
3041*3088717bSVictor Perevertkin
3042*3088717bSVictor Perevertkin
3043*3088717bSVictor Perevertkin NTSTATUS
3044*3088717bSVictor Perevertkin NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DiskFdoExecuteWmiMethod(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG MethodId,IN ULONG InBufferSize,IN ULONG OutBufferSize,IN PUCHAR Buffer)3045*3088717bSVictor Perevertkin DiskFdoExecuteWmiMethod(
3046*3088717bSVictor Perevertkin IN PDEVICE_OBJECT DeviceObject,
3047*3088717bSVictor Perevertkin IN PIRP Irp,
3048*3088717bSVictor Perevertkin IN ULONG GuidIndex,
3049*3088717bSVictor Perevertkin IN ULONG MethodId,
3050*3088717bSVictor Perevertkin IN ULONG InBufferSize,
3051*3088717bSVictor Perevertkin IN ULONG OutBufferSize,
3052*3088717bSVictor Perevertkin IN PUCHAR Buffer
3053*3088717bSVictor Perevertkin )
3054*3088717bSVictor Perevertkin /*++
3055*3088717bSVictor Perevertkin
3056*3088717bSVictor Perevertkin Routine Description:
3057*3088717bSVictor Perevertkin
3058*3088717bSVictor Perevertkin This routine is a callback into the driver to execute a method. When the
3059*3088717bSVictor Perevertkin driver has finished filling the data block it must call
3060*3088717bSVictor Perevertkin ClassWmiCompleteRequest to complete the irp. The driver can
3061*3088717bSVictor Perevertkin return STATUS_PENDING if the irp cannot be completed immediately.
3062*3088717bSVictor Perevertkin
3063*3088717bSVictor Perevertkin Arguments:
3064*3088717bSVictor Perevertkin
3065*3088717bSVictor Perevertkin DeviceObject is the device whose data block is being queried
3066*3088717bSVictor Perevertkin
3067*3088717bSVictor Perevertkin Irp is the Irp that makes this request
3068*3088717bSVictor Perevertkin
3069*3088717bSVictor Perevertkin GuidIndex is the index into the list of guids provided when the
3070*3088717bSVictor Perevertkin device registered
3071*3088717bSVictor Perevertkin
3072*3088717bSVictor Perevertkin MethodId has the id of the method being called
3073*3088717bSVictor Perevertkin
3074*3088717bSVictor Perevertkin InBufferSize has the size of the data block passed in as the input to
3075*3088717bSVictor Perevertkin the method.
3076*3088717bSVictor Perevertkin
3077*3088717bSVictor Perevertkin OutBufferSize on entry has the maximum size available to write the
3078*3088717bSVictor Perevertkin returned data block.
3079*3088717bSVictor Perevertkin
3080*3088717bSVictor Perevertkin Buffer is filled with the returned data block
3081*3088717bSVictor Perevertkin
3082*3088717bSVictor Perevertkin
3083*3088717bSVictor Perevertkin Return Value:
3084*3088717bSVictor Perevertkin
3085*3088717bSVictor Perevertkin status
3086*3088717bSVictor Perevertkin
3087*3088717bSVictor Perevertkin --*/
3088*3088717bSVictor Perevertkin {
3089*3088717bSVictor Perevertkin PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
3090*3088717bSVictor Perevertkin PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
3091*3088717bSVictor Perevertkin PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
3092*3088717bSVictor Perevertkin ULONG sizeNeeded = 0;
3093*3088717bSVictor Perevertkin NTSTATUS status;
3094*3088717bSVictor Perevertkin
3095*3088717bSVictor Perevertkin PAGED_CODE();
3096*3088717bSVictor Perevertkin
3097*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskExecuteWmiMethod, DeviceObject %p, Irp %p, Guid Id %d, MethodId %d\n"
3098*3088717bSVictor Perevertkin " InBufferSize %#x, OutBufferSize %#x, Buffer %p\n",
3099*3088717bSVictor Perevertkin DeviceObject, Irp,
3100*3088717bSVictor Perevertkin GuidIndex, MethodId, InBufferSize, OutBufferSize, Buffer));
3101*3088717bSVictor Perevertkin
3102*3088717bSVictor Perevertkin switch(GuidIndex)
3103*3088717bSVictor Perevertkin {
3104*3088717bSVictor Perevertkin case SmartPerformFunction:
3105*3088717bSVictor Perevertkin {
3106*3088717bSVictor Perevertkin
3107*3088717bSVictor Perevertkin NT_ASSERT((diskData->FailurePredictionCapability ==
3108*3088717bSVictor Perevertkin FailurePredictionSmart) ||
3109*3088717bSVictor Perevertkin (diskData->FailurePredictionCapability ==
3110*3088717bSVictor Perevertkin FailurePredictionIoctl) ||
3111*3088717bSVictor Perevertkin (diskData->FailurePredictionCapability ==
3112*3088717bSVictor Perevertkin FailurePredictionSense));
3113*3088717bSVictor Perevertkin
3114*3088717bSVictor Perevertkin
3115*3088717bSVictor Perevertkin switch(MethodId)
3116*3088717bSVictor Perevertkin {
3117*3088717bSVictor Perevertkin //
3118*3088717bSVictor Perevertkin // void AllowPerformanceHit([in] boolean Allow)
3119*3088717bSVictor Perevertkin //
3120*3088717bSVictor Perevertkin case AllowDisallowPerformanceHit:
3121*3088717bSVictor Perevertkin {
3122*3088717bSVictor Perevertkin BOOLEAN allowPerfHit;
3123*3088717bSVictor Perevertkin
3124*3088717bSVictor Perevertkin sizeNeeded = 0;
3125*3088717bSVictor Perevertkin if (InBufferSize >= sizeof(BOOLEAN))
3126*3088717bSVictor Perevertkin {
3127*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3128*3088717bSVictor Perevertkin
3129*3088717bSVictor Perevertkin allowPerfHit = *((PBOOLEAN)Buffer);
3130*3088717bSVictor Perevertkin if (diskData->AllowFPPerfHit != allowPerfHit)
3131*3088717bSVictor Perevertkin {
3132*3088717bSVictor Perevertkin diskData->AllowFPPerfHit = allowPerfHit;
3133*3088717bSVictor Perevertkin if (diskData->FailurePredictionCapability ==
3134*3088717bSVictor Perevertkin FailurePredictionSense)
3135*3088717bSVictor Perevertkin {
3136*3088717bSVictor Perevertkin MODE_INFO_EXCEPTIONS modeInfo;
3137*3088717bSVictor Perevertkin
3138*3088717bSVictor Perevertkin status = DiskGetInfoExceptionInformation(fdoExtension,
3139*3088717bSVictor Perevertkin &modeInfo);
3140*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
3141*3088717bSVictor Perevertkin {
3142*3088717bSVictor Perevertkin modeInfo.Perf = allowPerfHit ? 0 : 1;
3143*3088717bSVictor Perevertkin status = DiskSetInfoExceptionInformation(fdoExtension,
3144*3088717bSVictor Perevertkin &modeInfo);
3145*3088717bSVictor Perevertkin }
3146*3088717bSVictor Perevertkin }
3147*3088717bSVictor Perevertkin else
3148*3088717bSVictor Perevertkin {
3149*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
3150*3088717bSVictor Perevertkin }
3151*3088717bSVictor Perevertkin }
3152*3088717bSVictor Perevertkin
3153*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: AllowPerformanceHit %x for device %p --> %lx\n",
3154*3088717bSVictor Perevertkin allowPerfHit,
3155*3088717bSVictor Perevertkin fdoExtension->DeviceObject,
3156*3088717bSVictor Perevertkin status));
3157*3088717bSVictor Perevertkin } else {
3158*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3159*3088717bSVictor Perevertkin }
3160*3088717bSVictor Perevertkin break;
3161*3088717bSVictor Perevertkin }
3162*3088717bSVictor Perevertkin
3163*3088717bSVictor Perevertkin //
3164*3088717bSVictor Perevertkin // void EnableDisableHardwareFailurePrediction([in] boolean Enable)
3165*3088717bSVictor Perevertkin //
3166*3088717bSVictor Perevertkin case EnableDisableHardwareFailurePrediction:
3167*3088717bSVictor Perevertkin {
3168*3088717bSVictor Perevertkin BOOLEAN enable;
3169*3088717bSVictor Perevertkin
3170*3088717bSVictor Perevertkin sizeNeeded = 0;
3171*3088717bSVictor Perevertkin if (InBufferSize >= sizeof(BOOLEAN))
3172*3088717bSVictor Perevertkin {
3173*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3174*3088717bSVictor Perevertkin enable = *((PBOOLEAN)Buffer);
3175*3088717bSVictor Perevertkin if (!enable)
3176*3088717bSVictor Perevertkin {
3177*3088717bSVictor Perevertkin //
3178*3088717bSVictor Perevertkin // If we are disabling we need to also disable
3179*3088717bSVictor Perevertkin // polling
3180*3088717bSVictor Perevertkin //
3181*3088717bSVictor Perevertkin DiskEnableDisableFailurePredictPolling(
3182*3088717bSVictor Perevertkin fdoExtension,
3183*3088717bSVictor Perevertkin enable,
3184*3088717bSVictor Perevertkin 0);
3185*3088717bSVictor Perevertkin }
3186*3088717bSVictor Perevertkin
3187*3088717bSVictor Perevertkin status = DiskEnableDisableFailurePrediction(
3188*3088717bSVictor Perevertkin fdoExtension,
3189*3088717bSVictor Perevertkin enable);
3190*3088717bSVictor Perevertkin
3191*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: EnableDisableHardwareFailurePrediction: %x for device %p --> %lx\n",
3192*3088717bSVictor Perevertkin enable,
3193*3088717bSVictor Perevertkin fdoExtension->DeviceObject,
3194*3088717bSVictor Perevertkin status));
3195*3088717bSVictor Perevertkin } else {
3196*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3197*3088717bSVictor Perevertkin }
3198*3088717bSVictor Perevertkin break;
3199*3088717bSVictor Perevertkin }
3200*3088717bSVictor Perevertkin
3201*3088717bSVictor Perevertkin //
3202*3088717bSVictor Perevertkin // void EnableDisableFailurePredictionPolling(
3203*3088717bSVictor Perevertkin // [in] uint32 Period,
3204*3088717bSVictor Perevertkin // [in] boolean Enable)
3205*3088717bSVictor Perevertkin //
3206*3088717bSVictor Perevertkin case EnableDisableFailurePredictionPolling:
3207*3088717bSVictor Perevertkin {
3208*3088717bSVictor Perevertkin BOOLEAN enable;
3209*3088717bSVictor Perevertkin ULONG period;
3210*3088717bSVictor Perevertkin
3211*3088717bSVictor Perevertkin sizeNeeded = 0;
3212*3088717bSVictor Perevertkin if (InBufferSize >= (sizeof(ULONG) + sizeof(BOOLEAN)))
3213*3088717bSVictor Perevertkin {
3214*3088717bSVictor Perevertkin period = *((PULONG)Buffer);
3215*3088717bSVictor Perevertkin Buffer += sizeof(ULONG);
3216*3088717bSVictor Perevertkin enable = *((PBOOLEAN)Buffer);
3217*3088717bSVictor Perevertkin
3218*3088717bSVictor Perevertkin status = DiskEnableDisableFailurePredictPolling(
3219*3088717bSVictor Perevertkin fdoExtension,
3220*3088717bSVictor Perevertkin enable,
3221*3088717bSVictor Perevertkin period);
3222*3088717bSVictor Perevertkin
3223*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: EnableDisableFailurePredictionPolling: %x %x for device %p --> %lx\n",
3224*3088717bSVictor Perevertkin enable,
3225*3088717bSVictor Perevertkin period,
3226*3088717bSVictor Perevertkin fdoExtension->DeviceObject,
3227*3088717bSVictor Perevertkin status));
3228*3088717bSVictor Perevertkin } else {
3229*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3230*3088717bSVictor Perevertkin }
3231*3088717bSVictor Perevertkin break;
3232*3088717bSVictor Perevertkin }
3233*3088717bSVictor Perevertkin
3234*3088717bSVictor Perevertkin //
3235*3088717bSVictor Perevertkin // void GetFailurePredictionCapability([out] uint32 Capability)
3236*3088717bSVictor Perevertkin //
3237*3088717bSVictor Perevertkin case GetFailurePredictionCapability:
3238*3088717bSVictor Perevertkin {
3239*3088717bSVictor Perevertkin sizeNeeded = sizeof(ULONG);
3240*3088717bSVictor Perevertkin if (OutBufferSize >= sizeNeeded)
3241*3088717bSVictor Perevertkin {
3242*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3243*3088717bSVictor Perevertkin *((PFAILURE_PREDICTION_METHOD)Buffer) = diskData->FailurePredictionCapability;
3244*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: GetFailurePredictionCapability: %x for device %p --> %lx\n",
3245*3088717bSVictor Perevertkin *((PFAILURE_PREDICTION_METHOD)Buffer),
3246*3088717bSVictor Perevertkin fdoExtension->DeviceObject,
3247*3088717bSVictor Perevertkin status));
3248*3088717bSVictor Perevertkin } else {
3249*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
3250*3088717bSVictor Perevertkin }
3251*3088717bSVictor Perevertkin break;
3252*3088717bSVictor Perevertkin }
3253*3088717bSVictor Perevertkin
3254*3088717bSVictor Perevertkin //
3255*3088717bSVictor Perevertkin // void EnableOfflineDiags([out] boolean Success);
3256*3088717bSVictor Perevertkin //
3257*3088717bSVictor Perevertkin case EnableOfflineDiags:
3258*3088717bSVictor Perevertkin {
3259*3088717bSVictor Perevertkin sizeNeeded = sizeof(BOOLEAN);
3260*3088717bSVictor Perevertkin if (OutBufferSize >= sizeNeeded)
3261*3088717bSVictor Perevertkin {
3262*3088717bSVictor Perevertkin if (diskData->FailurePredictionCapability ==
3263*3088717bSVictor Perevertkin FailurePredictionSmart)
3264*3088717bSVictor Perevertkin {
3265*3088717bSVictor Perevertkin //
3266*3088717bSVictor Perevertkin // Initiate or resume offline diagnostics.
3267*3088717bSVictor Perevertkin // This may cause a loss of performance
3268*3088717bSVictor Perevertkin // to the disk, but mayincrease the amount
3269*3088717bSVictor Perevertkin // of disk checking.
3270*3088717bSVictor Perevertkin //
3271*3088717bSVictor Perevertkin status = DiskExecuteSmartDiagnostics(fdoExtension,
3272*3088717bSVictor Perevertkin 0);
3273*3088717bSVictor Perevertkin
3274*3088717bSVictor Perevertkin } else {
3275*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
3276*3088717bSVictor Perevertkin }
3277*3088717bSVictor Perevertkin
3278*3088717bSVictor Perevertkin *((PBOOLEAN)Buffer) = NT_SUCCESS(status);
3279*3088717bSVictor Perevertkin
3280*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "DiskFdoWmiExecuteMethod: EnableOfflineDiags for device %p --> %lx\n",
3281*3088717bSVictor Perevertkin fdoExtension->DeviceObject,
3282*3088717bSVictor Perevertkin status));
3283*3088717bSVictor Perevertkin } else {
3284*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
3285*3088717bSVictor Perevertkin }
3286*3088717bSVictor Perevertkin break;
3287*3088717bSVictor Perevertkin }
3288*3088717bSVictor Perevertkin
3289*3088717bSVictor Perevertkin //
3290*3088717bSVictor Perevertkin // void ReadLogSectors([in] uint8 LogAddress,
3291*3088717bSVictor Perevertkin // [in] uint8 SectorCount,
3292*3088717bSVictor Perevertkin // [out] uint32 Length,
3293*3088717bSVictor Perevertkin // [out, WmiSizeIs("Length")] uint8 LogSectors[]
3294*3088717bSVictor Perevertkin // );
3295*3088717bSVictor Perevertkin //
3296*3088717bSVictor Perevertkin case ReadLogSectors:
3297*3088717bSVictor Perevertkin {
3298*3088717bSVictor Perevertkin if (diskData->FailurePredictionCapability ==
3299*3088717bSVictor Perevertkin FailurePredictionSmart)
3300*3088717bSVictor Perevertkin {
3301*3088717bSVictor Perevertkin if (InBufferSize >= sizeof(READ_LOG_SECTORS_IN))
3302*3088717bSVictor Perevertkin {
3303*3088717bSVictor Perevertkin PREAD_LOG_SECTORS_IN inParams;
3304*3088717bSVictor Perevertkin PREAD_LOG_SECTORS_OUT outParams;
3305*3088717bSVictor Perevertkin ULONG readSize;
3306*3088717bSVictor Perevertkin
3307*3088717bSVictor Perevertkin inParams = (PREAD_LOG_SECTORS_IN)Buffer;
3308*3088717bSVictor Perevertkin readSize = inParams->SectorCount * SMART_LOG_SECTOR_SIZE;
3309*3088717bSVictor Perevertkin sizeNeeded = FIELD_OFFSET(READ_LOG_SECTORS_OUT,
3310*3088717bSVictor Perevertkin LogSectors) + readSize;
3311*3088717bSVictor Perevertkin
3312*3088717bSVictor Perevertkin if (OutBufferSize >= sizeNeeded)
3313*3088717bSVictor Perevertkin {
3314*3088717bSVictor Perevertkin outParams = (PREAD_LOG_SECTORS_OUT)Buffer;
3315*3088717bSVictor Perevertkin status = DiskReadSmartLog(fdoExtension,
3316*3088717bSVictor Perevertkin inParams->SectorCount,
3317*3088717bSVictor Perevertkin inParams->LogAddress,
3318*3088717bSVictor Perevertkin outParams->LogSectors);
3319*3088717bSVictor Perevertkin
3320*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
3321*3088717bSVictor Perevertkin {
3322*3088717bSVictor Perevertkin outParams->Length = readSize;
3323*3088717bSVictor Perevertkin } else {
3324*3088717bSVictor Perevertkin //
3325*3088717bSVictor Perevertkin // SMART command failure is
3326*3088717bSVictor Perevertkin // indicated by successful
3327*3088717bSVictor Perevertkin // execution, but no data returned
3328*3088717bSVictor Perevertkin //
3329*3088717bSVictor Perevertkin outParams->Length = 0;
3330*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3331*3088717bSVictor Perevertkin }
3332*3088717bSVictor Perevertkin } else {
3333*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
3334*3088717bSVictor Perevertkin }
3335*3088717bSVictor Perevertkin
3336*3088717bSVictor Perevertkin } else {
3337*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3338*3088717bSVictor Perevertkin }
3339*3088717bSVictor Perevertkin } else {
3340*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
3341*3088717bSVictor Perevertkin }
3342*3088717bSVictor Perevertkin break;
3343*3088717bSVictor Perevertkin }
3344*3088717bSVictor Perevertkin
3345*3088717bSVictor Perevertkin // void WriteLogSectors([in] uint8 LogAddress,
3346*3088717bSVictor Perevertkin // [in] uint8 SectorCount,
3347*3088717bSVictor Perevertkin // [in] uint32 Length,
3348*3088717bSVictor Perevertkin // [in, WmiSizeIs("Length")] uint8 LogSectors[],
3349*3088717bSVictor Perevertkin // [out] boolean Success
3350*3088717bSVictor Perevertkin // );
3351*3088717bSVictor Perevertkin case WriteLogSectors:
3352*3088717bSVictor Perevertkin {
3353*3088717bSVictor Perevertkin if (diskData->FailurePredictionCapability ==
3354*3088717bSVictor Perevertkin FailurePredictionSmart)
3355*3088717bSVictor Perevertkin {
3356*3088717bSVictor Perevertkin if ((LONG)InBufferSize >= FIELD_OFFSET(WRITE_LOG_SECTORS_IN,
3357*3088717bSVictor Perevertkin LogSectors))
3358*3088717bSVictor Perevertkin {
3359*3088717bSVictor Perevertkin PWRITE_LOG_SECTORS_IN inParams;
3360*3088717bSVictor Perevertkin PWRITE_LOG_SECTORS_OUT outParams;
3361*3088717bSVictor Perevertkin ULONG writeSize;
3362*3088717bSVictor Perevertkin
3363*3088717bSVictor Perevertkin inParams = (PWRITE_LOG_SECTORS_IN)Buffer;
3364*3088717bSVictor Perevertkin writeSize = inParams->SectorCount * SMART_LOG_SECTOR_SIZE;
3365*3088717bSVictor Perevertkin if (InBufferSize >= (FIELD_OFFSET(WRITE_LOG_SECTORS_IN,
3366*3088717bSVictor Perevertkin LogSectors) +
3367*3088717bSVictor Perevertkin writeSize))
3368*3088717bSVictor Perevertkin {
3369*3088717bSVictor Perevertkin sizeNeeded = sizeof(WRITE_LOG_SECTORS_OUT);
3370*3088717bSVictor Perevertkin
3371*3088717bSVictor Perevertkin if (OutBufferSize >= sizeNeeded)
3372*3088717bSVictor Perevertkin {
3373*3088717bSVictor Perevertkin outParams = (PWRITE_LOG_SECTORS_OUT)Buffer;
3374*3088717bSVictor Perevertkin status = DiskWriteSmartLog(fdoExtension,
3375*3088717bSVictor Perevertkin inParams->SectorCount,
3376*3088717bSVictor Perevertkin inParams->LogAddress,
3377*3088717bSVictor Perevertkin inParams->LogSectors);
3378*3088717bSVictor Perevertkin
3379*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
3380*3088717bSVictor Perevertkin {
3381*3088717bSVictor Perevertkin outParams->Success = TRUE;
3382*3088717bSVictor Perevertkin } else {
3383*3088717bSVictor Perevertkin outParams->Success = FALSE;
3384*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3385*3088717bSVictor Perevertkin }
3386*3088717bSVictor Perevertkin } else {
3387*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
3388*3088717bSVictor Perevertkin }
3389*3088717bSVictor Perevertkin } else {
3390*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3391*3088717bSVictor Perevertkin }
3392*3088717bSVictor Perevertkin } else {
3393*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3394*3088717bSVictor Perevertkin }
3395*3088717bSVictor Perevertkin } else {
3396*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
3397*3088717bSVictor Perevertkin }
3398*3088717bSVictor Perevertkin break;
3399*3088717bSVictor Perevertkin }
3400*3088717bSVictor Perevertkin
3401*3088717bSVictor Perevertkin // void ExecuteSelfTest([in] uint8 Subcommand,
3402*3088717bSVictor Perevertkin // [out,
3403*3088717bSVictor Perevertkin // Values{"0", "1", "2"},
3404*3088717bSVictor Perevertkin // ValueMap{"Successful Completion",
3405*3088717bSVictor Perevertkin // "Captive Mode Required",
3406*3088717bSVictor Perevertkin // "Unsuccessful Completion"}
3407*3088717bSVictor Perevertkin // ]
3408*3088717bSVictor Perevertkin // uint32 ReturnCode);
3409*3088717bSVictor Perevertkin case ExecuteSelfTest:
3410*3088717bSVictor Perevertkin {
3411*3088717bSVictor Perevertkin if (diskData->FailurePredictionCapability ==
3412*3088717bSVictor Perevertkin FailurePredictionSmart)
3413*3088717bSVictor Perevertkin {
3414*3088717bSVictor Perevertkin if (InBufferSize >= sizeof(EXECUTE_SELF_TEST_IN))
3415*3088717bSVictor Perevertkin {
3416*3088717bSVictor Perevertkin sizeNeeded = sizeof(EXECUTE_SELF_TEST_OUT);
3417*3088717bSVictor Perevertkin if (OutBufferSize >= sizeNeeded)
3418*3088717bSVictor Perevertkin {
3419*3088717bSVictor Perevertkin PEXECUTE_SELF_TEST_IN inParam;
3420*3088717bSVictor Perevertkin PEXECUTE_SELF_TEST_OUT outParam;
3421*3088717bSVictor Perevertkin
3422*3088717bSVictor Perevertkin inParam = (PEXECUTE_SELF_TEST_IN)Buffer;
3423*3088717bSVictor Perevertkin outParam = (PEXECUTE_SELF_TEST_OUT)Buffer;
3424*3088717bSVictor Perevertkin
3425*3088717bSVictor Perevertkin if (DiskIsValidSmartSelfTest(inParam->Subcommand))
3426*3088717bSVictor Perevertkin {
3427*3088717bSVictor Perevertkin status = DiskExecuteSmartDiagnostics(fdoExtension,
3428*3088717bSVictor Perevertkin inParam->Subcommand);
3429*3088717bSVictor Perevertkin if (NT_SUCCESS(status))
3430*3088717bSVictor Perevertkin {
3431*3088717bSVictor Perevertkin //
3432*3088717bSVictor Perevertkin // Return self test executed
3433*3088717bSVictor Perevertkin // without a problem
3434*3088717bSVictor Perevertkin //
3435*3088717bSVictor Perevertkin outParam->ReturnCode = 0;
3436*3088717bSVictor Perevertkin } else {
3437*3088717bSVictor Perevertkin //
3438*3088717bSVictor Perevertkin // Return Self test execution
3439*3088717bSVictor Perevertkin // failed status
3440*3088717bSVictor Perevertkin //
3441*3088717bSVictor Perevertkin outParam->ReturnCode = 2;
3442*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3443*3088717bSVictor Perevertkin }
3444*3088717bSVictor Perevertkin } else {
3445*3088717bSVictor Perevertkin //
3446*3088717bSVictor Perevertkin // If self test subcommand requires
3447*3088717bSVictor Perevertkin // captive mode then return that
3448*3088717bSVictor Perevertkin // status
3449*3088717bSVictor Perevertkin //
3450*3088717bSVictor Perevertkin outParam->ReturnCode = 1;
3451*3088717bSVictor Perevertkin status = STATUS_SUCCESS;
3452*3088717bSVictor Perevertkin }
3453*3088717bSVictor Perevertkin
3454*3088717bSVictor Perevertkin } else {
3455*3088717bSVictor Perevertkin status = STATUS_BUFFER_TOO_SMALL;
3456*3088717bSVictor Perevertkin }
3457*3088717bSVictor Perevertkin
3458*3088717bSVictor Perevertkin } else {
3459*3088717bSVictor Perevertkin status = STATUS_INVALID_PARAMETER;
3460*3088717bSVictor Perevertkin }
3461*3088717bSVictor Perevertkin } else {
3462*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
3463*3088717bSVictor Perevertkin }
3464*3088717bSVictor Perevertkin
3465*3088717bSVictor Perevertkin break;
3466*3088717bSVictor Perevertkin }
3467*3088717bSVictor Perevertkin
3468*3088717bSVictor Perevertkin default :
3469*3088717bSVictor Perevertkin {
3470*3088717bSVictor Perevertkin sizeNeeded = 0;
3471*3088717bSVictor Perevertkin status = STATUS_WMI_ITEMID_NOT_FOUND;
3472*3088717bSVictor Perevertkin break;
3473*3088717bSVictor Perevertkin }
3474*3088717bSVictor Perevertkin }
3475*3088717bSVictor Perevertkin
3476*3088717bSVictor Perevertkin break;
3477*3088717bSVictor Perevertkin }
3478*3088717bSVictor Perevertkin
3479*3088717bSVictor Perevertkin case DiskGeometryGuid:
3480*3088717bSVictor Perevertkin case SmartStatusGuid:
3481*3088717bSVictor Perevertkin case SmartDataGuid:
3482*3088717bSVictor Perevertkin case SmartEventGuid:
3483*3088717bSVictor Perevertkin case SmartThresholdsGuid:
3484*3088717bSVictor Perevertkin case ScsiInfoExceptionsGuid:
3485*3088717bSVictor Perevertkin {
3486*3088717bSVictor Perevertkin sizeNeeded = 0;
3487*3088717bSVictor Perevertkin status = STATUS_INVALID_DEVICE_REQUEST;
3488*3088717bSVictor Perevertkin break;
3489*3088717bSVictor Perevertkin }
3490*3088717bSVictor Perevertkin
3491*3088717bSVictor Perevertkin default:
3492*3088717bSVictor Perevertkin {
3493*3088717bSVictor Perevertkin sizeNeeded = 0;
3494*3088717bSVictor Perevertkin status = STATUS_WMI_GUID_NOT_FOUND;
3495*3088717bSVictor Perevertkin }
3496*3088717bSVictor Perevertkin }
3497*3088717bSVictor Perevertkin
3498*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "Disk: DiskExecuteMethod Device %p, Irp %p returns %lx\n",
3499*3088717bSVictor Perevertkin DeviceObject, Irp, status));
3500*3088717bSVictor Perevertkin
3501*3088717bSVictor Perevertkin status = ClassWmiCompleteRequest(DeviceObject,
3502*3088717bSVictor Perevertkin Irp,
3503*3088717bSVictor Perevertkin status,
3504*3088717bSVictor Perevertkin sizeNeeded,
3505*3088717bSVictor Perevertkin IO_NO_INCREMENT);
3506*3088717bSVictor Perevertkin
3507*3088717bSVictor Perevertkin return status;
3508*3088717bSVictor Perevertkin }
3509*3088717bSVictor Perevertkin
3510*3088717bSVictor Perevertkin
3511