1*3088717bSVictor Perevertkin /*--
2*3088717bSVictor Perevertkin
3*3088717bSVictor Perevertkin Copyright (C) Microsoft Corporation. All rights reserved.
4*3088717bSVictor Perevertkin
5*3088717bSVictor Perevertkin Module Name:
6*3088717bSVictor Perevertkin
7*3088717bSVictor Perevertkin sense.c
8*3088717bSVictor Perevertkin
9*3088717bSVictor Perevertkin Abstract:
10*3088717bSVictor Perevertkin
11*3088717bSVictor Perevertkin This file contains the methods needed to accurately
12*3088717bSVictor Perevertkin determine how to retry requests on CDROM device types.
13*3088717bSVictor Perevertkin
14*3088717bSVictor Perevertkin Environment:
15*3088717bSVictor Perevertkin
16*3088717bSVictor Perevertkin kernel mode only
17*3088717bSVictor Perevertkin
18*3088717bSVictor Perevertkin Revision History:
19*3088717bSVictor Perevertkin
20*3088717bSVictor Perevertkin --*/
21*3088717bSVictor Perevertkin
22*3088717bSVictor Perevertkin #include "stddef.h"
23*3088717bSVictor Perevertkin #include "string.h"
24*3088717bSVictor Perevertkin
25*3088717bSVictor Perevertkin #include "ntddk.h"
26*3088717bSVictor Perevertkin #include "ntddstor.h"
27*3088717bSVictor Perevertkin #include "cdrom.h"
28*3088717bSVictor Perevertkin #include "ntstrsafe.h"
29*3088717bSVictor Perevertkin
30*3088717bSVictor Perevertkin
31*3088717bSVictor Perevertkin #ifdef DEBUG_USE_WPP
32*3088717bSVictor Perevertkin #include "sense.tmh"
33*3088717bSVictor Perevertkin #endif
34*3088717bSVictor Perevertkin
35*3088717bSVictor Perevertkin // Forward declarations
36*3088717bSVictor Perevertkin VOID
37*3088717bSVictor Perevertkin SenseInfoInterpretRefineByIoControl(
38*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
39*3088717bSVictor Perevertkin _In_ ULONG IoControlCode,
40*3088717bSVictor Perevertkin _In_ BOOLEAN OverrideVerifyVolume,
41*3088717bSVictor Perevertkin _Inout_ BOOLEAN* Retry,
42*3088717bSVictor Perevertkin _Inout_ NTSTATUS* Status
43*3088717bSVictor Perevertkin );
44*3088717bSVictor Perevertkin
45*3088717bSVictor Perevertkin
46*3088717bSVictor Perevertkin #ifdef ALLOC_PRAGMA
47*3088717bSVictor Perevertkin
48*3088717bSVictor Perevertkin #pragma alloc_text(PAGE, SenseInfoInterpretRefineByIoControl)
49*3088717bSVictor Perevertkin
50*3088717bSVictor Perevertkin #endif
51*3088717bSVictor Perevertkin
52*3088717bSVictor Perevertkin
53*3088717bSVictor Perevertkin //
54*3088717bSVictor Perevertkin // FROM CLASSPNP\CLASSP.H
55*3088717bSVictor Perevertkin // Lots of retries of synchronized SCSI commands that devices may not
56*3088717bSVictor Perevertkin // even support really slows down the system (especially while booting).
57*3088717bSVictor Perevertkin // (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
58*3088717bSVictor Perevertkin // If a disk cannot return a small initialization buffer at startup
59*3088717bSVictor Perevertkin // in two attempts (with delay interval) then we cannot expect it to return
60*3088717bSVictor Perevertkin // data consistently with four retries.
61*3088717bSVictor Perevertkin // So don't set the retry counts as high here as for data SRBs.
62*3088717bSVictor Perevertkin //
63*3088717bSVictor Perevertkin // If we find that these requests are failing consecutively,
64*3088717bSVictor Perevertkin // despite the retry interval, on otherwise reliable media,
65*3088717bSVictor Perevertkin // then we should either increase the retry interval for
66*3088717bSVictor Perevertkin // that failure or (by all means) increase these retry counts as appropriate.
67*3088717bSVictor Perevertkin //
68*3088717bSVictor Perevertkin
69*3088717bSVictor Perevertkin #define TOTAL_COUNT_RETRY_DEFAULT 4
70*3088717bSVictor Perevertkin #define TOTAL_COUNT_RETRY_LOCK_MEDIA 1
71*3088717bSVictor Perevertkin #define TOTAL_COUNT_RETRY_MODESENSE 1
72*3088717bSVictor Perevertkin #define TOTAL_COUNT_RETRY_READ_CAPACITY 1
73*3088717bSVictor Perevertkin
74*3088717bSVictor Perevertkin
75*3088717bSVictor Perevertkin #define TOTAL_SECONDS_RETRY_TIME_WRITE 160
76*3088717bSVictor Perevertkin #define TOTAL_SECONDS_RETRY_TIME_MEDIUM_REMOVAL 120
77*3088717bSVictor Perevertkin
78*3088717bSVictor Perevertkin typedef struct _ERROR_LOG_CONTEXT {
79*3088717bSVictor Perevertkin BOOLEAN LogError;
80*3088717bSVictor Perevertkin BOOLEAN ErrorUnhandled;
81*3088717bSVictor Perevertkin NTSTATUS ErrorCode;
82*3088717bSVictor Perevertkin ULONG UniqueErrorValue;
83*3088717bSVictor Perevertkin ULONG BadSector;
84*3088717bSVictor Perevertkin } ERROR_LOG_CONTEXT, *PERROR_LOG_CONTEXT;
85*3088717bSVictor Perevertkin
86*3088717bSVictor Perevertkin NTSTATUS
DeviceErrorHandlerForMmc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_ PSCSI_REQUEST_BLOCK Srb,_Inout_ PNTSTATUS Status,_Inout_ PBOOLEAN Retry)87*3088717bSVictor Perevertkin DeviceErrorHandlerForMmc(
88*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
89*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
90*3088717bSVictor Perevertkin _Inout_ PNTSTATUS Status,
91*3088717bSVictor Perevertkin _Inout_ PBOOLEAN Retry
92*3088717bSVictor Perevertkin )
93*3088717bSVictor Perevertkin /*++
94*3088717bSVictor Perevertkin
95*3088717bSVictor Perevertkin Routine Description:
96*3088717bSVictor Perevertkin
97*3088717bSVictor Perevertkin this routine will be used for error handler for all MMC devices.
98*3088717bSVictor Perevertkin it's invoked by DeviceErrorHandler()that invoked by SenseInfoInterpret() or GESN
99*3088717bSVictor Perevertkin
100*3088717bSVictor Perevertkin This routine just checks for media change sense/asc/ascq and
101*3088717bSVictor Perevertkin also for other events, such as bus resets. this is used to
102*3088717bSVictor Perevertkin determine if the device behaviour has changed, to allow for
103*3088717bSVictor Perevertkin read and write operations to be allowed and/or disallowed.
104*3088717bSVictor Perevertkin
105*3088717bSVictor Perevertkin Arguments:
106*3088717bSVictor Perevertkin
107*3088717bSVictor Perevertkin DeviceExtension - device context
108*3088717bSVictor Perevertkin Srb - SRB structure for analyze
109*3088717bSVictor Perevertkin
110*3088717bSVictor Perevertkin Return Value:
111*3088717bSVictor Perevertkin
112*3088717bSVictor Perevertkin NTSTATUS
113*3088717bSVictor Perevertkin Status -
114*3088717bSVictor Perevertkin Retry -
115*3088717bSVictor Perevertkin
116*3088717bSVictor Perevertkin --*/
117*3088717bSVictor Perevertkin {
118*3088717bSVictor Perevertkin BOOLEAN mediaChange = FALSE;
119*3088717bSVictor Perevertkin PCDB cdb = (PCDB)Srb->Cdb;
120*3088717bSVictor Perevertkin
121*3088717bSVictor Perevertkin if (TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
122*3088717bSVictor Perevertkin {
123*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
124*3088717bSVictor Perevertkin
125*3088717bSVictor Perevertkin // the following sense keys could indicate a change in capabilities.
126*3088717bSVictor Perevertkin
127*3088717bSVictor Perevertkin // we used to expect this to be serialized, and only hit from our
128*3088717bSVictor Perevertkin // own routine. we now allow some requests to continue during our
129*3088717bSVictor Perevertkin // processing of the capabilities update in order to allow
130*3088717bSVictor Perevertkin // IoReadPartitionTable() to succeed.
131*3088717bSVictor Perevertkin switch (senseBuffer->SenseKey & 0xf)
132*3088717bSVictor Perevertkin {
133*3088717bSVictor Perevertkin
134*3088717bSVictor Perevertkin case SCSI_SENSE_NOT_READY:
135*3088717bSVictor Perevertkin {
136*3088717bSVictor Perevertkin if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
137*3088717bSVictor Perevertkin {
138*3088717bSVictor Perevertkin if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
139*3088717bSVictor Perevertkin {
140*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
141*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: media removed, writes will be "
142*3088717bSVictor Perevertkin "failed until new media detected\n"));
143*3088717bSVictor Perevertkin }
144*3088717bSVictor Perevertkin
145*3088717bSVictor Perevertkin // NOTE - REF #0002
146*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
147*3088717bSVictor Perevertkin }
148*3088717bSVictor Perevertkin else if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)
149*3088717bSVictor Perevertkin {
150*3088717bSVictor Perevertkin if (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_BECOMING_READY)
151*3088717bSVictor Perevertkin {
152*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
153*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: media becoming ready, "
154*3088717bSVictor Perevertkin "SHOULD notify shell of change time by sending "
155*3088717bSVictor Perevertkin "GESN request immediately!\n"));
156*3088717bSVictor Perevertkin }
157*3088717bSVictor Perevertkin else if (((senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_OPERATION_IN_PROGRESS) ||
158*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)
159*3088717bSVictor Perevertkin ) &&
160*3088717bSVictor Perevertkin ((Srb->Cdb[0] == SCSIOP_READ) ||
161*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ6) ||
162*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ_CAPACITY) ||
163*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ_CD) ||
164*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ_CD_MSF) ||
165*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ_TOC) ||
166*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_WRITE) ||
167*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_WRITE6) ||
168*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ_TRACK_INFORMATION) ||
169*3088717bSVictor Perevertkin (Srb->Cdb[0] == SCSIOP_READ_DISK_INFORMATION)
170*3088717bSVictor Perevertkin )
171*3088717bSVictor Perevertkin )
172*3088717bSVictor Perevertkin {
173*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
174*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: LONG_WRITE or "
175*3088717bSVictor Perevertkin "OP_IN_PROGRESS for limited subset of cmds -- "
176*3088717bSVictor Perevertkin "setting retry to TRUE\n"));
177*3088717bSVictor Perevertkin *Retry = TRUE;
178*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_BUSY;
179*3088717bSVictor Perevertkin }
180*3088717bSVictor Perevertkin }
181*3088717bSVictor Perevertkin break;
182*3088717bSVictor Perevertkin } // end SCSI_SENSE_NOT_READY
183*3088717bSVictor Perevertkin
184*3088717bSVictor Perevertkin case SCSI_SENSE_UNIT_ATTENTION:
185*3088717bSVictor Perevertkin {
186*3088717bSVictor Perevertkin switch (senseBuffer->AdditionalSenseCode)
187*3088717bSVictor Perevertkin {
188*3088717bSVictor Perevertkin case SCSI_ADSENSE_MEDIUM_CHANGED:
189*3088717bSVictor Perevertkin {
190*3088717bSVictor Perevertkin // always update if the medium may have changed
191*3088717bSVictor Perevertkin
192*3088717bSVictor Perevertkin // NOTE - REF #0002
193*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
194*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
195*3088717bSVictor Perevertkin
196*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
197*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: media change detected, need to "
198*3088717bSVictor Perevertkin "update drive capabilities\n"));
199*3088717bSVictor Perevertkin mediaChange = TRUE;
200*3088717bSVictor Perevertkin break;
201*3088717bSVictor Perevertkin
202*3088717bSVictor Perevertkin } // end SCSI_ADSENSE_MEDIUM_CHANGED
203*3088717bSVictor Perevertkin
204*3088717bSVictor Perevertkin case SCSI_ADSENSE_BUS_RESET:
205*3088717bSVictor Perevertkin {
206*3088717bSVictor Perevertkin // NOTE - REF #0002
207*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
208*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
209*3088717bSVictor Perevertkin
210*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
211*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: bus reset detected, need to "
212*3088717bSVictor Perevertkin "update drive capabilities\n"));
213*3088717bSVictor Perevertkin break;
214*3088717bSVictor Perevertkin
215*3088717bSVictor Perevertkin } // end SCSI_ADSENSE_BUS_RESET
216*3088717bSVictor Perevertkin
217*3088717bSVictor Perevertkin case SCSI_ADSENSE_OPERATOR_REQUEST:
218*3088717bSVictor Perevertkin {
219*3088717bSVictor Perevertkin
220*3088717bSVictor Perevertkin BOOLEAN b = FALSE;
221*3088717bSVictor Perevertkin
222*3088717bSVictor Perevertkin switch (senseBuffer->AdditionalSenseCodeQualifier)
223*3088717bSVictor Perevertkin {
224*3088717bSVictor Perevertkin case SCSI_SENSEQ_MEDIUM_REMOVAL:
225*3088717bSVictor Perevertkin {
226*3088717bSVictor Perevertkin // eject notification currently handled by classpnp
227*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
228*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: Eject requested by user\n"));
229*3088717bSVictor Perevertkin *Retry = TRUE;
230*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_BUSY;
231*3088717bSVictor Perevertkin break;
232*3088717bSVictor Perevertkin }
233*3088717bSVictor Perevertkin
234*3088717bSVictor Perevertkin case SCSI_SENSEQ_WRITE_PROTECT_DISABLE:
235*3088717bSVictor Perevertkin b = TRUE;
236*3088717bSVictor Perevertkin case SCSI_SENSEQ_WRITE_PROTECT_ENABLE:
237*3088717bSVictor Perevertkin {
238*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
239*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: Write protect %s requested "
240*3088717bSVictor Perevertkin "by user\n",
241*3088717bSVictor Perevertkin (b ? "disable" : "enable")));
242*3088717bSVictor Perevertkin *Retry = TRUE;
243*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_BUSY;
244*3088717bSVictor Perevertkin // NOTE - REF #0002
245*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
246*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
247*3088717bSVictor Perevertkin
248*3088717bSVictor Perevertkin break;
249*3088717bSVictor Perevertkin }
250*3088717bSVictor Perevertkin
251*3088717bSVictor Perevertkin } // end of AdditionalSenseCodeQualifier switch
252*3088717bSVictor Perevertkin
253*3088717bSVictor Perevertkin
254*3088717bSVictor Perevertkin break;
255*3088717bSVictor Perevertkin
256*3088717bSVictor Perevertkin } // end SCSI_ADSENSE_OPERATOR_REQUEST
257*3088717bSVictor Perevertkin
258*3088717bSVictor Perevertkin default:
259*3088717bSVictor Perevertkin {
260*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
261*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: Unit attention %02x/%02x\n",
262*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode,
263*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCodeQualifier));
264*3088717bSVictor Perevertkin break;
265*3088717bSVictor Perevertkin }
266*3088717bSVictor Perevertkin
267*3088717bSVictor Perevertkin } // end of AdditionSenseCode switch
268*3088717bSVictor Perevertkin break;
269*3088717bSVictor Perevertkin
270*3088717bSVictor Perevertkin } // end SCSI_SENSE_UNIT_ATTENTION
271*3088717bSVictor Perevertkin
272*3088717bSVictor Perevertkin case SCSI_SENSE_ILLEGAL_REQUEST:
273*3088717bSVictor Perevertkin {
274*3088717bSVictor Perevertkin if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_WRITE_PROTECT)
275*3088717bSVictor Perevertkin {
276*3088717bSVictor Perevertkin if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
277*3088717bSVictor Perevertkin {
278*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
279*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: media was writable, but "
280*3088717bSVictor Perevertkin "failed request with WRITE_PROTECT error...\n"));
281*3088717bSVictor Perevertkin }
282*3088717bSVictor Perevertkin // NOTE - REF #0002
283*3088717bSVictor Perevertkin // do not update all the capabilities just because
284*3088717bSVictor Perevertkin // we can't write to the disc.
285*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
286*3088717bSVictor Perevertkin }
287*3088717bSVictor Perevertkin break;
288*3088717bSVictor Perevertkin } // end SCSI_SENSE_ILLEGAL_REQUEST
289*3088717bSVictor Perevertkin
290*3088717bSVictor Perevertkin } // end of SenseKey switch
291*3088717bSVictor Perevertkin
292*3088717bSVictor Perevertkin // Check if we failed to set the DVD region key and send appropriate error
293*3088717bSVictor Perevertkin if (cdb->CDB16.OperationCode == SCSIOP_SEND_KEY)
294*3088717bSVictor Perevertkin {
295*3088717bSVictor Perevertkin if (cdb->SEND_KEY.KeyFormat == DvdSetRpcKey)
296*3088717bSVictor Perevertkin {
297*3088717bSVictor Perevertkin if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
298*3088717bSVictor Perevertkin {
299*3088717bSVictor Perevertkin // media of appropriate region required
300*3088717bSVictor Perevertkin *Status = STATUS_NO_MEDIA_IN_DEVICE;
301*3088717bSVictor Perevertkin *Retry = FALSE;
302*3088717bSVictor Perevertkin }
303*3088717bSVictor Perevertkin else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
304*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_COPY_PROTECTION_FAILURE) &&
305*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT))
306*3088717bSVictor Perevertkin {
307*3088717bSVictor Perevertkin // media of appropriate region required
308*3088717bSVictor Perevertkin *Status = STATUS_CSS_REGION_MISMATCH;
309*3088717bSVictor Perevertkin *Retry = FALSE;
310*3088717bSVictor Perevertkin }
311*3088717bSVictor Perevertkin else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
312*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_INVALID_MEDIA) &&
313*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_INCOMPATIBLE_FORMAT))
314*3088717bSVictor Perevertkin {
315*3088717bSVictor Perevertkin // media of appropriate region required
316*3088717bSVictor Perevertkin *Status = STATUS_CSS_REGION_MISMATCH;
317*3088717bSVictor Perevertkin *Retry = FALSE;
318*3088717bSVictor Perevertkin }
319*3088717bSVictor Perevertkin }
320*3088717bSVictor Perevertkin }
321*3088717bSVictor Perevertkin } // end of SRB_STATUS_AUTOSENSE_VALID
322*3088717bSVictor Perevertkin
323*3088717bSVictor Perevertkin // On media change, if device speed should be reset to default then
324*3088717bSVictor Perevertkin // queue a workitem to send the commands to the device. Do this on
325*3088717bSVictor Perevertkin // media arrival as some device will fail this command if no media
326*3088717bSVictor Perevertkin // is present. Ignore the fake media change from classpnp driver.
327*3088717bSVictor Perevertkin if ((mediaChange == TRUE) && (*Status != STATUS_MEDIA_CHANGED))
328*3088717bSVictor Perevertkin {
329*3088717bSVictor Perevertkin if (DeviceExtension->DeviceAdditionalData.RestoreDefaults == TRUE)
330*3088717bSVictor Perevertkin {
331*3088717bSVictor Perevertkin NTSTATUS status = STATUS_SUCCESS;
332*3088717bSVictor Perevertkin WDF_OBJECT_ATTRIBUTES attributes;
333*3088717bSVictor Perevertkin WDF_WORKITEM_CONFIG workitemConfig;
334*3088717bSVictor Perevertkin WDFWORKITEM workItem;
335*3088717bSVictor Perevertkin
336*3088717bSVictor Perevertkin WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
337*3088717bSVictor Perevertkin attributes.ParentObject = DeviceExtension->Device;
338*3088717bSVictor Perevertkin
339*3088717bSVictor Perevertkin WDF_WORKITEM_CONFIG_INIT(&workitemConfig,
340*3088717bSVictor Perevertkin DeviceRestoreDefaultSpeed);
341*3088717bSVictor Perevertkin
342*3088717bSVictor Perevertkin status = WdfWorkItemCreate(&workitemConfig,
343*3088717bSVictor Perevertkin &attributes,
344*3088717bSVictor Perevertkin &workItem);
345*3088717bSVictor Perevertkin if (!NT_SUCCESS(status))
346*3088717bSVictor Perevertkin {
347*3088717bSVictor Perevertkin return STATUS_SUCCESS;
348*3088717bSVictor Perevertkin }
349*3088717bSVictor Perevertkin
350*3088717bSVictor Perevertkin WdfWorkItemEnqueue(workItem);
351*3088717bSVictor Perevertkin
352*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
353*3088717bSVictor Perevertkin "DeviceErrorHandlerForMmc: Restore device default speed for %p\n",
354*3088717bSVictor Perevertkin DeviceExtension->DeviceObject));
355*3088717bSVictor Perevertkin }
356*3088717bSVictor Perevertkin }
357*3088717bSVictor Perevertkin return STATUS_SUCCESS;
358*3088717bSVictor Perevertkin }
359*3088717bSVictor Perevertkin
360*3088717bSVictor Perevertkin NTSTATUS
DeviceErrorHandlerForHitachiGD2000(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_ PSCSI_REQUEST_BLOCK Srb,_Inout_ PNTSTATUS Status,_Inout_ PBOOLEAN Retry)361*3088717bSVictor Perevertkin DeviceErrorHandlerForHitachiGD2000(
362*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
363*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
364*3088717bSVictor Perevertkin _Inout_ PNTSTATUS Status,
365*3088717bSVictor Perevertkin _Inout_ PBOOLEAN Retry
366*3088717bSVictor Perevertkin )
367*3088717bSVictor Perevertkin /*++
368*3088717bSVictor Perevertkin
369*3088717bSVictor Perevertkin Routine Description:
370*3088717bSVictor Perevertkin
371*3088717bSVictor Perevertkin error handler for HITACHI CDR-1750S, CDR-3650/1650S
372*3088717bSVictor Perevertkin
373*3088717bSVictor Perevertkin This routine checks the type of error. If the error suggests that the
374*3088717bSVictor Perevertkin drive has spun down and cannot reinitialize itself, send a
375*3088717bSVictor Perevertkin START_UNIT or READ to the device. This will force the drive to spin
376*3088717bSVictor Perevertkin up. This drive also loses the AGIDs it has granted when it spins down,
377*3088717bSVictor Perevertkin which may result in playback failure the first time around.
378*3088717bSVictor Perevertkin
379*3088717bSVictor Perevertkin Arguments:
380*3088717bSVictor Perevertkin
381*3088717bSVictor Perevertkin DeviceExtension - the device object.
382*3088717bSVictor Perevertkin
383*3088717bSVictor Perevertkin Srb - Supplies a pointer to the failing Srb.
384*3088717bSVictor Perevertkin
385*3088717bSVictor Perevertkin Status - return the final status for this command?
386*3088717bSVictor Perevertkin
387*3088717bSVictor Perevertkin Retry - return if the command should be retried.
388*3088717bSVictor Perevertkin
389*3088717bSVictor Perevertkin Return Value:
390*3088717bSVictor Perevertkin
391*3088717bSVictor Perevertkin None.
392*3088717bSVictor Perevertkin
393*3088717bSVictor Perevertkin --*/
394*3088717bSVictor Perevertkin {
395*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
396*3088717bSVictor Perevertkin
397*3088717bSVictor Perevertkin if (!TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
398*3088717bSVictor Perevertkin {
399*3088717bSVictor Perevertkin return STATUS_SUCCESS; //nobody cares about this return value yet.
400*3088717bSVictor Perevertkin }
401*3088717bSVictor Perevertkin
402*3088717bSVictor Perevertkin if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_HARDWARE_ERROR) &&
403*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCode == 0x44))
404*3088717bSVictor Perevertkin {
405*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
406*3088717bSVictor Perevertkin "DeviceErrorHandlerForHitachiGD2000 (%p) => Internal Target "
407*3088717bSVictor Perevertkin "Failure Detected -- spinning up drive\n", DeviceExtension->Device));
408*3088717bSVictor Perevertkin
409*3088717bSVictor Perevertkin // the request should be retried because the device isn't ready
410*3088717bSVictor Perevertkin *Retry = TRUE;
411*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
412*3088717bSVictor Perevertkin
413*3088717bSVictor Perevertkin // send a START_STOP unit to spin up the drive
414*3088717bSVictor Perevertkin // NOTE: this temporarily violates the StartIo serialization
415*3088717bSVictor Perevertkin // mechanism, but the completion routine on this will NOT
416*3088717bSVictor Perevertkin // call StartNextPacket(), so it's a temporary disruption
417*3088717bSVictor Perevertkin // of the serialization only.
418*3088717bSVictor Perevertkin DeviceSendStartUnit(DeviceExtension->Device);
419*3088717bSVictor Perevertkin }
420*3088717bSVictor Perevertkin
421*3088717bSVictor Perevertkin return STATUS_SUCCESS;
422*3088717bSVictor Perevertkin }
423*3088717bSVictor Perevertkin
424*3088717bSVictor Perevertkin
425*3088717bSVictor Perevertkin VOID
SenseInfoRequestGetInformation(_In_ WDFREQUEST Request,_Out_ UCHAR * MajorFunctionCode,_Out_ ULONG * IoControlCode,_Out_ BOOLEAN * OverrideVerifyVolume,_Out_ ULONGLONG * Total100nsSinceFirstSend)426*3088717bSVictor Perevertkin SenseInfoRequestGetInformation(
427*3088717bSVictor Perevertkin _In_ WDFREQUEST Request,
428*3088717bSVictor Perevertkin _Out_ UCHAR* MajorFunctionCode,
429*3088717bSVictor Perevertkin _Out_ ULONG* IoControlCode,
430*3088717bSVictor Perevertkin _Out_ BOOLEAN* OverrideVerifyVolume,
431*3088717bSVictor Perevertkin _Out_ ULONGLONG* Total100nsSinceFirstSend
432*3088717bSVictor Perevertkin )
433*3088717bSVictor Perevertkin {
434*3088717bSVictor Perevertkin PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
435*3088717bSVictor Perevertkin
436*3088717bSVictor Perevertkin *MajorFunctionCode = 0;
437*3088717bSVictor Perevertkin *IoControlCode = 0;
438*3088717bSVictor Perevertkin *OverrideVerifyVolume = FALSE;
439*3088717bSVictor Perevertkin *Total100nsSinceFirstSend = 0;
440*3088717bSVictor Perevertkin
441*3088717bSVictor Perevertkin if (requestContext->OriginalRequest != NULL)
442*3088717bSVictor Perevertkin {
443*3088717bSVictor Perevertkin PIO_STACK_LOCATION originalIrpStack = NULL;
444*3088717bSVictor Perevertkin
445*3088717bSVictor Perevertkin PIRP originalIrp = WdfRequestWdmGetIrp(requestContext->OriginalRequest);
446*3088717bSVictor Perevertkin
447*3088717bSVictor Perevertkin if (originalIrp != NULL)
448*3088717bSVictor Perevertkin {
449*3088717bSVictor Perevertkin originalIrpStack = IoGetCurrentIrpStackLocation(originalIrp);
450*3088717bSVictor Perevertkin }
451*3088717bSVictor Perevertkin
452*3088717bSVictor Perevertkin if (originalIrpStack != NULL)
453*3088717bSVictor Perevertkin {
454*3088717bSVictor Perevertkin *MajorFunctionCode = originalIrpStack->MajorFunction;
455*3088717bSVictor Perevertkin
456*3088717bSVictor Perevertkin if (*MajorFunctionCode == IRP_MJ_DEVICE_CONTROL)
457*3088717bSVictor Perevertkin {
458*3088717bSVictor Perevertkin *IoControlCode = originalIrpStack->Parameters.DeviceIoControl.IoControlCode;
459*3088717bSVictor Perevertkin }
460*3088717bSVictor Perevertkin
461*3088717bSVictor Perevertkin *OverrideVerifyVolume = TEST_FLAG(originalIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);
462*3088717bSVictor Perevertkin }
463*3088717bSVictor Perevertkin }
464*3088717bSVictor Perevertkin
465*3088717bSVictor Perevertkin // Calculate time past since the request was first time sent.
466*3088717bSVictor Perevertkin if (requestContext->TimeSentDownFirstTime.QuadPart > 0)
467*3088717bSVictor Perevertkin {
468*3088717bSVictor Perevertkin LARGE_INTEGER tmp;
469*3088717bSVictor Perevertkin KeQueryTickCount(&tmp);
470*3088717bSVictor Perevertkin tmp.QuadPart -= requestContext->TimeSentDownFirstTime.QuadPart;
471*3088717bSVictor Perevertkin tmp.QuadPart *= KeQueryTimeIncrement();
472*3088717bSVictor Perevertkin *Total100nsSinceFirstSend = tmp.QuadPart;
473*3088717bSVictor Perevertkin }
474*3088717bSVictor Perevertkin else
475*3088717bSVictor Perevertkin {
476*3088717bSVictor Perevertkin // set to -1 if field TimeSentDownFirstTime not set.
477*3088717bSVictor Perevertkin *Total100nsSinceFirstSend = (ULONGLONG) -1;
478*3088717bSVictor Perevertkin }
479*3088717bSVictor Perevertkin
480*3088717bSVictor Perevertkin return;
481*3088717bSVictor Perevertkin }
482*3088717bSVictor Perevertkin
483*3088717bSVictor Perevertkin BOOLEAN
484*3088717bSVictor Perevertkin SenseInfoInterpretByAdditionalSenseCode(
485*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
486*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
487*3088717bSVictor Perevertkin _In_ UCHAR AdditionalSenseCode,
488*3088717bSVictor Perevertkin _In_ UCHAR AdditionalSenseCodeQual,
489*3088717bSVictor Perevertkin _Inout_ NTSTATUS* Status,
490*3088717bSVictor Perevertkin _Inout_ BOOLEAN* Retry,
491*3088717bSVictor Perevertkin _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds,
492*3088717bSVictor Perevertkin _Inout_ PERROR_LOG_CONTEXT LogContext
493*3088717bSVictor Perevertkin )
494*3088717bSVictor Perevertkin /*
495*3088717bSVictor Perevertkin This function will interpret error based on ASC/ASCQ.
496*3088717bSVictor Perevertkin
497*3088717bSVictor Perevertkin If the error code is not processed in this function, e.g. return value is TRUE,
498*3088717bSVictor Perevertkin caller needs to call SenseInfoInterpretBySenseKey() for further interpret.
499*3088717bSVictor Perevertkin */
500*3088717bSVictor Perevertkin {
501*3088717bSVictor Perevertkin BOOLEAN needFurtherInterpret = TRUE;
502*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
503*3088717bSVictor Perevertkin
504*3088717bSVictor Perevertkin // set default values for retry fields.
505*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
506*3088717bSVictor Perevertkin *Retry = TRUE;
507*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
508*3088717bSVictor Perevertkin
509*3088717bSVictor Perevertkin switch (AdditionalSenseCode)
510*3088717bSVictor Perevertkin {
511*3088717bSVictor Perevertkin case SCSI_ADSENSE_LUN_NOT_READY:
512*3088717bSVictor Perevertkin {
513*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
514*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Lun not ready\n"));
515*3088717bSVictor Perevertkin
516*3088717bSVictor Perevertkin //
517*3088717bSVictor Perevertkin // Many non-WHQL certified drives (mostly CD-RW) return
518*3088717bSVictor Perevertkin // 2/4/0 when they have no media instead of the obvious choice of:
519*3088717bSVictor Perevertkin //
520*3088717bSVictor Perevertkin // SCSI_SENSE_NOT_READY/SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
521*3088717bSVictor Perevertkin //
522*3088717bSVictor Perevertkin // These drives should not pass WHQL certification due to this discrepency.
523*3088717bSVictor Perevertkin //
524*3088717bSVictor Perevertkin // However, we have to retry on 2/4/0 (Not ready, LUN not ready, no info)
525*3088717bSVictor Perevertkin // and also 3/2/0 (no seek complete).
526*3088717bSVictor Perevertkin //
527*3088717bSVictor Perevertkin // These conditions occur when the shell tries to examine an
528*3088717bSVictor Perevertkin // injected CD (e.g. for autoplay) before the CD is spun up.
529*3088717bSVictor Perevertkin //
530*3088717bSVictor Perevertkin // The drive should be returning an ASCQ of SCSI_SENSEQ_BECOMING_READY
531*3088717bSVictor Perevertkin // (0x01) in order to comply with WHQL standards.
532*3088717bSVictor Perevertkin //
533*3088717bSVictor Perevertkin // The default retry timeout of one second is acceptable to balance
534*3088717bSVictor Perevertkin // these discrepencies. don't modify the status, though....
535*3088717bSVictor Perevertkin //
536*3088717bSVictor Perevertkin
537*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
538*3088717bSVictor Perevertkin {
539*3088717bSVictor Perevertkin case SCSI_SENSEQ_OPERATION_IN_PROGRESS:
540*3088717bSVictor Perevertkin {
541*3088717bSVictor Perevertkin DEVICE_EVENT_BECOMING_READY notReady = {0};
542*3088717bSVictor Perevertkin
543*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
544*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Operation In Progress\n"));
545*3088717bSVictor Perevertkin
546*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
547*3088717bSVictor Perevertkin
548*3088717bSVictor Perevertkin *Retry = TRUE;
549*3088717bSVictor Perevertkin *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
550*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
551*3088717bSVictor Perevertkin
552*3088717bSVictor Perevertkin notReady.Version = 1;
553*3088717bSVictor Perevertkin notReady.Reason = 2;
554*3088717bSVictor Perevertkin notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10;
555*3088717bSVictor Perevertkin DeviceSendNotification(DeviceExtension,
556*3088717bSVictor Perevertkin &GUID_IO_DEVICE_BECOMING_READY,
557*3088717bSVictor Perevertkin sizeof(DEVICE_EVENT_BECOMING_READY),
558*3088717bSVictor Perevertkin ¬Ready);
559*3088717bSVictor Perevertkin
560*3088717bSVictor Perevertkin break;
561*3088717bSVictor Perevertkin }
562*3088717bSVictor Perevertkin
563*3088717bSVictor Perevertkin case SCSI_SENSEQ_BECOMING_READY:
564*3088717bSVictor Perevertkin {
565*3088717bSVictor Perevertkin DEVICE_EVENT_BECOMING_READY notReady = {0};
566*3088717bSVictor Perevertkin
567*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
568*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: In process of becoming ready\n"));
569*3088717bSVictor Perevertkin
570*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
571*3088717bSVictor Perevertkin
572*3088717bSVictor Perevertkin *Retry = TRUE;
573*3088717bSVictor Perevertkin *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
574*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
575*3088717bSVictor Perevertkin
576*3088717bSVictor Perevertkin notReady.Version = 1;
577*3088717bSVictor Perevertkin notReady.Reason = 1;
578*3088717bSVictor Perevertkin notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10;
579*3088717bSVictor Perevertkin DeviceSendNotification(DeviceExtension,
580*3088717bSVictor Perevertkin &GUID_IO_DEVICE_BECOMING_READY,
581*3088717bSVictor Perevertkin sizeof(DEVICE_EVENT_BECOMING_READY),
582*3088717bSVictor Perevertkin ¬Ready);
583*3088717bSVictor Perevertkin
584*3088717bSVictor Perevertkin break;
585*3088717bSVictor Perevertkin }
586*3088717bSVictor Perevertkin
587*3088717bSVictor Perevertkin case SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS:
588*3088717bSVictor Perevertkin {
589*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
590*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Long write in progress\n"));
591*3088717bSVictor Perevertkin
592*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
593*3088717bSVictor Perevertkin
594*3088717bSVictor Perevertkin // This has been seen as a transcient failure on some drives
595*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
596*3088717bSVictor Perevertkin *Retry = TRUE;
597*3088717bSVictor Perevertkin // Set retry interval to be 0 as the drive can be ready at anytime.
598*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
599*3088717bSVictor Perevertkin
600*3088717bSVictor Perevertkin break;
601*3088717bSVictor Perevertkin }
602*3088717bSVictor Perevertkin
603*3088717bSVictor Perevertkin case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:
604*3088717bSVictor Perevertkin {
605*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
606*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Manual intervention required\n"));
607*3088717bSVictor Perevertkin
608*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
609*3088717bSVictor Perevertkin
610*3088717bSVictor Perevertkin *Status = STATUS_NO_MEDIA_IN_DEVICE;
611*3088717bSVictor Perevertkin *Retry = FALSE;
612*3088717bSVictor Perevertkin *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
613*3088717bSVictor Perevertkin
614*3088717bSVictor Perevertkin break;
615*3088717bSVictor Perevertkin }
616*3088717bSVictor Perevertkin
617*3088717bSVictor Perevertkin case SCSI_SENSEQ_FORMAT_IN_PROGRESS:
618*3088717bSVictor Perevertkin {
619*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
620*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Format in progress\n"));
621*3088717bSVictor Perevertkin
622*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
623*3088717bSVictor Perevertkin
624*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
625*3088717bSVictor Perevertkin *Retry = FALSE;
626*3088717bSVictor Perevertkin *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
627*3088717bSVictor Perevertkin
628*3088717bSVictor Perevertkin break;
629*3088717bSVictor Perevertkin }
630*3088717bSVictor Perevertkin
631*3088717bSVictor Perevertkin case SCSI_SENSEQ_CAUSE_NOT_REPORTABLE:
632*3088717bSVictor Perevertkin case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:
633*3088717bSVictor Perevertkin default:
634*3088717bSVictor Perevertkin {
635*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
636*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Initializing command required\n"));
637*3088717bSVictor Perevertkin
638*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
639*3088717bSVictor Perevertkin
640*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
641*3088717bSVictor Perevertkin *Retry = TRUE;
642*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
643*3088717bSVictor Perevertkin
644*3088717bSVictor Perevertkin // This sense code/additional sense code combination may indicate
645*3088717bSVictor Perevertkin // that the device needs to be started.
646*3088717bSVictor Perevertkin if (TEST_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT) &&
647*3088717bSVictor Perevertkin !TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_LOW_PRIORITY))
648*3088717bSVictor Perevertkin {
649*3088717bSVictor Perevertkin DeviceSendStartUnit(DeviceExtension->Device);
650*3088717bSVictor Perevertkin }
651*3088717bSVictor Perevertkin
652*3088717bSVictor Perevertkin break;
653*3088717bSVictor Perevertkin }
654*3088717bSVictor Perevertkin } // end switch (AdditionalSenseCodeQual)
655*3088717bSVictor Perevertkin break;
656*3088717bSVictor Perevertkin
657*3088717bSVictor Perevertkin } // end case (SCSI_ADSENSE_LUN_NOT_READY)
658*3088717bSVictor Perevertkin
659*3088717bSVictor Perevertkin case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
660*3088717bSVictor Perevertkin {
661*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
662*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: No Media in device.\n"));
663*3088717bSVictor Perevertkin
664*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
665*3088717bSVictor Perevertkin
666*3088717bSVictor Perevertkin *Status = STATUS_NO_MEDIA_IN_DEVICE;
667*3088717bSVictor Perevertkin *Retry = FALSE;
668*3088717bSVictor Perevertkin
669*3088717bSVictor Perevertkin if (AdditionalSenseCodeQual == 0xCC)
670*3088717bSVictor Perevertkin {
671*3088717bSVictor Perevertkin // The IMAPIv1 filter returns this ASCQ value while it is burning CD media, and we want
672*3088717bSVictor Perevertkin // to preserve this functionality for compatibility reasons.
673*3088717bSVictor Perevertkin // We want to indicate that the media is not present to most applications;
674*3088717bSVictor Perevertkin // but RSM has to know that the media is still in the drive (i.e. the drive is not free).
675*3088717bSVictor Perevertkin DeviceSetMediaChangeStateEx(DeviceExtension, MediaUnavailable, NULL);
676*3088717bSVictor Perevertkin }
677*3088717bSVictor Perevertkin else
678*3088717bSVictor Perevertkin {
679*3088717bSVictor Perevertkin DeviceSetMediaChangeStateEx(DeviceExtension, MediaNotPresent, NULL);
680*3088717bSVictor Perevertkin }
681*3088717bSVictor Perevertkin
682*3088717bSVictor Perevertkin break;
683*3088717bSVictor Perevertkin } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
684*3088717bSVictor Perevertkin
685*3088717bSVictor Perevertkin case SCSI_ADSENSE_INVALID_MEDIA:
686*3088717bSVictor Perevertkin {
687*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
688*3088717bSVictor Perevertkin {
689*3088717bSVictor Perevertkin
690*3088717bSVictor Perevertkin case SCSI_SENSEQ_UNKNOWN_FORMAT:
691*3088717bSVictor Perevertkin {
692*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
693*3088717bSVictor Perevertkin
694*3088717bSVictor Perevertkin // Log error only if this is a paging request
695*3088717bSVictor Perevertkin *Status = STATUS_UNRECOGNIZED_MEDIA;
696*3088717bSVictor Perevertkin *Retry = FALSE;
697*3088717bSVictor Perevertkin
698*3088717bSVictor Perevertkin LogContext->LogError = TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING);
699*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 256;
700*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
701*3088717bSVictor Perevertkin
702*3088717bSVictor Perevertkin break;
703*3088717bSVictor Perevertkin }
704*3088717bSVictor Perevertkin
705*3088717bSVictor Perevertkin case SCSI_SENSEQ_INCOMPATIBLE_FORMAT:
706*3088717bSVictor Perevertkin {
707*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
708*3088717bSVictor Perevertkin
709*3088717bSVictor Perevertkin *Status = STATUS_UNRECOGNIZED_MEDIA;
710*3088717bSVictor Perevertkin *Retry = FALSE;
711*3088717bSVictor Perevertkin
712*3088717bSVictor Perevertkin LogContext->LogError = FALSE;
713*3088717bSVictor Perevertkin
714*3088717bSVictor Perevertkin break;
715*3088717bSVictor Perevertkin }
716*3088717bSVictor Perevertkin
717*3088717bSVictor Perevertkin case SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED:
718*3088717bSVictor Perevertkin {
719*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
720*3088717bSVictor Perevertkin
721*3088717bSVictor Perevertkin *Status = STATUS_CLEANER_CARTRIDGE_INSTALLED;
722*3088717bSVictor Perevertkin *Retry = FALSE;
723*3088717bSVictor Perevertkin
724*3088717bSVictor Perevertkin LogContext->LogError = FALSE;
725*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 256;
726*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
727*3088717bSVictor Perevertkin break;
728*3088717bSVictor Perevertkin }
729*3088717bSVictor Perevertkin
730*3088717bSVictor Perevertkin default:
731*3088717bSVictor Perevertkin {
732*3088717bSVictor Perevertkin needFurtherInterpret = TRUE;
733*3088717bSVictor Perevertkin break;
734*3088717bSVictor Perevertkin }
735*3088717bSVictor Perevertkin } // end case AdditionalSenseCodeQual
736*3088717bSVictor Perevertkin
737*3088717bSVictor Perevertkin break;
738*3088717bSVictor Perevertkin } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
739*3088717bSVictor Perevertkin
740*3088717bSVictor Perevertkin case SCSI_ADSENSE_NO_SEEK_COMPLETE:
741*3088717bSVictor Perevertkin {
742*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
743*3088717bSVictor Perevertkin {
744*3088717bSVictor Perevertkin
745*3088717bSVictor Perevertkin case 0x00:
746*3088717bSVictor Perevertkin {
747*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
748*3088717bSVictor Perevertkin
749*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_DATA_ERROR;
750*3088717bSVictor Perevertkin *Retry = TRUE;
751*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
752*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
753*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 256;
754*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
755*3088717bSVictor Perevertkin break;
756*3088717bSVictor Perevertkin }
757*3088717bSVictor Perevertkin
758*3088717bSVictor Perevertkin default:
759*3088717bSVictor Perevertkin {
760*3088717bSVictor Perevertkin needFurtherInterpret = TRUE;
761*3088717bSVictor Perevertkin break;
762*3088717bSVictor Perevertkin }
763*3088717bSVictor Perevertkin }
764*3088717bSVictor Perevertkin
765*3088717bSVictor Perevertkin break;
766*3088717bSVictor Perevertkin } // end case SCSI_ADSENSE_NO_SEEK_COMPLETE
767*3088717bSVictor Perevertkin
768*3088717bSVictor Perevertkin case SCSI_ADSENSE_LUN_COMMUNICATION:
769*3088717bSVictor Perevertkin {
770*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
771*3088717bSVictor Perevertkin {
772*3088717bSVictor Perevertkin
773*3088717bSVictor Perevertkin case SCSI_SESNEQ_COMM_CRC_ERROR:
774*3088717bSVictor Perevertkin {
775*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
776*3088717bSVictor Perevertkin
777*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
778*3088717bSVictor Perevertkin *Retry = TRUE;
779*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 1;
780*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
781*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 257;
782*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
783*3088717bSVictor Perevertkin break;
784*3088717bSVictor Perevertkin }
785*3088717bSVictor Perevertkin
786*3088717bSVictor Perevertkin default:
787*3088717bSVictor Perevertkin {
788*3088717bSVictor Perevertkin needFurtherInterpret = TRUE;
789*3088717bSVictor Perevertkin break;
790*3088717bSVictor Perevertkin }
791*3088717bSVictor Perevertkin }
792*3088717bSVictor Perevertkin
793*3088717bSVictor Perevertkin break;
794*3088717bSVictor Perevertkin } // end case SCSI_ADSENSE_LUN_COMMUNICATION
795*3088717bSVictor Perevertkin
796*3088717bSVictor Perevertkin case SCSI_ADSENSE_ILLEGAL_BLOCK:
797*3088717bSVictor Perevertkin {
798*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
799*3088717bSVictor Perevertkin
800*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
801*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Illegal block address\n"));
802*3088717bSVictor Perevertkin *Status = STATUS_NONEXISTENT_SECTOR;
803*3088717bSVictor Perevertkin *Retry = FALSE;
804*3088717bSVictor Perevertkin break;
805*3088717bSVictor Perevertkin }
806*3088717bSVictor Perevertkin
807*3088717bSVictor Perevertkin case SCSI_ADSENSE_INVALID_LUN:
808*3088717bSVictor Perevertkin {
809*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
810*3088717bSVictor Perevertkin
811*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
812*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Invalid LUN\n"));
813*3088717bSVictor Perevertkin *Status = STATUS_NO_SUCH_DEVICE;
814*3088717bSVictor Perevertkin *Retry = FALSE;
815*3088717bSVictor Perevertkin break;
816*3088717bSVictor Perevertkin }
817*3088717bSVictor Perevertkin
818*3088717bSVictor Perevertkin case SCSI_ADSENSE_COPY_PROTECTION_FAILURE:
819*3088717bSVictor Perevertkin {
820*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
821*3088717bSVictor Perevertkin
822*3088717bSVictor Perevertkin *Retry = FALSE;
823*3088717bSVictor Perevertkin
824*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
825*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Key - Copy protection failure\n"));
826*3088717bSVictor Perevertkin
827*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
828*3088717bSVictor Perevertkin {
829*3088717bSVictor Perevertkin case SCSI_SENSEQ_AUTHENTICATION_FAILURE:
830*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
831*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Authentication failure\n"));
832*3088717bSVictor Perevertkin *Status = STATUS_CSS_AUTHENTICATION_FAILURE;
833*3088717bSVictor Perevertkin break;
834*3088717bSVictor Perevertkin case SCSI_SENSEQ_KEY_NOT_PRESENT:
835*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
836*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Key not present\n"));
837*3088717bSVictor Perevertkin *Status = STATUS_CSS_KEY_NOT_PRESENT;
838*3088717bSVictor Perevertkin break;
839*3088717bSVictor Perevertkin case SCSI_SENSEQ_KEY_NOT_ESTABLISHED:
840*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
841*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Key not established\n"));
842*3088717bSVictor Perevertkin *Status = STATUS_CSS_KEY_NOT_ESTABLISHED;
843*3088717bSVictor Perevertkin break;
844*3088717bSVictor Perevertkin case SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION:
845*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
846*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Read of scrambled sector w/o authentication\n"));
847*3088717bSVictor Perevertkin *Status = STATUS_CSS_SCRAMBLED_SECTOR;
848*3088717bSVictor Perevertkin break;
849*3088717bSVictor Perevertkin case SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT:
850*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
851*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Media region does not logical unit region\n"));
852*3088717bSVictor Perevertkin *Status = STATUS_CSS_REGION_MISMATCH;
853*3088717bSVictor Perevertkin break;
854*3088717bSVictor Perevertkin case SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR:
855*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
856*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Region set error -- region may be permanent\n"));
857*3088717bSVictor Perevertkin *Status = STATUS_CSS_RESETS_EXHAUSTED;
858*3088717bSVictor Perevertkin break;
859*3088717bSVictor Perevertkin
860*3088717bSVictor Perevertkin default:
861*3088717bSVictor Perevertkin *Status = STATUS_COPY_PROTECTION_FAILURE;
862*3088717bSVictor Perevertkin break;
863*3088717bSVictor Perevertkin } // end switch of ASCQ for COPY_PROTECTION_FAILURE
864*3088717bSVictor Perevertkin
865*3088717bSVictor Perevertkin break;
866*3088717bSVictor Perevertkin }
867*3088717bSVictor Perevertkin
868*3088717bSVictor Perevertkin case SCSI_ADSENSE_INVALID_CDB:
869*3088717bSVictor Perevertkin {
870*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
871*3088717bSVictor Perevertkin
872*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
873*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Key - Invalid CDB\n"));
874*3088717bSVictor Perevertkin
875*3088717bSVictor Perevertkin *Status = STATUS_INVALID_DEVICE_REQUEST;
876*3088717bSVictor Perevertkin *Retry = FALSE;
877*3088717bSVictor Perevertkin
878*3088717bSVictor Perevertkin // Note: the retry interval is not typically used.
879*3088717bSVictor Perevertkin // it is set here only because a ClassErrorHandler
880*3088717bSVictor Perevertkin // cannot set the RetryIntervalInSeconds, and the error may
881*3088717bSVictor Perevertkin // require a few commands to be sent to clear whatever
882*3088717bSVictor Perevertkin // caused this condition (i.e. disk clears the write
883*3088717bSVictor Perevertkin // cache, requiring at least two commands)
884*3088717bSVictor Perevertkin //
885*3088717bSVictor Perevertkin // hopefully, this shortcoming can be changed for blackcomb.
886*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 3;
887*3088717bSVictor Perevertkin
888*3088717bSVictor Perevertkin break;
889*3088717bSVictor Perevertkin }
890*3088717bSVictor Perevertkin
891*3088717bSVictor Perevertkin case SCSI_ADSENSE_MEDIUM_CHANGED:
892*3088717bSVictor Perevertkin {
893*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
894*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
895*3088717bSVictor Perevertkin
896*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
897*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Media changed\n"));
898*3088717bSVictor Perevertkin
899*3088717bSVictor Perevertkin DeviceSetMediaChangeStateEx(DeviceExtension, MediaPresent, NULL);
900*3088717bSVictor Perevertkin
901*3088717bSVictor Perevertkin // special process for Media Change
902*3088717bSVictor Perevertkin if (IsVolumeMounted(DeviceExtension->DeviceObject))
903*3088717bSVictor Perevertkin {
904*3088717bSVictor Perevertkin // Set bit to indicate that media may have changed and volume needs verification.
905*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
906*3088717bSVictor Perevertkin
907*3088717bSVictor Perevertkin *Status = STATUS_VERIFY_REQUIRED;
908*3088717bSVictor Perevertkin *Retry = FALSE;
909*3088717bSVictor Perevertkin }
910*3088717bSVictor Perevertkin else
911*3088717bSVictor Perevertkin {
912*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
913*3088717bSVictor Perevertkin *Retry = TRUE;
914*3088717bSVictor Perevertkin }
915*3088717bSVictor Perevertkin break;
916*3088717bSVictor Perevertkin }
917*3088717bSVictor Perevertkin
918*3088717bSVictor Perevertkin case SCSI_ADSENSE_OPERATOR_REQUEST:
919*3088717bSVictor Perevertkin {
920*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
921*3088717bSVictor Perevertkin {
922*3088717bSVictor Perevertkin case SCSI_SENSEQ_MEDIUM_REMOVAL:
923*3088717bSVictor Perevertkin {
924*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
925*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
926*3088717bSVictor Perevertkin
927*3088717bSVictor Perevertkin InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
928*3088717bSVictor Perevertkin
929*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
930*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Ejection request received!\n"));
931*3088717bSVictor Perevertkin //Send eject notification.
932*3088717bSVictor Perevertkin DeviceSendNotification(DeviceExtension,
933*3088717bSVictor Perevertkin &GUID_IO_MEDIA_EJECT_REQUEST,
934*3088717bSVictor Perevertkin 0,
935*3088717bSVictor Perevertkin NULL);
936*3088717bSVictor Perevertkin // special process for Media Change
937*3088717bSVictor Perevertkin if (IsVolumeMounted(DeviceExtension->DeviceObject))
938*3088717bSVictor Perevertkin {
939*3088717bSVictor Perevertkin // Set bit to indicate that media may have changed and volume needs verification.
940*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
941*3088717bSVictor Perevertkin
942*3088717bSVictor Perevertkin *Status = STATUS_VERIFY_REQUIRED;
943*3088717bSVictor Perevertkin *Retry = FALSE;
944*3088717bSVictor Perevertkin }
945*3088717bSVictor Perevertkin else
946*3088717bSVictor Perevertkin {
947*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
948*3088717bSVictor Perevertkin *Retry = TRUE;
949*3088717bSVictor Perevertkin }
950*3088717bSVictor Perevertkin break;
951*3088717bSVictor Perevertkin }
952*3088717bSVictor Perevertkin default:
953*3088717bSVictor Perevertkin {
954*3088717bSVictor Perevertkin needFurtherInterpret = TRUE;
955*3088717bSVictor Perevertkin break;
956*3088717bSVictor Perevertkin }
957*3088717bSVictor Perevertkin }
958*3088717bSVictor Perevertkin break;
959*3088717bSVictor Perevertkin }
960*3088717bSVictor Perevertkin
961*3088717bSVictor Perevertkin case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED:
962*3088717bSVictor Perevertkin {
963*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
964*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 5;
965*3088717bSVictor Perevertkin
966*3088717bSVictor Perevertkin InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
967*3088717bSVictor Perevertkin
968*3088717bSVictor Perevertkin // Device information has changed, we need to rescan the
969*3088717bSVictor Perevertkin // bus for changed information such as the capacity.
970*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
971*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Device information changed. Invalidate the bus\n"));
972*3088717bSVictor Perevertkin
973*3088717bSVictor Perevertkin IoInvalidateDeviceRelations(DeviceExtension->LowerPdo, BusRelations);
974*3088717bSVictor Perevertkin
975*3088717bSVictor Perevertkin // special process for Media Change
976*3088717bSVictor Perevertkin if (IsVolumeMounted(DeviceExtension->DeviceObject))
977*3088717bSVictor Perevertkin {
978*3088717bSVictor Perevertkin // Set bit to indicate that media may have changed and volume needs verification.
979*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
980*3088717bSVictor Perevertkin
981*3088717bSVictor Perevertkin *Status = STATUS_VERIFY_REQUIRED;
982*3088717bSVictor Perevertkin *Retry = FALSE;
983*3088717bSVictor Perevertkin }
984*3088717bSVictor Perevertkin else
985*3088717bSVictor Perevertkin {
986*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
987*3088717bSVictor Perevertkin *Retry = TRUE;
988*3088717bSVictor Perevertkin }
989*3088717bSVictor Perevertkin break;
990*3088717bSVictor Perevertkin } //end Case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
991*3088717bSVictor Perevertkin
992*3088717bSVictor Perevertkin
993*3088717bSVictor Perevertkin case SCSI_ADSENSE_REC_DATA_NOECC:
994*3088717bSVictor Perevertkin case SCSI_ADSENSE_REC_DATA_ECC:
995*3088717bSVictor Perevertkin {
996*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
997*3088717bSVictor Perevertkin
998*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
999*3088717bSVictor Perevertkin *Retry = FALSE;
1000*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1001*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 258;
1002*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_RECOVERED_VIA_ECC;
1003*3088717bSVictor Perevertkin
1004*3088717bSVictor Perevertkin if (senseBuffer->IncorrectLength)
1005*3088717bSVictor Perevertkin {
1006*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1007*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n"));
1008*3088717bSVictor Perevertkin *Status = STATUS_INVALID_BLOCK_LENGTH ;
1009*3088717bSVictor Perevertkin }
1010*3088717bSVictor Perevertkin break;
1011*3088717bSVictor Perevertkin }
1012*3088717bSVictor Perevertkin
1013*3088717bSVictor Perevertkin case SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED:
1014*3088717bSVictor Perevertkin {
1015*3088717bSVictor Perevertkin UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
1016*3088717bSVictor Perevertkin
1017*3088717bSVictor Perevertkin *((PULONG)wmiEventData) = sizeof(UCHAR);
1018*3088717bSVictor Perevertkin wmiEventData[sizeof(ULONG)] = AdditionalSenseCodeQual;
1019*3088717bSVictor Perevertkin
1020*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
1021*3088717bSVictor Perevertkin
1022*3088717bSVictor Perevertkin // Don't log another eventlog if we have already logged once
1023*3088717bSVictor Perevertkin // NOTE: this should have been interlocked, but the structure
1024*3088717bSVictor Perevertkin // was publicly defined to use a BOOLEAN (char). Since
1025*3088717bSVictor Perevertkin // media only reports these errors once per X minutes,
1026*3088717bSVictor Perevertkin // the potential race condition is nearly non-existant.
1027*3088717bSVictor Perevertkin // the worst case is duplicate log entries, so ignore.
1028*3088717bSVictor Perevertkin
1029*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
1030*3088717bSVictor Perevertkin *Retry = FALSE;
1031*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 258;
1032*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1033*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_WRN_FAILURE_PREDICTED;
1034*3088717bSVictor Perevertkin
1035*3088717bSVictor Perevertkin if (senseBuffer->IncorrectLength)
1036*3088717bSVictor Perevertkin {
1037*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1038*3088717bSVictor Perevertkin "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n"));
1039*3088717bSVictor Perevertkin *Status = STATUS_INVALID_BLOCK_LENGTH ;
1040*3088717bSVictor Perevertkin }
1041*3088717bSVictor Perevertkin break;
1042*3088717bSVictor Perevertkin }
1043*3088717bSVictor Perevertkin
1044*3088717bSVictor Perevertkin case 0x57:
1045*3088717bSVictor Perevertkin {
1046*3088717bSVictor Perevertkin // UNABLE_TO_RECOVER_TABLE_OF_CONTENTS
1047*3088717bSVictor Perevertkin // the Matshita CR-585 returns this for all read commands
1048*3088717bSVictor Perevertkin // on blank CD-R and CD-RW media, and we need to handle
1049*3088717bSVictor Perevertkin // this for READ_CD detection ability.
1050*3088717bSVictor Perevertkin switch (AdditionalSenseCodeQual)
1051*3088717bSVictor Perevertkin {
1052*3088717bSVictor Perevertkin case 0x00:
1053*3088717bSVictor Perevertkin {
1054*3088717bSVictor Perevertkin needFurtherInterpret = FALSE;
1055*3088717bSVictor Perevertkin
1056*3088717bSVictor Perevertkin *Status = STATUS_UNRECOGNIZED_MEDIA;
1057*3088717bSVictor Perevertkin *Retry = FALSE;
1058*3088717bSVictor Perevertkin break;
1059*3088717bSVictor Perevertkin }
1060*3088717bSVictor Perevertkin default:
1061*3088717bSVictor Perevertkin {
1062*3088717bSVictor Perevertkin needFurtherInterpret = TRUE;
1063*3088717bSVictor Perevertkin break;
1064*3088717bSVictor Perevertkin }
1065*3088717bSVictor Perevertkin }
1066*3088717bSVictor Perevertkin break;
1067*3088717bSVictor Perevertkin } //end case Matshita specific error 0x57
1068*3088717bSVictor Perevertkin
1069*3088717bSVictor Perevertkin default:
1070*3088717bSVictor Perevertkin {
1071*3088717bSVictor Perevertkin needFurtherInterpret = TRUE;
1072*3088717bSVictor Perevertkin break;
1073*3088717bSVictor Perevertkin }
1074*3088717bSVictor Perevertkin }
1075*3088717bSVictor Perevertkin
1076*3088717bSVictor Perevertkin return needFurtherInterpret;
1077*3088717bSVictor Perevertkin }
1078*3088717bSVictor Perevertkin
1079*3088717bSVictor Perevertkin VOID
1080*3088717bSVictor Perevertkin SenseInfoInterpretBySenseKey(
1081*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1082*3088717bSVictor Perevertkin _In_ PSENSE_DATA SenseData,
1083*3088717bSVictor Perevertkin _In_ UCHAR SenseKey,
1084*3088717bSVictor Perevertkin _Inout_ NTSTATUS* Status,
1085*3088717bSVictor Perevertkin _Inout_ BOOLEAN* Retry,
1086*3088717bSVictor Perevertkin _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds,
1087*3088717bSVictor Perevertkin _Inout_ PERROR_LOG_CONTEXT LogContext
1088*3088717bSVictor Perevertkin )
1089*3088717bSVictor Perevertkin {
1090*3088717bSVictor Perevertkin // set default values for retry fields.
1091*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1092*3088717bSVictor Perevertkin *Retry = TRUE;
1093*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
1094*3088717bSVictor Perevertkin
1095*3088717bSVictor Perevertkin switch (SenseKey)
1096*3088717bSVictor Perevertkin {
1097*3088717bSVictor Perevertkin case SCSI_SENSE_NOT_READY:
1098*3088717bSVictor Perevertkin {
1099*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1100*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Key - Not Ready (bad block)\n"));
1101*3088717bSVictor Perevertkin
1102*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
1103*3088717bSVictor Perevertkin *Retry = TRUE;
1104*3088717bSVictor Perevertkin
1105*3088717bSVictor Perevertkin // for unprocessed "not ready" codes, retry the command immediately.
1106*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
1107*3088717bSVictor Perevertkin break;
1108*3088717bSVictor Perevertkin }
1109*3088717bSVictor Perevertkin
1110*3088717bSVictor Perevertkin case SCSI_SENSE_DATA_PROTECT:
1111*3088717bSVictor Perevertkin {
1112*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1113*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Key - Media write protected\n"));
1114*3088717bSVictor Perevertkin *Status = STATUS_MEDIA_WRITE_PROTECTED;
1115*3088717bSVictor Perevertkin *Retry = FALSE;
1116*3088717bSVictor Perevertkin break;
1117*3088717bSVictor Perevertkin }
1118*3088717bSVictor Perevertkin
1119*3088717bSVictor Perevertkin case SCSI_SENSE_MEDIUM_ERROR:
1120*3088717bSVictor Perevertkin {
1121*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1122*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Key - Medium Error (bad block)\n"));
1123*3088717bSVictor Perevertkin
1124*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_DATA_ERROR;
1125*3088717bSVictor Perevertkin *Retry = FALSE;
1126*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1127*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 256;
1128*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
1129*3088717bSVictor Perevertkin
1130*3088717bSVictor Perevertkin break;
1131*3088717bSVictor Perevertkin } // end SCSI_SENSE_MEDIUM_ERROR
1132*3088717bSVictor Perevertkin
1133*3088717bSVictor Perevertkin case SCSI_SENSE_HARDWARE_ERROR:
1134*3088717bSVictor Perevertkin {
1135*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1136*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Key - Hardware error\n"));
1137*3088717bSVictor Perevertkin
1138*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1139*3088717bSVictor Perevertkin *Retry = TRUE;
1140*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1141*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 257;
1142*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1143*3088717bSVictor Perevertkin
1144*3088717bSVictor Perevertkin break;
1145*3088717bSVictor Perevertkin } // end SCSI_SENSE_HARDWARE_ERROR
1146*3088717bSVictor Perevertkin
1147*3088717bSVictor Perevertkin case SCSI_SENSE_ILLEGAL_REQUEST:
1148*3088717bSVictor Perevertkin {
1149*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1150*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Key - Illegal SCSI request\n"));
1151*3088717bSVictor Perevertkin *Status = STATUS_INVALID_DEVICE_REQUEST;
1152*3088717bSVictor Perevertkin *Retry = FALSE;
1153*3088717bSVictor Perevertkin
1154*3088717bSVictor Perevertkin break;
1155*3088717bSVictor Perevertkin } // end SCSI_SENSE_ILLEGAL_REQUEST
1156*3088717bSVictor Perevertkin
1157*3088717bSVictor Perevertkin case SCSI_SENSE_UNIT_ATTENTION:
1158*3088717bSVictor Perevertkin {
1159*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1160*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Key - Unit Attention\n"));
1161*3088717bSVictor Perevertkin
1162*3088717bSVictor Perevertkin // A media change may have occured so increment the change
1163*3088717bSVictor Perevertkin // count for the physical device
1164*3088717bSVictor Perevertkin InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
1165*3088717bSVictor Perevertkin
1166*3088717bSVictor Perevertkin if (IsVolumeMounted(DeviceExtension->DeviceObject))
1167*3088717bSVictor Perevertkin {
1168*3088717bSVictor Perevertkin // Set bit to indicate that media may have changed
1169*3088717bSVictor Perevertkin // and volume needs verification.
1170*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
1171*3088717bSVictor Perevertkin
1172*3088717bSVictor Perevertkin *Status = STATUS_VERIFY_REQUIRED;
1173*3088717bSVictor Perevertkin *Retry = FALSE;
1174*3088717bSVictor Perevertkin }
1175*3088717bSVictor Perevertkin else
1176*3088717bSVictor Perevertkin {
1177*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1178*3088717bSVictor Perevertkin *Retry = TRUE;
1179*3088717bSVictor Perevertkin }
1180*3088717bSVictor Perevertkin
1181*3088717bSVictor Perevertkin break;
1182*3088717bSVictor Perevertkin
1183*3088717bSVictor Perevertkin } // end SCSI_SENSE_UNIT_ATTENTION
1184*3088717bSVictor Perevertkin
1185*3088717bSVictor Perevertkin case SCSI_SENSE_ABORTED_COMMAND:
1186*3088717bSVictor Perevertkin {
1187*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1188*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Command aborted\n"));
1189*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1190*3088717bSVictor Perevertkin *Retry = TRUE;
1191*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 1;
1192*3088717bSVictor Perevertkin break;
1193*3088717bSVictor Perevertkin } // end SCSI_SENSE_ABORTED_COMMAND
1194*3088717bSVictor Perevertkin
1195*3088717bSVictor Perevertkin case SCSI_SENSE_BLANK_CHECK:
1196*3088717bSVictor Perevertkin {
1197*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1198*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Media blank check\n"));
1199*3088717bSVictor Perevertkin *Retry = FALSE;
1200*3088717bSVictor Perevertkin *Status = STATUS_NO_DATA_DETECTED;
1201*3088717bSVictor Perevertkin break;
1202*3088717bSVictor Perevertkin } // end SCSI_SENSE_BLANK_CHECK
1203*3088717bSVictor Perevertkin
1204*3088717bSVictor Perevertkin case SCSI_SENSE_RECOVERED_ERROR:
1205*3088717bSVictor Perevertkin {
1206*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1207*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Recovered error\n"));
1208*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
1209*3088717bSVictor Perevertkin *Retry = FALSE;
1210*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1211*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 258;
1212*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1213*3088717bSVictor Perevertkin
1214*3088717bSVictor Perevertkin if (SenseData->IncorrectLength)
1215*3088717bSVictor Perevertkin {
1216*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1217*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Incorrect length detected.\n"));
1218*3088717bSVictor Perevertkin *Status = STATUS_INVALID_BLOCK_LENGTH ;
1219*3088717bSVictor Perevertkin }
1220*3088717bSVictor Perevertkin
1221*3088717bSVictor Perevertkin break;
1222*3088717bSVictor Perevertkin } // end SCSI_SENSE_RECOVERED_ERROR
1223*3088717bSVictor Perevertkin
1224*3088717bSVictor Perevertkin case SCSI_SENSE_NO_SENSE:
1225*3088717bSVictor Perevertkin {
1226*3088717bSVictor Perevertkin // Check other indicators.
1227*3088717bSVictor Perevertkin if (SenseData->IncorrectLength)
1228*3088717bSVictor Perevertkin {
1229*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1230*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Incorrect length detected.\n"));
1231*3088717bSVictor Perevertkin *Status = STATUS_INVALID_BLOCK_LENGTH ;
1232*3088717bSVictor Perevertkin *Retry = FALSE;
1233*3088717bSVictor Perevertkin }
1234*3088717bSVictor Perevertkin else
1235*3088717bSVictor Perevertkin {
1236*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1237*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: No specific sense key\n"));
1238*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1239*3088717bSVictor Perevertkin *Retry = TRUE;
1240*3088717bSVictor Perevertkin }
1241*3088717bSVictor Perevertkin
1242*3088717bSVictor Perevertkin break;
1243*3088717bSVictor Perevertkin } // end SCSI_SENSE_NO_SENSE
1244*3088717bSVictor Perevertkin
1245*3088717bSVictor Perevertkin default:
1246*3088717bSVictor Perevertkin {
1247*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1248*3088717bSVictor Perevertkin "SenseInfoInterpretBySenseKey: Unrecognized sense code\n"));
1249*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1250*3088717bSVictor Perevertkin *Retry = TRUE;
1251*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
1252*3088717bSVictor Perevertkin
1253*3088717bSVictor Perevertkin break;
1254*3088717bSVictor Perevertkin }
1255*3088717bSVictor Perevertkin
1256*3088717bSVictor Perevertkin } // end switch (SenseKey)
1257*3088717bSVictor Perevertkin
1258*3088717bSVictor Perevertkin return;
1259*3088717bSVictor Perevertkin }
1260*3088717bSVictor Perevertkin
1261*3088717bSVictor Perevertkin VOID
1262*3088717bSVictor Perevertkin SenseInfoInterpretBySrbStatus(
1263*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1264*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
1265*3088717bSVictor Perevertkin _In_ ULONG RetriedCount,
1266*3088717bSVictor Perevertkin _Inout_ NTSTATUS* Status,
1267*3088717bSVictor Perevertkin _Inout_ BOOLEAN* Retry,
1268*3088717bSVictor Perevertkin _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds,
1269*3088717bSVictor Perevertkin _Inout_ PERROR_LOG_CONTEXT LogContext
1270*3088717bSVictor Perevertkin )
1271*3088717bSVictor Perevertkin {
1272*3088717bSVictor Perevertkin BOOLEAN incrementErrorCount = FALSE;
1273*3088717bSVictor Perevertkin
1274*3088717bSVictor Perevertkin // set default values for retry fields.
1275*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1276*3088717bSVictor Perevertkin *Retry = TRUE;
1277*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
1278*3088717bSVictor Perevertkin
1279*3088717bSVictor Perevertkin switch (SRB_STATUS(Srb->SrbStatus))
1280*3088717bSVictor Perevertkin {
1281*3088717bSVictor Perevertkin case SRB_STATUS_INVALID_LUN:
1282*3088717bSVictor Perevertkin case SRB_STATUS_INVALID_TARGET_ID:
1283*3088717bSVictor Perevertkin case SRB_STATUS_NO_DEVICE:
1284*3088717bSVictor Perevertkin case SRB_STATUS_NO_HBA:
1285*3088717bSVictor Perevertkin case SRB_STATUS_INVALID_PATH_ID:
1286*3088717bSVictor Perevertkin {
1287*3088717bSVictor Perevertkin *Status = STATUS_NO_SUCH_DEVICE;
1288*3088717bSVictor Perevertkin *Retry = FALSE;
1289*3088717bSVictor Perevertkin break;
1290*3088717bSVictor Perevertkin }
1291*3088717bSVictor Perevertkin
1292*3088717bSVictor Perevertkin case SRB_STATUS_COMMAND_TIMEOUT:
1293*3088717bSVictor Perevertkin case SRB_STATUS_TIMEOUT:
1294*3088717bSVictor Perevertkin {
1295*3088717bSVictor Perevertkin // Update the error count for the device.
1296*3088717bSVictor Perevertkin *Status = STATUS_IO_TIMEOUT;
1297*3088717bSVictor Perevertkin *Retry = TRUE;
1298*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 0;
1299*3088717bSVictor Perevertkin incrementErrorCount = TRUE;
1300*3088717bSVictor Perevertkin break;
1301*3088717bSVictor Perevertkin }
1302*3088717bSVictor Perevertkin
1303*3088717bSVictor Perevertkin case SRB_STATUS_ABORTED:
1304*3088717bSVictor Perevertkin {
1305*3088717bSVictor Perevertkin // Update the error count for the device.
1306*3088717bSVictor Perevertkin *Status = STATUS_IO_TIMEOUT;
1307*3088717bSVictor Perevertkin *Retry = TRUE;
1308*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 1;
1309*3088717bSVictor Perevertkin incrementErrorCount = TRUE;
1310*3088717bSVictor Perevertkin break;
1311*3088717bSVictor Perevertkin }
1312*3088717bSVictor Perevertkin
1313*3088717bSVictor Perevertkin case SRB_STATUS_SELECTION_TIMEOUT:
1314*3088717bSVictor Perevertkin {
1315*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_CONNECTED;
1316*3088717bSVictor Perevertkin *Retry = FALSE;
1317*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 2;
1318*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1319*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_NOT_READY;
1320*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 260;
1321*3088717bSVictor Perevertkin break;
1322*3088717bSVictor Perevertkin }
1323*3088717bSVictor Perevertkin
1324*3088717bSVictor Perevertkin case SRB_STATUS_DATA_OVERRUN:
1325*3088717bSVictor Perevertkin {
1326*3088717bSVictor Perevertkin *Status = STATUS_DATA_OVERRUN;
1327*3088717bSVictor Perevertkin *Retry = FALSE;
1328*3088717bSVictor Perevertkin break;
1329*3088717bSVictor Perevertkin }
1330*3088717bSVictor Perevertkin
1331*3088717bSVictor Perevertkin case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
1332*3088717bSVictor Perevertkin {
1333*3088717bSVictor Perevertkin // Update the error count for the device.
1334*3088717bSVictor Perevertkin incrementErrorCount = TRUE;
1335*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1336*3088717bSVictor Perevertkin
1337*3088717bSVictor Perevertkin // If there was phase sequence error then limit the number of retries.
1338*3088717bSVictor Perevertkin *Retry = (RetriedCount <= 1);
1339*3088717bSVictor Perevertkin
1340*3088717bSVictor Perevertkin break;
1341*3088717bSVictor Perevertkin }
1342*3088717bSVictor Perevertkin
1343*3088717bSVictor Perevertkin case SRB_STATUS_REQUEST_FLUSHED:
1344*3088717bSVictor Perevertkin {
1345*3088717bSVictor Perevertkin // If the status needs verification bit is set. Then set
1346*3088717bSVictor Perevertkin // the status to need verification and no retry; otherwise,
1347*3088717bSVictor Perevertkin // just retry the request.
1348*3088717bSVictor Perevertkin if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME))
1349*3088717bSVictor Perevertkin {
1350*3088717bSVictor Perevertkin *Status = STATUS_VERIFY_REQUIRED;
1351*3088717bSVictor Perevertkin *Retry = FALSE;
1352*3088717bSVictor Perevertkin }
1353*3088717bSVictor Perevertkin else
1354*3088717bSVictor Perevertkin {
1355*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1356*3088717bSVictor Perevertkin *Retry = TRUE;
1357*3088717bSVictor Perevertkin }
1358*3088717bSVictor Perevertkin
1359*3088717bSVictor Perevertkin break;
1360*3088717bSVictor Perevertkin }
1361*3088717bSVictor Perevertkin
1362*3088717bSVictor Perevertkin case SRB_STATUS_INVALID_REQUEST:
1363*3088717bSVictor Perevertkin {
1364*3088717bSVictor Perevertkin *Status = STATUS_INVALID_DEVICE_REQUEST;
1365*3088717bSVictor Perevertkin *Retry = FALSE;
1366*3088717bSVictor Perevertkin break;
1367*3088717bSVictor Perevertkin }
1368*3088717bSVictor Perevertkin
1369*3088717bSVictor Perevertkin case SRB_STATUS_UNEXPECTED_BUS_FREE:
1370*3088717bSVictor Perevertkin case SRB_STATUS_PARITY_ERROR:
1371*3088717bSVictor Perevertkin // Update the error count for the device and fall through to below
1372*3088717bSVictor Perevertkin incrementErrorCount = TRUE;
1373*3088717bSVictor Perevertkin
1374*3088717bSVictor Perevertkin case SRB_STATUS_BUS_RESET:
1375*3088717bSVictor Perevertkin {
1376*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1377*3088717bSVictor Perevertkin *Retry = TRUE;
1378*3088717bSVictor Perevertkin break;
1379*3088717bSVictor Perevertkin }
1380*3088717bSVictor Perevertkin
1381*3088717bSVictor Perevertkin case SRB_STATUS_ERROR:
1382*3088717bSVictor Perevertkin {
1383*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1384*3088717bSVictor Perevertkin *Retry = TRUE;
1385*3088717bSVictor Perevertkin
1386*3088717bSVictor Perevertkin if (Srb->ScsiStatus == 0)
1387*3088717bSVictor Perevertkin {
1388*3088717bSVictor Perevertkin // This is some strange return code. Update the error
1389*3088717bSVictor Perevertkin // count for the device.
1390*3088717bSVictor Perevertkin incrementErrorCount = TRUE;
1391*3088717bSVictor Perevertkin }
1392*3088717bSVictor Perevertkin
1393*3088717bSVictor Perevertkin if (Srb->ScsiStatus == SCSISTAT_BUSY)
1394*3088717bSVictor Perevertkin {
1395*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
1396*3088717bSVictor Perevertkin }
1397*3088717bSVictor Perevertkin
1398*3088717bSVictor Perevertkin break;
1399*3088717bSVictor Perevertkin }
1400*3088717bSVictor Perevertkin
1401*3088717bSVictor Perevertkin default:
1402*3088717bSVictor Perevertkin {
1403*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1404*3088717bSVictor Perevertkin *Retry = TRUE;
1405*3088717bSVictor Perevertkin LogContext->LogError = TRUE;
1406*3088717bSVictor Perevertkin LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1407*3088717bSVictor Perevertkin LogContext->UniqueErrorValue = 259;
1408*3088717bSVictor Perevertkin LogContext->ErrorUnhandled = TRUE;
1409*3088717bSVictor Perevertkin break;
1410*3088717bSVictor Perevertkin }
1411*3088717bSVictor Perevertkin
1412*3088717bSVictor Perevertkin } //end of (SRB_STATUS(Srb->SrbStatus))
1413*3088717bSVictor Perevertkin
1414*3088717bSVictor Perevertkin if (incrementErrorCount)
1415*3088717bSVictor Perevertkin {
1416*3088717bSVictor Perevertkin // if any error count occurred, delay the retry of this io by
1417*3088717bSVictor Perevertkin // at least one second, if caller supports it.
1418*3088717bSVictor Perevertkin if (*RetryIntervalInSeconds == 0)
1419*3088717bSVictor Perevertkin {
1420*3088717bSVictor Perevertkin *RetryIntervalInSeconds = 1;
1421*3088717bSVictor Perevertkin }
1422*3088717bSVictor Perevertkin
1423*3088717bSVictor Perevertkin DevicePerfIncrementErrorCount(DeviceExtension);
1424*3088717bSVictor Perevertkin }
1425*3088717bSVictor Perevertkin
1426*3088717bSVictor Perevertkin return;
1427*3088717bSVictor Perevertkin }
1428*3088717bSVictor Perevertkin
1429*3088717bSVictor Perevertkin VOID
SenseInfoLogError(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_ PSCSI_REQUEST_BLOCK Srb,_In_ UCHAR MajorFunctionCode,_In_ ULONG IoControlCode,_In_ ULONG RetriedCount,_In_ NTSTATUS * Status,_In_ BOOLEAN * Retry,_Inout_ PERROR_LOG_CONTEXT LogContext)1430*3088717bSVictor Perevertkin SenseInfoLogError(
1431*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1432*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
1433*3088717bSVictor Perevertkin _In_ UCHAR MajorFunctionCode,
1434*3088717bSVictor Perevertkin _In_ ULONG IoControlCode,
1435*3088717bSVictor Perevertkin _In_ ULONG RetriedCount,
1436*3088717bSVictor Perevertkin _In_ NTSTATUS* Status,
1437*3088717bSVictor Perevertkin _In_ BOOLEAN* Retry,
1438*3088717bSVictor Perevertkin _Inout_ PERROR_LOG_CONTEXT LogContext
1439*3088717bSVictor Perevertkin )
1440*3088717bSVictor Perevertkin {
1441*3088717bSVictor Perevertkin // Always log the error in our internal log.
1442*3088717bSVictor Perevertkin // If logError is set, also log the error in the system log.
1443*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
1444*3088717bSVictor Perevertkin ULONG totalSize = 0;
1445*3088717bSVictor Perevertkin ULONG senseBufferSize = 0;
1446*3088717bSVictor Perevertkin IO_ERROR_LOG_PACKET staticErrLogEntry = {0};
1447*3088717bSVictor Perevertkin CDROM_ERROR_LOG_DATA staticErrLogData = {0};
1448*3088717bSVictor Perevertkin
1449*3088717bSVictor Perevertkin // Calculate the total size of the error log entry.
1450*3088717bSVictor Perevertkin // add to totalSize in the order that they are used.
1451*3088717bSVictor Perevertkin // the advantage to calculating all the sizes here is
1452*3088717bSVictor Perevertkin // that we don't have to do a bunch of extraneous checks
1453*3088717bSVictor Perevertkin // later on in this code path.
1454*3088717bSVictor Perevertkin totalSize = sizeof(IO_ERROR_LOG_PACKET) // required
1455*3088717bSVictor Perevertkin + sizeof(CDROM_ERROR_LOG_DATA); // struct for ease
1456*3088717bSVictor Perevertkin
1457*3088717bSVictor Perevertkin // also save any available extra sense data, up to the maximum errlog
1458*3088717bSVictor Perevertkin // packet size . WMI should be used for real-time analysis.
1459*3088717bSVictor Perevertkin // the event log should only be used for post-mortem debugging.
1460*3088717bSVictor Perevertkin if (TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
1461*3088717bSVictor Perevertkin {
1462*3088717bSVictor Perevertkin ULONG validSenseBytes;
1463*3088717bSVictor Perevertkin BOOLEAN validSense;
1464*3088717bSVictor Perevertkin
1465*3088717bSVictor Perevertkin // make sure we can at least access the AdditionalSenseLength field
1466*3088717bSVictor Perevertkin validSense = RTL_CONTAINS_FIELD(senseBuffer,
1467*3088717bSVictor Perevertkin Srb->SenseInfoBufferLength,
1468*3088717bSVictor Perevertkin AdditionalSenseLength);
1469*3088717bSVictor Perevertkin if (validSense)
1470*3088717bSVictor Perevertkin {
1471*3088717bSVictor Perevertkin // if extra info exists, copy the maximum amount of available
1472*3088717bSVictor Perevertkin // sense data that is safe into the the errlog.
1473*3088717bSVictor Perevertkin validSenseBytes = senseBuffer->AdditionalSenseLength
1474*3088717bSVictor Perevertkin + offsetof(SENSE_DATA, AdditionalSenseLength);
1475*3088717bSVictor Perevertkin
1476*3088717bSVictor Perevertkin // this is invalid because it causes overflow!
1477*3088717bSVictor Perevertkin // whoever sent this type of request would cause
1478*3088717bSVictor Perevertkin // a system crash.
1479*3088717bSVictor Perevertkin NT_ASSERT(validSenseBytes < MAX_ADDITIONAL_SENSE_BYTES);
1480*3088717bSVictor Perevertkin
1481*3088717bSVictor Perevertkin // set to save the most sense buffer possible
1482*3088717bSVictor Perevertkin senseBufferSize = max(validSenseBytes, sizeof(SENSE_DATA));
1483*3088717bSVictor Perevertkin senseBufferSize = min(senseBufferSize, Srb->SenseInfoBufferLength);
1484*3088717bSVictor Perevertkin }
1485*3088717bSVictor Perevertkin else
1486*3088717bSVictor Perevertkin {
1487*3088717bSVictor Perevertkin // it's smaller than required to read the total number of
1488*3088717bSVictor Perevertkin // valid bytes, so just use the SenseInfoBufferLength field.
1489*3088717bSVictor Perevertkin senseBufferSize = Srb->SenseInfoBufferLength;
1490*3088717bSVictor Perevertkin }
1491*3088717bSVictor Perevertkin
1492*3088717bSVictor Perevertkin // Bump totalSize by the number of extra senseBuffer bytes
1493*3088717bSVictor Perevertkin // (beyond the default sense buffer within CDROM_ERROR_LOG_DATA).
1494*3088717bSVictor Perevertkin // Make sure to never allocate more than ERROR_LOG_MAXIMUM_SIZE.
1495*3088717bSVictor Perevertkin if (senseBufferSize > sizeof(SENSE_DATA))
1496*3088717bSVictor Perevertkin {
1497*3088717bSVictor Perevertkin totalSize += senseBufferSize-sizeof(SENSE_DATA);
1498*3088717bSVictor Perevertkin if (totalSize > ERROR_LOG_MAXIMUM_SIZE)
1499*3088717bSVictor Perevertkin {
1500*3088717bSVictor Perevertkin senseBufferSize -= totalSize-ERROR_LOG_MAXIMUM_SIZE;
1501*3088717bSVictor Perevertkin totalSize = ERROR_LOG_MAXIMUM_SIZE;
1502*3088717bSVictor Perevertkin }
1503*3088717bSVictor Perevertkin }
1504*3088717bSVictor Perevertkin }
1505*3088717bSVictor Perevertkin
1506*3088717bSVictor Perevertkin // If we've used up all of our retry attempts, set the final status to
1507*3088717bSVictor Perevertkin // reflect the appropriate result.
1508*3088717bSVictor Perevertkin //
1509*3088717bSVictor Perevertkin // ISSUE: the test below should also check RetriedCount to determine if we will actually retry,
1510*3088717bSVictor Perevertkin // but there is no easy test because we'd have to consider the original retry count
1511*3088717bSVictor Perevertkin // for the op; besides, InterpretTransferPacketError sometimes ignores the retry
1512*3088717bSVictor Perevertkin // decision returned by this function. So just ErrorRetried to be true in the majority case.
1513*3088717bSVictor Perevertkin //
1514*3088717bSVictor Perevertkin if (*Retry)
1515*3088717bSVictor Perevertkin {
1516*3088717bSVictor Perevertkin staticErrLogEntry.FinalStatus = STATUS_SUCCESS;
1517*3088717bSVictor Perevertkin staticErrLogData.ErrorRetried = TRUE;
1518*3088717bSVictor Perevertkin }
1519*3088717bSVictor Perevertkin else
1520*3088717bSVictor Perevertkin {
1521*3088717bSVictor Perevertkin staticErrLogEntry.FinalStatus = *Status;
1522*3088717bSVictor Perevertkin }
1523*3088717bSVictor Perevertkin
1524*3088717bSVictor Perevertkin // Don't log generic IO_WARNING_PAGING_FAILURE message if either the
1525*3088717bSVictor Perevertkin // I/O is retried, or it completed successfully.
1526*3088717bSVictor Perevertkin if ((LogContext->ErrorCode == IO_WARNING_PAGING_FAILURE) &&
1527*3088717bSVictor Perevertkin (*Retry || NT_SUCCESS(*Status)) )
1528*3088717bSVictor Perevertkin {
1529*3088717bSVictor Perevertkin LogContext->LogError = FALSE;
1530*3088717bSVictor Perevertkin }
1531*3088717bSVictor Perevertkin
1532*3088717bSVictor Perevertkin if (TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING))
1533*3088717bSVictor Perevertkin {
1534*3088717bSVictor Perevertkin staticErrLogData.ErrorPaging = TRUE;
1535*3088717bSVictor Perevertkin }
1536*3088717bSVictor Perevertkin
1537*3088717bSVictor Perevertkin staticErrLogData.ErrorUnhandled = LogContext->ErrorUnhandled;
1538*3088717bSVictor Perevertkin
1539*3088717bSVictor Perevertkin // Calculate the device offset if there is a geometry.
1540*3088717bSVictor Perevertkin staticErrLogEntry.DeviceOffset.QuadPart = (LONGLONG)LogContext->BadSector;
1541*3088717bSVictor Perevertkin staticErrLogEntry.DeviceOffset.QuadPart *= (LONGLONG)DeviceExtension->DiskGeometry.BytesPerSector;
1542*3088717bSVictor Perevertkin
1543*3088717bSVictor Perevertkin if (LogContext->ErrorCode == -1)
1544*3088717bSVictor Perevertkin {
1545*3088717bSVictor Perevertkin staticErrLogEntry.ErrorCode = STATUS_IO_DEVICE_ERROR;
1546*3088717bSVictor Perevertkin }
1547*3088717bSVictor Perevertkin else
1548*3088717bSVictor Perevertkin {
1549*3088717bSVictor Perevertkin staticErrLogEntry.ErrorCode = LogContext->ErrorCode;
1550*3088717bSVictor Perevertkin }
1551*3088717bSVictor Perevertkin
1552*3088717bSVictor Perevertkin // The dump data follows the IO_ERROR_LOG_PACKET
1553*3088717bSVictor Perevertkin staticErrLogEntry.DumpDataSize = (USHORT)totalSize - sizeof(IO_ERROR_LOG_PACKET);
1554*3088717bSVictor Perevertkin
1555*3088717bSVictor Perevertkin staticErrLogEntry.SequenceNumber = 0;
1556*3088717bSVictor Perevertkin staticErrLogEntry.MajorFunctionCode = MajorFunctionCode;
1557*3088717bSVictor Perevertkin staticErrLogEntry.IoControlCode = IoControlCode;
1558*3088717bSVictor Perevertkin staticErrLogEntry.RetryCount = (UCHAR)RetriedCount;
1559*3088717bSVictor Perevertkin staticErrLogEntry.UniqueErrorValue = LogContext->UniqueErrorValue;
1560*3088717bSVictor Perevertkin
1561*3088717bSVictor Perevertkin KeQueryTickCount(&staticErrLogData.TickCount);
1562*3088717bSVictor Perevertkin staticErrLogData.PortNumber = (ULONG)-1;
1563*3088717bSVictor Perevertkin
1564*3088717bSVictor Perevertkin // Save the entire contents of the SRB.
1565*3088717bSVictor Perevertkin staticErrLogData.Srb = *Srb;
1566*3088717bSVictor Perevertkin
1567*3088717bSVictor Perevertkin // For our private log, save just the default length of the SENSE_DATA.
1568*3088717bSVictor Perevertkin if (senseBufferSize != 0)
1569*3088717bSVictor Perevertkin {
1570*3088717bSVictor Perevertkin RtlCopyMemory(&staticErrLogData.SenseData, senseBuffer, min(senseBufferSize, sizeof(SENSE_DATA)));
1571*3088717bSVictor Perevertkin }
1572*3088717bSVictor Perevertkin
1573*3088717bSVictor Perevertkin // Save the error log in our context.
1574*3088717bSVictor Perevertkin // We only save the default sense buffer length.
1575*3088717bSVictor Perevertkin {
1576*3088717bSVictor Perevertkin KIRQL oldIrql;
1577*3088717bSVictor Perevertkin KeAcquireSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, &oldIrql);
1578*3088717bSVictor Perevertkin DeviceExtension->PrivateFdoData->ErrorLogs[DeviceExtension->PrivateFdoData->ErrorLogNextIndex] = staticErrLogData;
1579*3088717bSVictor Perevertkin DeviceExtension->PrivateFdoData->ErrorLogNextIndex++;
1580*3088717bSVictor Perevertkin DeviceExtension->PrivateFdoData->ErrorLogNextIndex %= NUM_ERROR_LOG_ENTRIES;
1581*3088717bSVictor Perevertkin KeReleaseSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, oldIrql);
1582*3088717bSVictor Perevertkin }
1583*3088717bSVictor Perevertkin
1584*3088717bSVictor Perevertkin // If logError is set, also save this log in the system's error log.
1585*3088717bSVictor Perevertkin // But make sure we don't log TUR failures over and over
1586*3088717bSVictor Perevertkin // (e.g. if an external drive was switched off and we're still sending TUR's to it every second).
1587*3088717bSVictor Perevertkin if (LogContext->LogError)
1588*3088717bSVictor Perevertkin {
1589*3088717bSVictor Perevertkin // We do not want to log certain system events repetitively
1590*3088717bSVictor Perevertkin switch (((PCDB)Srb->Cdb)->CDB10.OperationCode)
1591*3088717bSVictor Perevertkin {
1592*3088717bSVictor Perevertkin case SCSIOP_TEST_UNIT_READY:
1593*3088717bSVictor Perevertkin {
1594*3088717bSVictor Perevertkin if (DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO)
1595*3088717bSVictor Perevertkin {
1596*3088717bSVictor Perevertkin LogContext->LogError = FALSE;
1597*3088717bSVictor Perevertkin }
1598*3088717bSVictor Perevertkin else
1599*3088717bSVictor Perevertkin {
1600*3088717bSVictor Perevertkin DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO = TRUE;
1601*3088717bSVictor Perevertkin }
1602*3088717bSVictor Perevertkin
1603*3088717bSVictor Perevertkin break;
1604*3088717bSVictor Perevertkin }
1605*3088717bSVictor Perevertkin
1606*3088717bSVictor Perevertkin case SCSIOP_SYNCHRONIZE_CACHE:
1607*3088717bSVictor Perevertkin {
1608*3088717bSVictor Perevertkin if (DeviceExtension->PrivateFdoData->LoggedSYNCFailure)
1609*3088717bSVictor Perevertkin {
1610*3088717bSVictor Perevertkin LogContext->LogError = FALSE;
1611*3088717bSVictor Perevertkin }
1612*3088717bSVictor Perevertkin else
1613*3088717bSVictor Perevertkin {
1614*3088717bSVictor Perevertkin DeviceExtension->PrivateFdoData->LoggedSYNCFailure = TRUE;
1615*3088717bSVictor Perevertkin }
1616*3088717bSVictor Perevertkin
1617*3088717bSVictor Perevertkin break;
1618*3088717bSVictor Perevertkin }
1619*3088717bSVictor Perevertkin }
1620*3088717bSVictor Perevertkin
1621*3088717bSVictor Perevertkin // Do not log 5/21/00 LOGICAL BLOCK ADDRESS OUT OF RANGE if the disc is blank,
1622*3088717bSVictor Perevertkin // it is known to litter the Event Log with repetitive errors
1623*3088717bSVictor Perevertkin // Do not log this error for READ, as it's known that File System mount process reads different sectors from media.
1624*3088717bSVictor Perevertkin if (senseBufferSize > RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier) &&
1625*3088717bSVictor Perevertkin senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST &&
1626*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK &&
1627*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCodeQualifier == 0 &&
1628*3088717bSVictor Perevertkin IS_SCSIOP_READ(((PCDB)Srb->Cdb)->CDB10.OperationCode))
1629*3088717bSVictor Perevertkin {
1630*3088717bSVictor Perevertkin LogContext->LogError = FALSE;
1631*3088717bSVictor Perevertkin }
1632*3088717bSVictor Perevertkin }
1633*3088717bSVictor Perevertkin
1634*3088717bSVictor Perevertkin // Write the error log packet to the system error logging thread.
1635*3088717bSVictor Perevertkin if (LogContext->LogError)
1636*3088717bSVictor Perevertkin {
1637*3088717bSVictor Perevertkin PIO_ERROR_LOG_PACKET errorLogEntry;
1638*3088717bSVictor Perevertkin PCDROM_ERROR_LOG_DATA errlogData;
1639*3088717bSVictor Perevertkin
1640*3088717bSVictor Perevertkin errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DeviceExtension->DeviceObject, (UCHAR)totalSize);
1641*3088717bSVictor Perevertkin if (errorLogEntry)
1642*3088717bSVictor Perevertkin {
1643*3088717bSVictor Perevertkin errlogData = (PCDROM_ERROR_LOG_DATA)errorLogEntry->DumpData;
1644*3088717bSVictor Perevertkin
1645*3088717bSVictor Perevertkin *errorLogEntry = staticErrLogEntry;
1646*3088717bSVictor Perevertkin *errlogData = staticErrLogData;
1647*3088717bSVictor Perevertkin
1648*3088717bSVictor Perevertkin // For the system log, copy as much of the sense buffer as possible.
1649*3088717bSVictor Perevertkin if (senseBufferSize != 0)
1650*3088717bSVictor Perevertkin {
1651*3088717bSVictor Perevertkin RtlCopyMemory(&errlogData->SenseData, senseBuffer, senseBufferSize);
1652*3088717bSVictor Perevertkin }
1653*3088717bSVictor Perevertkin
1654*3088717bSVictor Perevertkin // errorLogEntry - It will be freed by the kernel.
1655*3088717bSVictor Perevertkin IoWriteErrorLogEntry(errorLogEntry);
1656*3088717bSVictor Perevertkin }
1657*3088717bSVictor Perevertkin }
1658*3088717bSVictor Perevertkin
1659*3088717bSVictor Perevertkin return;
1660*3088717bSVictor Perevertkin }
1661*3088717bSVictor Perevertkin
1662*3088717bSVictor Perevertkin VOID
1663*3088717bSVictor Perevertkin SenseInfoInterpretRefineByScsiCommand(
1664*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1665*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
1666*3088717bSVictor Perevertkin _In_ ULONG RetriedCount,
1667*3088717bSVictor Perevertkin _In_ LONGLONG Total100nsSinceFirstSend,
1668*3088717bSVictor Perevertkin _In_ BOOLEAN OverrideVerifyVolume,
1669*3088717bSVictor Perevertkin _Inout_ BOOLEAN* Retry,
1670*3088717bSVictor Perevertkin _Inout_ NTSTATUS* Status,
1671*3088717bSVictor Perevertkin _Inout_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
1672*3088717bSVictor Perevertkin LONGLONG* RetryIntervalIn100ns
1673*3088717bSVictor Perevertkin )
1674*3088717bSVictor Perevertkin /*++
1675*3088717bSVictor Perevertkin
1676*3088717bSVictor Perevertkin Routine Description:
1677*3088717bSVictor Perevertkin
1678*3088717bSVictor Perevertkin Based on SCSI command, modify the interpretion result.
1679*3088717bSVictor Perevertkin
1680*3088717bSVictor Perevertkin Arguments:
1681*3088717bSVictor Perevertkin
1682*3088717bSVictor Perevertkin DeviceExtension - device extension.
1683*3088717bSVictor Perevertkin Srb - Supplies the scsi request block which failed.
1684*3088717bSVictor Perevertkin RetriedCount - retried count.
1685*3088717bSVictor Perevertkin Total100nsUnitsSinceFirstSend - time spent after the request was sent down first time.
1686*3088717bSVictor Perevertkin OverrideVerifyVolume - should override verify volume request.
1687*3088717bSVictor Perevertkin
1688*3088717bSVictor Perevertkin Return Value:
1689*3088717bSVictor Perevertkin
1690*3088717bSVictor Perevertkin Retry - the reques should be retried or not.
1691*3088717bSVictor Perevertkin Status - Returns the status for the request.
1692*3088717bSVictor Perevertkin RetryInterval - waiting time (in 100ns) before the request should be retried.
1693*3088717bSVictor Perevertkin Zero indicates the request should be immediately retried.
1694*3088717bSVictor Perevertkin
1695*3088717bSVictor Perevertkin --*/
1696*3088717bSVictor Perevertkin {
1697*3088717bSVictor Perevertkin UCHAR const opCode = Srb->Cdb[0];
1698*3088717bSVictor Perevertkin CDB const* cdb = (CDB const*)(Srb->Cdb);
1699*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
1700*3088717bSVictor Perevertkin
1701*3088717bSVictor Perevertkin if (opCode == SCSIOP_MEDIUM_REMOVAL)
1702*3088717bSVictor Perevertkin {
1703*3088717bSVictor Perevertkin if (( cdb->AsByte[1] == 0) &&
1704*3088717bSVictor Perevertkin ( cdb->AsByte[2] == 0) &&
1705*3088717bSVictor Perevertkin ( cdb->AsByte[3] == 0) &&
1706*3088717bSVictor Perevertkin ((cdb->AsByte[4] & 0xFC) == 0)
1707*3088717bSVictor Perevertkin )
1708*3088717bSVictor Perevertkin {
1709*3088717bSVictor Perevertkin // byte[4] == 0x3 or byte[4] == 0x1 == UNLOCK OF MEDIA
1710*3088717bSVictor Perevertkin if ((cdb->AsByte[4] & 0x01) == 0)
1711*3088717bSVictor Perevertkin {
1712*3088717bSVictor Perevertkin if (RetriedCount < TOTAL_COUNT_RETRY_DEFAULT)
1713*3088717bSVictor Perevertkin {
1714*3088717bSVictor Perevertkin // keep retrying unlock operation for several times
1715*3088717bSVictor Perevertkin *Retry = TRUE;
1716*3088717bSVictor Perevertkin }
1717*3088717bSVictor Perevertkin }
1718*3088717bSVictor Perevertkin else // LOCK REQUEST
1719*3088717bSVictor Perevertkin {
1720*3088717bSVictor Perevertkin // do not retry LOCK requests more than once (per CLASSPNP code)
1721*3088717bSVictor Perevertkin if (RetriedCount > TOTAL_COUNT_RETRY_LOCK_MEDIA)
1722*3088717bSVictor Perevertkin {
1723*3088717bSVictor Perevertkin *Retry = FALSE;
1724*3088717bSVictor Perevertkin }
1725*3088717bSVictor Perevertkin }
1726*3088717bSVictor Perevertkin }
1727*3088717bSVictor Perevertkin
1728*3088717bSVictor Perevertkin // want a minimum time to retry of 2 seconds
1729*3088717bSVictor Perevertkin if ((*Status == STATUS_DEVICE_NOT_READY) &&
1730*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY))
1731*3088717bSVictor Perevertkin {
1732*3088717bSVictor Perevertkin *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1733*3088717bSVictor Perevertkin }
1734*3088717bSVictor Perevertkin else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)
1735*3088717bSVictor Perevertkin {
1736*3088717bSVictor Perevertkin *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1737*3088717bSVictor Perevertkin }
1738*3088717bSVictor Perevertkin }
1739*3088717bSVictor Perevertkin else if ((opCode == SCSIOP_MODE_SENSE) || (opCode == SCSIOP_MODE_SENSE10))
1740*3088717bSVictor Perevertkin {
1741*3088717bSVictor Perevertkin // want a minimum time to retry of 2 seconds
1742*3088717bSVictor Perevertkin if ((*Status == STATUS_DEVICE_NOT_READY) &&
1743*3088717bSVictor Perevertkin (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY))
1744*3088717bSVictor Perevertkin {
1745*3088717bSVictor Perevertkin *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1746*3088717bSVictor Perevertkin }
1747*3088717bSVictor Perevertkin else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)
1748*3088717bSVictor Perevertkin {
1749*3088717bSVictor Perevertkin *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1750*3088717bSVictor Perevertkin }
1751*3088717bSVictor Perevertkin
1752*3088717bSVictor Perevertkin // Want to ignore a STATUS_VERIFY_REQUIRED error because it either
1753*3088717bSVictor Perevertkin // doesn't make sense or is required to satisfy the VERIFY.
1754*3088717bSVictor Perevertkin if (*Status == STATUS_VERIFY_REQUIRED)
1755*3088717bSVictor Perevertkin {
1756*3088717bSVictor Perevertkin *Retry = TRUE;
1757*3088717bSVictor Perevertkin }
1758*3088717bSVictor Perevertkin else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)
1759*3088717bSVictor Perevertkin {
1760*3088717bSVictor Perevertkin /*
1761*3088717bSVictor Perevertkin * This is a HACK.
1762*3088717bSVictor Perevertkin * Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
1763*3088717bSVictor Perevertkin * underrun (i.e. success, and the buffer is longer than needed).
1764*3088717bSVictor Perevertkin * So treat this as a success.
1765*3088717bSVictor Perevertkin * When the caller of this function sees that the status was changed to success,
1766*3088717bSVictor Perevertkin * it will add the transferred length to the original irp.
1767*3088717bSVictor Perevertkin */
1768*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
1769*3088717bSVictor Perevertkin *Retry = FALSE;
1770*3088717bSVictor Perevertkin }
1771*3088717bSVictor Perevertkin
1772*3088717bSVictor Perevertkin // limit the count of retries
1773*3088717bSVictor Perevertkin if (RetriedCount > TOTAL_COUNT_RETRY_MODESENSE)
1774*3088717bSVictor Perevertkin {
1775*3088717bSVictor Perevertkin *Retry = FALSE;
1776*3088717bSVictor Perevertkin }
1777*3088717bSVictor Perevertkin }
1778*3088717bSVictor Perevertkin else if ((opCode == SCSIOP_READ_CAPACITY) || (opCode == SCSIOP_READ_CAPACITY16))
1779*3088717bSVictor Perevertkin {
1780*3088717bSVictor Perevertkin // Want to ignore a STATUS_VERIFY_REQUIRED error because it either
1781*3088717bSVictor Perevertkin // doesn't make sense or is required to satisfy the VERIFY.
1782*3088717bSVictor Perevertkin if (*Status == STATUS_VERIFY_REQUIRED)
1783*3088717bSVictor Perevertkin {
1784*3088717bSVictor Perevertkin *Retry = TRUE;
1785*3088717bSVictor Perevertkin }
1786*3088717bSVictor Perevertkin
1787*3088717bSVictor Perevertkin if (RetriedCount > TOTAL_COUNT_RETRY_READ_CAPACITY)
1788*3088717bSVictor Perevertkin {
1789*3088717bSVictor Perevertkin *Retry = FALSE;
1790*3088717bSVictor Perevertkin }
1791*3088717bSVictor Perevertkin }
1792*3088717bSVictor Perevertkin else if ((opCode == SCSIOP_RESERVE_UNIT) || (opCode == SCSIOP_RELEASE_UNIT))
1793*3088717bSVictor Perevertkin {
1794*3088717bSVictor Perevertkin // The RESERVE(6) / RELEASE(6) commands are optional.
1795*3088717bSVictor Perevertkin // So if they aren't supported, try the 10-byte equivalents
1796*3088717bSVictor Perevertkin if (*Status == STATUS_INVALID_DEVICE_REQUEST)
1797*3088717bSVictor Perevertkin {
1798*3088717bSVictor Perevertkin PCDB tempCdb = (PCDB)Srb->Cdb;
1799*3088717bSVictor Perevertkin
1800*3088717bSVictor Perevertkin Srb->CdbLength = 10;
1801*3088717bSVictor Perevertkin tempCdb->CDB10.OperationCode = (tempCdb->CDB6GENERIC.OperationCode == SCSIOP_RESERVE_UNIT)
1802*3088717bSVictor Perevertkin ? SCSIOP_RESERVE_UNIT10
1803*3088717bSVictor Perevertkin : SCSIOP_RELEASE_UNIT10;
1804*3088717bSVictor Perevertkin
1805*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6);
1806*3088717bSVictor Perevertkin *Retry = TRUE;
1807*3088717bSVictor Perevertkin }
1808*3088717bSVictor Perevertkin }
1809*3088717bSVictor Perevertkin else if (IS_SCSIOP_READWRITE(opCode))
1810*3088717bSVictor Perevertkin {
1811*3088717bSVictor Perevertkin // Retry if still verifying a (possibly) reloaded disk/cdrom.
1812*3088717bSVictor Perevertkin if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED))
1813*3088717bSVictor Perevertkin {
1814*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
1815*3088717bSVictor Perevertkin *Retry = TRUE;
1816*3088717bSVictor Perevertkin }
1817*3088717bSVictor Perevertkin
1818*3088717bSVictor Perevertkin // Special case for streaming READ/WRITE commands
1819*3088717bSVictor Perevertkin if (((opCode == SCSIOP_READ12) && (cdb->READ12.Streaming == 1)) ||
1820*3088717bSVictor Perevertkin ((opCode == SCSIOP_WRITE12) && (cdb->WRITE12.Streaming == 1)))
1821*3088717bSVictor Perevertkin {
1822*3088717bSVictor Perevertkin // We've got a failure while performing a streaming operation and now need to guess if
1823*3088717bSVictor Perevertkin // it's likely to be a permanent error because the drive does not support streaming at all
1824*3088717bSVictor Perevertkin // (in which case we're going to fall back to normal reads/writes), or a transient error
1825*3088717bSVictor Perevertkin // (in which case we quickly fail the request but contrinue to use streaming).
1826*3088717bSVictor Perevertkin //
1827*3088717bSVictor Perevertkin // We analyze the sense information to make that decision. Bus resets and device timeouts
1828*3088717bSVictor Perevertkin // are treated as permanent errors, because some non-compliant devices may even hang when
1829*3088717bSVictor Perevertkin // they get a command that they do not expect.
1830*3088717bSVictor Perevertkin
1831*3088717bSVictor Perevertkin BOOLEAN disableStreaming = FALSE;
1832*3088717bSVictor Perevertkin
1833*3088717bSVictor Perevertkin if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_TIMEOUT ||
1834*3088717bSVictor Perevertkin SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_COMMAND_TIMEOUT ||
1835*3088717bSVictor Perevertkin SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT ||
1836*3088717bSVictor Perevertkin SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_BUS_RESET)
1837*3088717bSVictor Perevertkin {
1838*3088717bSVictor Perevertkin disableStreaming = TRUE;
1839*3088717bSVictor Perevertkin }
1840*3088717bSVictor Perevertkin else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_UNIT_ATTENTION)
1841*3088717bSVictor Perevertkin {
1842*3088717bSVictor Perevertkin if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET ||
1843*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_INSUFFICIENT_TIME_FOR_OPERATION)
1844*3088717bSVictor Perevertkin {
1845*3088717bSVictor Perevertkin disableStreaming = TRUE;
1846*3088717bSVictor Perevertkin }
1847*3088717bSVictor Perevertkin }
1848*3088717bSVictor Perevertkin else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_ILLEGAL_REQUEST)
1849*3088717bSVictor Perevertkin {
1850*3088717bSVictor Perevertkin // LBA Out of Range is an exception, as it's more likely to be caused by
1851*3088717bSVictor Perevertkin // upper layers attempting to read/write a wrong LBA.
1852*3088717bSVictor Perevertkin if (senseBuffer->AdditionalSenseCode != SCSI_ADSENSE_ILLEGAL_BLOCK)
1853*3088717bSVictor Perevertkin {
1854*3088717bSVictor Perevertkin disableStreaming = TRUE;
1855*3088717bSVictor Perevertkin }
1856*3088717bSVictor Perevertkin }
1857*3088717bSVictor Perevertkin
1858*3088717bSVictor Perevertkin if (disableStreaming)
1859*3088717bSVictor Perevertkin {
1860*3088717bSVictor Perevertkin // if the failure looks permanent, we disable streaming for all future reads/writes
1861*3088717bSVictor Perevertkin // and retry the command immediately
1862*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_STREAMING);
1863*3088717bSVictor Perevertkin *Retry = TRUE;
1864*3088717bSVictor Perevertkin *RetryIntervalIn100ns = 0;
1865*3088717bSVictor Perevertkin }
1866*3088717bSVictor Perevertkin else
1867*3088717bSVictor Perevertkin {
1868*3088717bSVictor Perevertkin // if the failure looks transient, we simply fail the current request without retries
1869*3088717bSVictor Perevertkin // to minimize the time of processing
1870*3088717bSVictor Perevertkin *Retry = FALSE;
1871*3088717bSVictor Perevertkin }
1872*3088717bSVictor Perevertkin }
1873*3088717bSVictor Perevertkin
1874*3088717bSVictor Perevertkin // Special-case handling of READ/WRITE commands. These commands now have a 120 second timeout,
1875*3088717bSVictor Perevertkin // but the preferred behavior (and that taken by many drives) is to immediately report 2/4/x
1876*3088717bSVictor Perevertkin // on OPC and similar commands. Thus, retries must occur for at least 160 seconds
1877*3088717bSVictor Perevertkin // (120 seconds + four 10 second retries) as a conservative guess.
1878*3088717bSVictor Perevertkin // Note: 160s retry time is also a result of discussion with OEMs for case of 2/4/7 and 2/4/8.
1879*3088717bSVictor Perevertkin if (*Retry)
1880*3088717bSVictor Perevertkin {
1881*3088717bSVictor Perevertkin if ((Total100nsSinceFirstSend < 0) ||
1882*3088717bSVictor Perevertkin (((senseBuffer->SenseKey &0xf) == SCSI_SENSE_HARDWARE_ERROR) && (senseBuffer->AdditionalSenseCode == 0x09)))
1883*3088717bSVictor Perevertkin {
1884*3088717bSVictor Perevertkin // time information is not valid. use default retry count.
1885*3088717bSVictor Perevertkin // or if it's SERVO FAILURE, use retry count instead of 160s retry.
1886*3088717bSVictor Perevertkin *Retry = (RetriedCount <= TOTAL_COUNT_RETRY_DEFAULT);
1887*3088717bSVictor Perevertkin }
1888*3088717bSVictor Perevertkin else if (Total100nsSinceFirstSend > SECONDS_TO_100NS_UNITS(TOTAL_SECONDS_RETRY_TIME_WRITE))
1889*3088717bSVictor Perevertkin {
1890*3088717bSVictor Perevertkin *Retry = FALSE;
1891*3088717bSVictor Perevertkin }
1892*3088717bSVictor Perevertkin
1893*3088717bSVictor Perevertkin // How long should we request a delay for during writing? This depends entirely on
1894*3088717bSVictor Perevertkin // the current write speed of the drive. If we request retries too quickly,
1895*3088717bSVictor Perevertkin // we can overload the processor on the drive (resulting in garbage being written),
1896*3088717bSVictor Perevertkin // but too slowly results in lesser performance.
1897*3088717bSVictor Perevertkin //
1898*3088717bSVictor Perevertkin *RetryIntervalIn100ns = DeviceExtension->DeviceAdditionalData.ReadWriteRetryDelay100nsUnits;
1899*3088717bSVictor Perevertkin
1900*3088717bSVictor Perevertkin } // end retry for 160 seconds modification
1901*3088717bSVictor Perevertkin }
1902*3088717bSVictor Perevertkin else if (opCode == SCSIOP_GET_PERFORMANCE)
1903*3088717bSVictor Perevertkin {
1904*3088717bSVictor Perevertkin if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)
1905*3088717bSVictor Perevertkin {
1906*3088717bSVictor Perevertkin // This is a HACK.
1907*3088717bSVictor Perevertkin // Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
1908*3088717bSVictor Perevertkin // underrun (i.e. success, and the buffer is longer than needed).
1909*3088717bSVictor Perevertkin // So treat this as a success.
1910*3088717bSVictor Perevertkin // When the caller of this function sees that the status was changed to success,
1911*3088717bSVictor Perevertkin // it will add the transferred length to the original irp.
1912*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
1913*3088717bSVictor Perevertkin *Retry = FALSE;
1914*3088717bSVictor Perevertkin }
1915*3088717bSVictor Perevertkin
1916*3088717bSVictor Perevertkin if ((Srb->SenseInfoBufferLength < RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA,AdditionalSenseCodeQualifier)) ||
1917*3088717bSVictor Perevertkin !TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
1918*3088717bSVictor Perevertkin {
1919*3088717bSVictor Perevertkin // If get configuration command is failing and if the request type is TYPE ONE
1920*3088717bSVictor Perevertkin // then most likely the device does not support this request type. Set the
1921*3088717bSVictor Perevertkin // flag so that the TYPE ONE requests will be tried as TYPE ALL requets.
1922*3088717bSVictor Perevertkin if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
1923*3088717bSVictor Perevertkin (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_DATA_OVERRUN) &&
1924*3088717bSVictor Perevertkin (((PCDB)Srb->Cdb)->GET_CONFIGURATION.RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE))
1925*3088717bSVictor Perevertkin {
1926*3088717bSVictor Perevertkin
1927*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1928*3088717bSVictor Perevertkin "TYPE ONE GetConfiguration failed. Set hack flag and retry.\n"));
1929*3088717bSVictor Perevertkin SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG);
1930*3088717bSVictor Perevertkin *Retry = TRUE;
1931*3088717bSVictor Perevertkin }
1932*3088717bSVictor Perevertkin }
1933*3088717bSVictor Perevertkin
1934*3088717bSVictor Perevertkin // limit retries to GET_PERFORMANCE commands to default retry count
1935*3088717bSVictor Perevertkin if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT)
1936*3088717bSVictor Perevertkin {
1937*3088717bSVictor Perevertkin *Retry = FALSE;
1938*3088717bSVictor Perevertkin }
1939*3088717bSVictor Perevertkin }
1940*3088717bSVictor Perevertkin else // default handler -- checks for retry count only.
1941*3088717bSVictor Perevertkin {
1942*3088717bSVictor Perevertkin if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT)
1943*3088717bSVictor Perevertkin {
1944*3088717bSVictor Perevertkin *Retry = FALSE;
1945*3088717bSVictor Perevertkin }
1946*3088717bSVictor Perevertkin }
1947*3088717bSVictor Perevertkin
1948*3088717bSVictor Perevertkin return;
1949*3088717bSVictor Perevertkin }
1950*3088717bSVictor Perevertkin
1951*3088717bSVictor Perevertkin
1952*3088717bSVictor Perevertkin VOID
SenseInfoInterpretRefineByIoControl(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_ ULONG IoControlCode,_In_ BOOLEAN OverrideVerifyVolume,_Inout_ BOOLEAN * Retry,_Inout_ NTSTATUS * Status)1953*3088717bSVictor Perevertkin SenseInfoInterpretRefineByIoControl(
1954*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1955*3088717bSVictor Perevertkin _In_ ULONG IoControlCode,
1956*3088717bSVictor Perevertkin _In_ BOOLEAN OverrideVerifyVolume,
1957*3088717bSVictor Perevertkin _Inout_ BOOLEAN* Retry,
1958*3088717bSVictor Perevertkin _Inout_ NTSTATUS* Status
1959*3088717bSVictor Perevertkin )
1960*3088717bSVictor Perevertkin /*++
1961*3088717bSVictor Perevertkin
1962*3088717bSVictor Perevertkin Routine Description:
1963*3088717bSVictor Perevertkin
1964*3088717bSVictor Perevertkin Based on IOCTL code, modify the interpretion result.
1965*3088717bSVictor Perevertkin
1966*3088717bSVictor Perevertkin Arguments:
1967*3088717bSVictor Perevertkin
1968*3088717bSVictor Perevertkin Device - Supplies the device object associated with this request.
1969*3088717bSVictor Perevertkin OriginalRequest - the irp that error occurs on.
1970*3088717bSVictor Perevertkin Srb - Supplies the scsi request block which failed.
1971*3088717bSVictor Perevertkin MajorFunctionCode - Supplies the function code to be used for logging.
1972*3088717bSVictor Perevertkin IoDeviceCode - Supplies the device code to be used for logging.
1973*3088717bSVictor Perevertkin PreviousRetryCount - retried count.
1974*3088717bSVictor Perevertkin RequestHistory_DoNotUse - the history list
1975*3088717bSVictor Perevertkin
1976*3088717bSVictor Perevertkin Return Value:
1977*3088717bSVictor Perevertkin
1978*3088717bSVictor Perevertkin BOOLEAN TRUE: Drivers should retry this request.
1979*3088717bSVictor Perevertkin FALSE: Drivers should not retry this request.
1980*3088717bSVictor Perevertkin Status - Returns the status for the request.
1981*3088717bSVictor Perevertkin RetryInterval - Number of seconds before the request should be retried.
1982*3088717bSVictor Perevertkin Zero indicates the request should be immediately retried.
1983*3088717bSVictor Perevertkin
1984*3088717bSVictor Perevertkin --*/
1985*3088717bSVictor Perevertkin {
1986*3088717bSVictor Perevertkin PAGED_CODE();
1987*3088717bSVictor Perevertkin
1988*3088717bSVictor Perevertkin if ((IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) ||
1989*3088717bSVictor Perevertkin (IoControlCode == IOCTL_CDROM_READ_TOC) ||
1990*3088717bSVictor Perevertkin (IoControlCode == IOCTL_CDROM_READ_TOC_EX) ||
1991*3088717bSVictor Perevertkin (IoControlCode == IOCTL_CDROM_GET_CONFIGURATION)||
1992*3088717bSVictor Perevertkin (IoControlCode == IOCTL_CDROM_GET_VOLUME))
1993*3088717bSVictor Perevertkin {
1994*3088717bSVictor Perevertkin if (*Status == STATUS_DATA_OVERRUN)
1995*3088717bSVictor Perevertkin {
1996*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
1997*3088717bSVictor Perevertkin *Retry = FALSE;
1998*3088717bSVictor Perevertkin }
1999*3088717bSVictor Perevertkin }
2000*3088717bSVictor Perevertkin
2001*3088717bSVictor Perevertkin if (IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL)
2002*3088717bSVictor Perevertkin {
2003*3088717bSVictor Perevertkin PLAY_ACTIVE(DeviceExtension) = FALSE;
2004*3088717bSVictor Perevertkin }
2005*3088717bSVictor Perevertkin
2006*3088717bSVictor Perevertkin // If the status is verified required and the this request
2007*3088717bSVictor Perevertkin // should bypass verify required then retry the request.
2008*3088717bSVictor Perevertkin if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED))
2009*3088717bSVictor Perevertkin {
2010*3088717bSVictor Perevertkin // note: status gets overwritten here
2011*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
2012*3088717bSVictor Perevertkin *Retry = TRUE;
2013*3088717bSVictor Perevertkin
2014*3088717bSVictor Perevertkin if ((IoControlCode == IOCTL_CDROM_CHECK_VERIFY) ||
2015*3088717bSVictor Perevertkin (IoControlCode == IOCTL_STORAGE_CHECK_VERIFY) ||
2016*3088717bSVictor Perevertkin (IoControlCode == IOCTL_STORAGE_CHECK_VERIFY2) ||
2017*3088717bSVictor Perevertkin (IoControlCode == IOCTL_DISK_CHECK_VERIFY)
2018*3088717bSVictor Perevertkin )
2019*3088717bSVictor Perevertkin {
2020*3088717bSVictor Perevertkin // Update the geometry information, as the media could have changed.
2021*3088717bSVictor Perevertkin (VOID) MediaReadCapacity(DeviceExtension->Device);
2022*3088717bSVictor Perevertkin } // end of ioctls to update capacity
2023*3088717bSVictor Perevertkin }
2024*3088717bSVictor Perevertkin
2025*3088717bSVictor Perevertkin if (!NT_SUCCESS(*Status) && (IoControlCode == IOCTL_CDROM_SET_SPEED))
2026*3088717bSVictor Perevertkin {
2027*3088717bSVictor Perevertkin // If set speed request fails then we should disable the restore speed option.
2028*3088717bSVictor Perevertkin // Otherwise we will try to restore to default speed on next media change,
2029*3088717bSVictor Perevertkin // if requested by the caller.
2030*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.RestoreDefaults = FALSE;
2031*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "Disable restore default\n"));
2032*3088717bSVictor Perevertkin }
2033*3088717bSVictor Perevertkin
2034*3088717bSVictor Perevertkin return;
2035*3088717bSVictor Perevertkin }
2036*3088717bSVictor Perevertkin
2037*3088717bSVictor Perevertkin BOOLEAN
2038*3088717bSVictor Perevertkin SenseInfoInterpret(
2039*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2040*3088717bSVictor Perevertkin _In_ WDFREQUEST Request,
2041*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
2042*3088717bSVictor Perevertkin _In_ ULONG RetriedCount,
2043*3088717bSVictor Perevertkin _Out_ NTSTATUS* Status,
2044*3088717bSVictor Perevertkin _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
2045*3088717bSVictor Perevertkin LONGLONG* RetryIntervalIn100ns
2046*3088717bSVictor Perevertkin )
2047*3088717bSVictor Perevertkin /*++
2048*3088717bSVictor Perevertkin
2049*3088717bSVictor Perevertkin SenseInfoInterpret()
2050*3088717bSVictor Perevertkin
2051*3088717bSVictor Perevertkin Routine Description:
2052*3088717bSVictor Perevertkin
2053*3088717bSVictor Perevertkin This routine interprets the data returned from the SCSI request sense.
2054*3088717bSVictor Perevertkin It determines the status to return in the IRP
2055*3088717bSVictor Perevertkin and whether this request can be retried.
2056*3088717bSVictor Perevertkin
2057*3088717bSVictor Perevertkin Arguments:
2058*3088717bSVictor Perevertkin
2059*3088717bSVictor Perevertkin Device - Supplies the device object associated with this request.
2060*3088717bSVictor Perevertkin Srb - Supplies the scsi request block which failed.
2061*3088717bSVictor Perevertkin MajorFunctionCode - Supplies the function code to be used for logging.
2062*3088717bSVictor Perevertkin IoDeviceCode - Supplies the device code to be used for logging.
2063*3088717bSVictor Perevertkin
2064*3088717bSVictor Perevertkin Return Value:
2065*3088717bSVictor Perevertkin
2066*3088717bSVictor Perevertkin BOOLEAN TRUE: Drivers should retry this request.
2067*3088717bSVictor Perevertkin FALSE: Drivers should not retry this request.
2068*3088717bSVictor Perevertkin Status - Returns the status for the request.
2069*3088717bSVictor Perevertkin RetryInterval - Number of seconds before the request should be retried.
2070*3088717bSVictor Perevertkin Zero indicates the request should be immediately retried.
2071*3088717bSVictor Perevertkin
2072*3088717bSVictor Perevertkin --*/
2073*3088717bSVictor Perevertkin {
2074*3088717bSVictor Perevertkin ULONG retryIntervalInSeconds = 0;
2075*3088717bSVictor Perevertkin BOOLEAN retry = TRUE;
2076*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
2077*3088717bSVictor Perevertkin ULONG readSector = 0;
2078*3088717bSVictor Perevertkin ERROR_LOG_CONTEXT logContext;
2079*3088717bSVictor Perevertkin
2080*3088717bSVictor Perevertkin UCHAR majorFunctionCode = 0;
2081*3088717bSVictor Perevertkin ULONG ioControlCode = 0;
2082*3088717bSVictor Perevertkin BOOLEAN overrideVerifyVolume = FALSE;
2083*3088717bSVictor Perevertkin ULONGLONG total100nsSinceFirstSend = 0;
2084*3088717bSVictor Perevertkin PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
2085*3088717bSVictor Perevertkin
2086*3088717bSVictor Perevertkin //
2087*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
2088*3088717bSVictor Perevertkin
2089*3088717bSVictor Perevertkin RtlZeroMemory(&logContext, sizeof(ERROR_LOG_CONTEXT));
2090*3088717bSVictor Perevertkin logContext.ErrorCode = -1;
2091*3088717bSVictor Perevertkin
2092*3088717bSVictor Perevertkin // Get Original Request related information
2093*3088717bSVictor Perevertkin SenseInfoRequestGetInformation(Request,
2094*3088717bSVictor Perevertkin &majorFunctionCode,
2095*3088717bSVictor Perevertkin &ioControlCode,
2096*3088717bSVictor Perevertkin &overrideVerifyVolume,
2097*3088717bSVictor Perevertkin &total100nsSinceFirstSend);
2098*3088717bSVictor Perevertkin
2099*3088717bSVictor Perevertkin if(TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING))
2100*3088717bSVictor Perevertkin {
2101*3088717bSVictor Perevertkin // Log anything remotely incorrect about paging i/o
2102*3088717bSVictor Perevertkin logContext.LogError = TRUE;
2103*3088717bSVictor Perevertkin logContext.UniqueErrorValue = 301;
2104*3088717bSVictor Perevertkin logContext.ErrorCode = IO_WARNING_PAGING_FAILURE;
2105*3088717bSVictor Perevertkin }
2106*3088717bSVictor Perevertkin
2107*3088717bSVictor Perevertkin // must handle the SRB_STATUS_INTERNAL_ERROR case first,
2108*3088717bSVictor Perevertkin // as it has all the flags set.
2109*3088717bSVictor Perevertkin if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_INTERNAL_ERROR)
2110*3088717bSVictor Perevertkin {
2111*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
2112*3088717bSVictor Perevertkin "SenseInfoInterpret: Internal Error code is %x\n",
2113*3088717bSVictor Perevertkin Srb->InternalStatus));
2114*3088717bSVictor Perevertkin
2115*3088717bSVictor Perevertkin retry = FALSE;
2116*3088717bSVictor Perevertkin *Status = Srb->InternalStatus;
2117*3088717bSVictor Perevertkin }
2118*3088717bSVictor Perevertkin else if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT)
2119*3088717bSVictor Perevertkin {
2120*3088717bSVictor Perevertkin retry = FALSE;
2121*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_BUSY;
2122*3088717bSVictor Perevertkin logContext.LogError = FALSE;
2123*3088717bSVictor Perevertkin }
2124*3088717bSVictor Perevertkin else if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
2125*3088717bSVictor Perevertkin (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)))
2126*3088717bSVictor Perevertkin {
2127*3088717bSVictor Perevertkin UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f);
2128*3088717bSVictor Perevertkin UCHAR additionalSenseCode = 0;
2129*3088717bSVictor Perevertkin UCHAR additionalSenseCodeQual = 0;
2130*3088717bSVictor Perevertkin
2131*3088717bSVictor Perevertkin // Zero the additional sense code and additional sense code qualifier
2132*3088717bSVictor Perevertkin // if they were not returned by the device.
2133*3088717bSVictor Perevertkin readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength);
2134*3088717bSVictor Perevertkin if (readSector > Srb->SenseInfoBufferLength)
2135*3088717bSVictor Perevertkin {
2136*3088717bSVictor Perevertkin readSector = Srb->SenseInfoBufferLength;
2137*3088717bSVictor Perevertkin }
2138*3088717bSVictor Perevertkin
2139*3088717bSVictor Perevertkin additionalSenseCode = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCode)) ?
2140*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode : 0;
2141*3088717bSVictor Perevertkin additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ?
2142*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCodeQualifier : 0;
2143*3088717bSVictor Perevertkin
2144*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2145*3088717bSVictor Perevertkin "SCSI Error - \n"
2146*3088717bSVictor Perevertkin "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
2147*3088717bSVictor Perevertkin "\tsrb status: %X; sense: %02X/%02X/%02X; Retried count: %d\n\n",
2148*3088717bSVictor Perevertkin Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5],
2149*3088717bSVictor Perevertkin Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11],
2150*3088717bSVictor Perevertkin Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15],
2151*3088717bSVictor Perevertkin SRB_STATUS(Srb->SrbStatus),
2152*3088717bSVictor Perevertkin senseKey,
2153*3088717bSVictor Perevertkin additionalSenseCode,
2154*3088717bSVictor Perevertkin additionalSenseCodeQual,
2155*3088717bSVictor Perevertkin RetriedCount));
2156*3088717bSVictor Perevertkin
2157*3088717bSVictor Perevertkin if (senseKey == SCSI_SENSE_UNIT_ATTENTION)
2158*3088717bSVictor Perevertkin {
2159*3088717bSVictor Perevertkin ULONG mediaChangeCount;
2160*3088717bSVictor Perevertkin
2161*3088717bSVictor Perevertkin // A media change may have occured so increment the change count for the physical device
2162*3088717bSVictor Perevertkin mediaChangeCount = InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
2163*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2164*3088717bSVictor Perevertkin "SenseInfoInterpret: Media change count for device %d incremented to %#lx\n",
2165*3088717bSVictor Perevertkin DeviceExtension->DeviceNumber, mediaChangeCount));
2166*3088717bSVictor Perevertkin }
2167*3088717bSVictor Perevertkin
2168*3088717bSVictor Perevertkin if ((zpoddInfo != NULL) &&
2169*3088717bSVictor Perevertkin (((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode == SCSIOP_TEST_UNIT_READY))
2170*3088717bSVictor Perevertkin {
2171*3088717bSVictor Perevertkin // This sense code is in response to the Test Unit Ready sent during delayed power down
2172*3088717bSVictor Perevertkin // request. Copy the sense data into the zpoddInfo structure for later processing.
2173*3088717bSVictor Perevertkin zpoddInfo->SenseKey = senseKey;
2174*3088717bSVictor Perevertkin zpoddInfo->AdditionalSenseCode = additionalSenseCode;
2175*3088717bSVictor Perevertkin zpoddInfo->AdditionalSenseCodeQualifier = additionalSenseCodeQual;
2176*3088717bSVictor Perevertkin }
2177*3088717bSVictor Perevertkin
2178*3088717bSVictor Perevertkin // Interpret error by specific ASC & ASCQ first,
2179*3088717bSVictor Perevertkin // If the error is not handled, interpret using f
2180*3088717bSVictor Perevertkin {
2181*3088717bSVictor Perevertkin BOOLEAN notHandled = FALSE;
2182*3088717bSVictor Perevertkin notHandled = SenseInfoInterpretByAdditionalSenseCode(DeviceExtension,
2183*3088717bSVictor Perevertkin Srb,
2184*3088717bSVictor Perevertkin additionalSenseCode,
2185*3088717bSVictor Perevertkin additionalSenseCodeQual,
2186*3088717bSVictor Perevertkin Status,
2187*3088717bSVictor Perevertkin &retry,
2188*3088717bSVictor Perevertkin &retryIntervalInSeconds,
2189*3088717bSVictor Perevertkin &logContext);
2190*3088717bSVictor Perevertkin
2191*3088717bSVictor Perevertkin if (notHandled)
2192*3088717bSVictor Perevertkin {
2193*3088717bSVictor Perevertkin SenseInfoInterpretBySenseKey(DeviceExtension,
2194*3088717bSVictor Perevertkin senseBuffer,
2195*3088717bSVictor Perevertkin senseKey,
2196*3088717bSVictor Perevertkin Status,
2197*3088717bSVictor Perevertkin &retry,
2198*3088717bSVictor Perevertkin &retryIntervalInSeconds,
2199*3088717bSVictor Perevertkin &logContext);
2200*3088717bSVictor Perevertkin }
2201*3088717bSVictor Perevertkin }
2202*3088717bSVictor Perevertkin
2203*3088717bSVictor Perevertkin // Try to determine the bad sector from the inquiry data.
2204*3088717bSVictor Perevertkin if ((IS_SCSIOP_READWRITE(((PCDB)Srb->Cdb)->CDB10.OperationCode)) ||
2205*3088717bSVictor Perevertkin (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY) ||
2206*3088717bSVictor Perevertkin (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY16))
2207*3088717bSVictor Perevertkin {
2208*3088717bSVictor Perevertkin ULONG index;
2209*3088717bSVictor Perevertkin readSector = 0;
2210*3088717bSVictor Perevertkin
2211*3088717bSVictor Perevertkin for (index = 0; index < 4; index++)
2212*3088717bSVictor Perevertkin {
2213*3088717bSVictor Perevertkin logContext.BadSector = (logContext.BadSector << 8) | senseBuffer->Information[index];
2214*3088717bSVictor Perevertkin }
2215*3088717bSVictor Perevertkin
2216*3088717bSVictor Perevertkin for (index = 0; index < 4; index++)
2217*3088717bSVictor Perevertkin {
2218*3088717bSVictor Perevertkin readSector = (readSector << 8) | Srb->Cdb[index+2];
2219*3088717bSVictor Perevertkin }
2220*3088717bSVictor Perevertkin
2221*3088717bSVictor Perevertkin index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) |
2222*3088717bSVictor Perevertkin ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb;
2223*3088717bSVictor Perevertkin
2224*3088717bSVictor Perevertkin // Make sure the bad sector is within the read sectors.
2225*3088717bSVictor Perevertkin if (!(logContext.BadSector >= readSector && logContext.BadSector < (readSector + index)))
2226*3088717bSVictor Perevertkin {
2227*3088717bSVictor Perevertkin logContext.BadSector = readSector;
2228*3088717bSVictor Perevertkin }
2229*3088717bSVictor Perevertkin }
2230*3088717bSVictor Perevertkin }
2231*3088717bSVictor Perevertkin else
2232*3088717bSVictor Perevertkin {
2233*3088717bSVictor Perevertkin // Request sense buffer not valid. No sense information
2234*3088717bSVictor Perevertkin // to pinpoint the error. Return general request fail.
2235*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2236*3088717bSVictor Perevertkin "SCSI Error - \n"
2237*3088717bSVictor Perevertkin "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
2238*3088717bSVictor Perevertkin "\tsrb status: %X; sense info not valid; Retried count: %d\n\n",
2239*3088717bSVictor Perevertkin Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5],
2240*3088717bSVictor Perevertkin Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11],
2241*3088717bSVictor Perevertkin Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15],
2242*3088717bSVictor Perevertkin SRB_STATUS(Srb->SrbStatus),
2243*3088717bSVictor Perevertkin RetriedCount));
2244*3088717bSVictor Perevertkin
2245*3088717bSVictor Perevertkin SenseInfoInterpretBySrbStatus(DeviceExtension,
2246*3088717bSVictor Perevertkin Srb,
2247*3088717bSVictor Perevertkin RetriedCount,
2248*3088717bSVictor Perevertkin Status,
2249*3088717bSVictor Perevertkin &retry,
2250*3088717bSVictor Perevertkin &retryIntervalInSeconds,
2251*3088717bSVictor Perevertkin &logContext);
2252*3088717bSVictor Perevertkin }
2253*3088717bSVictor Perevertkin
2254*3088717bSVictor Perevertkin // all functions using unit - seconds for retry Interval already be called.
2255*3088717bSVictor Perevertkin *RetryIntervalIn100ns = SECONDS_TO_100NS_UNITS(retryIntervalInSeconds);
2256*3088717bSVictor Perevertkin
2257*3088717bSVictor Perevertkin // call the device specific error handler if it has one.
2258*3088717bSVictor Perevertkin // DeviceErrorHandlerForMmmc() for all MMC devices
2259*3088717bSVictor Perevertkin // or DeviceErrorHandlerForHitachiGD2000() for HITACHI GD-2000, HITACHI DVD-ROM GD-2000
2260*3088717bSVictor Perevertkin if (DeviceExtension->DeviceAdditionalData.ErrorHandler)
2261*3088717bSVictor Perevertkin {
2262*3088717bSVictor Perevertkin DeviceExtension->DeviceAdditionalData.ErrorHandler(DeviceExtension, Srb, Status, &retry);
2263*3088717bSVictor Perevertkin }
2264*3088717bSVictor Perevertkin
2265*3088717bSVictor Perevertkin // Refine retry based on SCSI command
2266*3088717bSVictor Perevertkin SenseInfoInterpretRefineByScsiCommand(DeviceExtension,
2267*3088717bSVictor Perevertkin Srb,
2268*3088717bSVictor Perevertkin RetriedCount,
2269*3088717bSVictor Perevertkin total100nsSinceFirstSend,
2270*3088717bSVictor Perevertkin overrideVerifyVolume,
2271*3088717bSVictor Perevertkin &retry,
2272*3088717bSVictor Perevertkin Status,
2273*3088717bSVictor Perevertkin RetryIntervalIn100ns);
2274*3088717bSVictor Perevertkin
2275*3088717bSVictor Perevertkin // Refine retry based on IOCTL code.
2276*3088717bSVictor Perevertkin if (majorFunctionCode == IRP_MJ_DEVICE_CONTROL)
2277*3088717bSVictor Perevertkin {
2278*3088717bSVictor Perevertkin SenseInfoInterpretRefineByIoControl(DeviceExtension,
2279*3088717bSVictor Perevertkin ioControlCode,
2280*3088717bSVictor Perevertkin overrideVerifyVolume,
2281*3088717bSVictor Perevertkin &retry,
2282*3088717bSVictor Perevertkin Status);
2283*3088717bSVictor Perevertkin }
2284*3088717bSVictor Perevertkin
2285*3088717bSVictor Perevertkin // LOG the error:
2286*3088717bSVictor Perevertkin // Always log the error in our internal log.
2287*3088717bSVictor Perevertkin // If logError is set, also log the error in the system log.
2288*3088717bSVictor Perevertkin SenseInfoLogError(DeviceExtension,
2289*3088717bSVictor Perevertkin Srb,
2290*3088717bSVictor Perevertkin majorFunctionCode,
2291*3088717bSVictor Perevertkin ioControlCode,
2292*3088717bSVictor Perevertkin RetriedCount,
2293*3088717bSVictor Perevertkin Status,
2294*3088717bSVictor Perevertkin &retry,
2295*3088717bSVictor Perevertkin &logContext);
2296*3088717bSVictor Perevertkin
2297*3088717bSVictor Perevertkin // all process about the error done. check if the irp was cancelled.
2298*3088717bSVictor Perevertkin if ((!NT_SUCCESS(*Status)) && retry)
2299*3088717bSVictor Perevertkin {
2300*3088717bSVictor Perevertkin PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
2301*3088717bSVictor Perevertkin
2302*3088717bSVictor Perevertkin if ((requestContext->OriginalRequest != NULL) &&
2303*3088717bSVictor Perevertkin WdfRequestIsCanceled(requestContext->OriginalRequest)
2304*3088717bSVictor Perevertkin )
2305*3088717bSVictor Perevertkin {
2306*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2307*3088717bSVictor Perevertkin "Request %p was cancelled when it would have been retried\n",
2308*3088717bSVictor Perevertkin requestContext->OriginalRequest));
2309*3088717bSVictor Perevertkin
2310*3088717bSVictor Perevertkin *Status = STATUS_CANCELLED;
2311*3088717bSVictor Perevertkin retry = FALSE;
2312*3088717bSVictor Perevertkin *RetryIntervalIn100ns = 0;
2313*3088717bSVictor Perevertkin }
2314*3088717bSVictor Perevertkin }
2315*3088717bSVictor Perevertkin
2316*3088717bSVictor Perevertkin // now, all decisions are made. display trace information.
2317*3088717bSVictor Perevertkin if (retry)
2318*3088717bSVictor Perevertkin {
2319*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2320*3088717bSVictor Perevertkin "Command shall be retried in %2I64d.%03I64d seconds\n",
2321*3088717bSVictor Perevertkin (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND),
2322*3088717bSVictor Perevertkin (*RetryIntervalIn100ns / 10000) % 1000
2323*3088717bSVictor Perevertkin ));
2324*3088717bSVictor Perevertkin }
2325*3088717bSVictor Perevertkin else
2326*3088717bSVictor Perevertkin {
2327*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2328*3088717bSVictor Perevertkin "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n",
2329*3088717bSVictor Perevertkin senseBuffer->SenseKey,
2330*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode,
2331*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCodeQualifier
2332*3088717bSVictor Perevertkin ));
2333*3088717bSVictor Perevertkin }
2334*3088717bSVictor Perevertkin
2335*3088717bSVictor Perevertkin return retry;
2336*3088717bSVictor Perevertkin
2337*3088717bSVictor Perevertkin } // end SenseInfoInterpret()
2338*3088717bSVictor Perevertkin
2339*3088717bSVictor Perevertkin
2340*3088717bSVictor Perevertkin BOOLEAN
2341*3088717bSVictor Perevertkin SenseInfoInterpretForZPODD(
2342*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2343*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
2344*3088717bSVictor Perevertkin _Out_ NTSTATUS* Status,
2345*3088717bSVictor Perevertkin _Out_ _Out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
2346*3088717bSVictor Perevertkin LONGLONG* RetryIntervalIn100ns
2347*3088717bSVictor Perevertkin )
2348*3088717bSVictor Perevertkin /*++
2349*3088717bSVictor Perevertkin
2350*3088717bSVictor Perevertkin SenseInfoInterpretForZPODD()
2351*3088717bSVictor Perevertkin
2352*3088717bSVictor Perevertkin Routine Description:
2353*3088717bSVictor Perevertkin
2354*3088717bSVictor Perevertkin This routine interprets the data returned from the SCSI request sense.
2355*3088717bSVictor Perevertkin It determines the status to return in the IRP
2356*3088717bSVictor Perevertkin and whether this request can be retried.
2357*3088717bSVictor Perevertkin
2358*3088717bSVictor Perevertkin Arguments:
2359*3088717bSVictor Perevertkin
2360*3088717bSVictor Perevertkin Device - Supplies the device object associated with this request.
2361*3088717bSVictor Perevertkin Srb - Supplies the scsi request block which failed.
2362*3088717bSVictor Perevertkin
2363*3088717bSVictor Perevertkin Return Value:
2364*3088717bSVictor Perevertkin
2365*3088717bSVictor Perevertkin BOOLEAN TRUE: Drivers should retry this request.
2366*3088717bSVictor Perevertkin FALSE: Drivers should not retry this request.
2367*3088717bSVictor Perevertkin Status - Returns the status for the request.
2368*3088717bSVictor Perevertkin RetryInterval - Number of seconds before the request should be retried.
2369*3088717bSVictor Perevertkin Zero indicates the request should be immediately retried.
2370*3088717bSVictor Perevertkin
2371*3088717bSVictor Perevertkin --*/
2372*3088717bSVictor Perevertkin {
2373*3088717bSVictor Perevertkin BOOLEAN retry = FALSE;
2374*3088717bSVictor Perevertkin PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
2375*3088717bSVictor Perevertkin ULONG readSector = 0;
2376*3088717bSVictor Perevertkin PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
2377*3088717bSVictor Perevertkin
2378*3088717bSVictor Perevertkin *Status = STATUS_IO_DEVICE_ERROR;
2379*3088717bSVictor Perevertkin *RetryIntervalIn100ns = 0;
2380*3088717bSVictor Perevertkin
2381*3088717bSVictor Perevertkin if (zpoddInfo->RetryFirstCommand != FALSE)
2382*3088717bSVictor Perevertkin {
2383*3088717bSVictor Perevertkin // The first command to the logical unit after power resumed will be terminated
2384*3088717bSVictor Perevertkin // with CHECK CONDITION Status, 6/29/00 POWER ON, RESET, OR BUS DEVICE RESET OCCURRED
2385*3088717bSVictor Perevertkin
2386*3088717bSVictor Perevertkin // We have observed some devices return a different sense code, and thus as long as
2387*3088717bSVictor Perevertkin // the first command after power resume fails, we just retry one more time.
2388*3088717bSVictor Perevertkin zpoddInfo->RetryFirstCommand = FALSE;
2389*3088717bSVictor Perevertkin
2390*3088717bSVictor Perevertkin retry = TRUE;
2391*3088717bSVictor Perevertkin }
2392*3088717bSVictor Perevertkin else if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
2393*3088717bSVictor Perevertkin (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)))
2394*3088717bSVictor Perevertkin {
2395*3088717bSVictor Perevertkin UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f);
2396*3088717bSVictor Perevertkin UCHAR additionalSenseCode = 0;
2397*3088717bSVictor Perevertkin UCHAR additionalSenseCodeQual = 0;
2398*3088717bSVictor Perevertkin
2399*3088717bSVictor Perevertkin // Zero the additional sense code and additional sense code qualifier
2400*3088717bSVictor Perevertkin // if they were not returned by the device.
2401*3088717bSVictor Perevertkin readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength);
2402*3088717bSVictor Perevertkin if (readSector > Srb->SenseInfoBufferLength)
2403*3088717bSVictor Perevertkin {
2404*3088717bSVictor Perevertkin readSector = Srb->SenseInfoBufferLength;
2405*3088717bSVictor Perevertkin }
2406*3088717bSVictor Perevertkin
2407*3088717bSVictor Perevertkin additionalSenseCode = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCode)) ?
2408*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode : 0;
2409*3088717bSVictor Perevertkin additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ?
2410*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCodeQualifier : 0;
2411*3088717bSVictor Perevertkin
2412*3088717bSVictor Perevertkin // If sense code is 2/4/1, device is becoming ready from ZPODD mode. According to Mt Fuji, device
2413*3088717bSVictor Perevertkin // could take up to 800msec to be fully operational.
2414*3088717bSVictor Perevertkin if ((senseKey == SCSI_SENSE_NOT_READY) &&
2415*3088717bSVictor Perevertkin (additionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) &&
2416*3088717bSVictor Perevertkin (additionalSenseCodeQual == SCSI_SENSEQ_BECOMING_READY))
2417*3088717bSVictor Perevertkin {
2418*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2419*3088717bSVictor Perevertkin "SenseInfoInterpretForZPODD: In process of becoming ready\n"));
2420*3088717bSVictor Perevertkin
2421*3088717bSVictor Perevertkin zpoddInfo->BecomingReadyRetryCount--;
2422*3088717bSVictor Perevertkin
2423*3088717bSVictor Perevertkin if (zpoddInfo->BecomingReadyRetryCount > 0)
2424*3088717bSVictor Perevertkin {
2425*3088717bSVictor Perevertkin DEVICE_EVENT_BECOMING_READY notReady = {0};
2426*3088717bSVictor Perevertkin
2427*3088717bSVictor Perevertkin retry = TRUE;
2428*3088717bSVictor Perevertkin *Status = STATUS_DEVICE_NOT_READY;
2429*3088717bSVictor Perevertkin *RetryIntervalIn100ns = BECOMING_READY_RETRY_INTERNVAL_IN_100NS;
2430*3088717bSVictor Perevertkin
2431*3088717bSVictor Perevertkin notReady.Version = 1;
2432*3088717bSVictor Perevertkin notReady.Reason = 1;
2433*3088717bSVictor Perevertkin notReady.Estimated100msToReady = (ULONG) *RetryIntervalIn100ns / (1000 * 1000);
2434*3088717bSVictor Perevertkin DeviceSendNotification(DeviceExtension,
2435*3088717bSVictor Perevertkin &GUID_IO_DEVICE_BECOMING_READY,
2436*3088717bSVictor Perevertkin sizeof(DEVICE_EVENT_BECOMING_READY),
2437*3088717bSVictor Perevertkin ¬Ready);
2438*3088717bSVictor Perevertkin }
2439*3088717bSVictor Perevertkin }
2440*3088717bSVictor Perevertkin }
2441*3088717bSVictor Perevertkin
2442*3088717bSVictor Perevertkin // now, all decisions are made. display trace information.
2443*3088717bSVictor Perevertkin if (retry)
2444*3088717bSVictor Perevertkin {
2445*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2446*3088717bSVictor Perevertkin "Command shall be retried in %2I64d.%03I64d seconds\n",
2447*3088717bSVictor Perevertkin (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND),
2448*3088717bSVictor Perevertkin (*RetryIntervalIn100ns / 10000) % 1000
2449*3088717bSVictor Perevertkin ));
2450*3088717bSVictor Perevertkin }
2451*3088717bSVictor Perevertkin else
2452*3088717bSVictor Perevertkin {
2453*3088717bSVictor Perevertkin TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2454*3088717bSVictor Perevertkin "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n",
2455*3088717bSVictor Perevertkin senseBuffer->SenseKey,
2456*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCode,
2457*3088717bSVictor Perevertkin senseBuffer->AdditionalSenseCodeQualifier
2458*3088717bSVictor Perevertkin ));
2459*3088717bSVictor Perevertkin }
2460*3088717bSVictor Perevertkin
2461*3088717bSVictor Perevertkin return retry;
2462*3088717bSVictor Perevertkin
2463*3088717bSVictor Perevertkin } // end SenseInfoInterpret()
2464*3088717bSVictor Perevertkin
2465*3088717bSVictor Perevertkin
2466*3088717bSVictor Perevertkin BOOLEAN
2467*3088717bSVictor Perevertkin RequestSenseInfoInterpret(
2468*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2469*3088717bSVictor Perevertkin _In_ WDFREQUEST Request,
2470*3088717bSVictor Perevertkin _In_ PSCSI_REQUEST_BLOCK Srb,
2471*3088717bSVictor Perevertkin _In_ ULONG RetriedCount,
2472*3088717bSVictor Perevertkin _Out_ NTSTATUS* Status,
2473*3088717bSVictor Perevertkin _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
2474*3088717bSVictor Perevertkin LONGLONG* RetryIntervalIn100ns
2475*3088717bSVictor Perevertkin )
2476*3088717bSVictor Perevertkin /*++
2477*3088717bSVictor Perevertkin
2478*3088717bSVictor Perevertkin Routine Description:
2479*3088717bSVictor Perevertkin
2480*3088717bSVictor Perevertkin Interpret the error, process it.
2481*3088717bSVictor Perevertkin 1. Release device queue if it's frozen.
2482*3088717bSVictor Perevertkin 2. Interpret and process the error.
2483*3088717bSVictor Perevertkin
2484*3088717bSVictor Perevertkin Arguments:
2485*3088717bSVictor Perevertkin
2486*3088717bSVictor Perevertkin DeviceExtension - Supplies the device object associated with this request.
2487*3088717bSVictor Perevertkin Request - the Request that error occurs on.
2488*3088717bSVictor Perevertkin Srb - Supplies the scsi request block which failed.
2489*3088717bSVictor Perevertkin RetriedCount - retried count.
2490*3088717bSVictor Perevertkin
2491*3088717bSVictor Perevertkin Return Value:
2492*3088717bSVictor Perevertkin
2493*3088717bSVictor Perevertkin BOOLEAN TRUE: Drivers should retry this request.
2494*3088717bSVictor Perevertkin FALSE: Drivers should not retry this request.
2495*3088717bSVictor Perevertkin Status - Returns the status for the request.
2496*3088717bSVictor Perevertkin RetryIntervalIn100nsUnits - Number of 100ns before the request should be retried.
2497*3088717bSVictor Perevertkin Zero indicates the request should be immediately retried.
2498*3088717bSVictor Perevertkin
2499*3088717bSVictor Perevertkin --*/
2500*3088717bSVictor Perevertkin {
2501*3088717bSVictor Perevertkin BOOLEAN retry = FALSE;
2502*3088717bSVictor Perevertkin LONGLONG retryIntervalIn100ns = 0;
2503*3088717bSVictor Perevertkin PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
2504*3088717bSVictor Perevertkin
2505*3088717bSVictor Perevertkin if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
2506*3088717bSVictor Perevertkin {
2507*3088717bSVictor Perevertkin // request succeeded.
2508*3088717bSVictor Perevertkin if ((zpoddInfo != NULL) &&
2509*3088717bSVictor Perevertkin (zpoddInfo->BecomingReadyRetryCount > 0))
2510*3088717bSVictor Perevertkin {
2511*3088717bSVictor Perevertkin zpoddInfo->BecomingReadyRetryCount = 0;
2512*3088717bSVictor Perevertkin }
2513*3088717bSVictor Perevertkin
2514*3088717bSVictor Perevertkin *Status = STATUS_SUCCESS;
2515*3088717bSVictor Perevertkin retry = FALSE;
2516*3088717bSVictor Perevertkin }
2517*3088717bSVictor Perevertkin else
2518*3088717bSVictor Perevertkin {
2519*3088717bSVictor Perevertkin // request failed. We need to process the error.
2520*3088717bSVictor Perevertkin
2521*3088717bSVictor Perevertkin // 1. Release the queue if it is frozen.
2522*3088717bSVictor Perevertkin if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN)
2523*3088717bSVictor Perevertkin {
2524*3088717bSVictor Perevertkin DeviceReleaseQueue(DeviceExtension->Device);
2525*3088717bSVictor Perevertkin }
2526*3088717bSVictor Perevertkin
2527*3088717bSVictor Perevertkin if ((zpoddInfo != NULL) &&
2528*3088717bSVictor Perevertkin ((zpoddInfo->RetryFirstCommand != FALSE) || (zpoddInfo->BecomingReadyRetryCount > 0)))
2529*3088717bSVictor Perevertkin {
2530*3088717bSVictor Perevertkin retry = SenseInfoInterpretForZPODD(DeviceExtension,
2531*3088717bSVictor Perevertkin Srb,
2532*3088717bSVictor Perevertkin Status,
2533*3088717bSVictor Perevertkin &retryIntervalIn100ns);
2534*3088717bSVictor Perevertkin }
2535*3088717bSVictor Perevertkin
2536*3088717bSVictor Perevertkin if (retry == FALSE)
2537*3088717bSVictor Perevertkin {
2538*3088717bSVictor Perevertkin // 2. Error Processing
2539*3088717bSVictor Perevertkin if ((zpoddInfo != NULL) &&
2540*3088717bSVictor Perevertkin (zpoddInfo->BecomingReadyRetryCount > 0))
2541*3088717bSVictor Perevertkin {
2542*3088717bSVictor Perevertkin zpoddInfo->BecomingReadyRetryCount = 0;
2543*3088717bSVictor Perevertkin }
2544*3088717bSVictor Perevertkin
2545*3088717bSVictor Perevertkin retry = SenseInfoInterpret(DeviceExtension,
2546*3088717bSVictor Perevertkin Request,
2547*3088717bSVictor Perevertkin Srb,
2548*3088717bSVictor Perevertkin RetriedCount,
2549*3088717bSVictor Perevertkin Status,
2550*3088717bSVictor Perevertkin &retryIntervalIn100ns);
2551*3088717bSVictor Perevertkin }
2552*3088717bSVictor Perevertkin }
2553*3088717bSVictor Perevertkin
2554*3088717bSVictor Perevertkin if (RetryIntervalIn100ns != NULL)
2555*3088717bSVictor Perevertkin {
2556*3088717bSVictor Perevertkin *RetryIntervalIn100ns = retryIntervalIn100ns;
2557*3088717bSVictor Perevertkin }
2558*3088717bSVictor Perevertkin
2559*3088717bSVictor Perevertkin return retry;
2560*3088717bSVictor Perevertkin }
2561*3088717bSVictor Perevertkin
2562*3088717bSVictor Perevertkin
2563*3088717bSVictor Perevertkin BOOLEAN
2564*3088717bSVictor Perevertkin RequestSenseInfoInterpretForScratchBuffer(
2565*3088717bSVictor Perevertkin _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2566*3088717bSVictor Perevertkin _In_ ULONG RetriedCount,
2567*3088717bSVictor Perevertkin _Out_ NTSTATUS* Status,
2568*3088717bSVictor Perevertkin _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
2569*3088717bSVictor Perevertkin LONGLONG* RetryIntervalIn100ns
2570*3088717bSVictor Perevertkin )
2571*3088717bSVictor Perevertkin /*++
2572*3088717bSVictor Perevertkin
2573*3088717bSVictor Perevertkin Routine Description:
2574*3088717bSVictor Perevertkin
2575*3088717bSVictor Perevertkin to analyze the error occurred and set the status, retry interval and decide to retry or not.
2576*3088717bSVictor Perevertkin
2577*3088717bSVictor Perevertkin Arguments:
2578*3088717bSVictor Perevertkin
2579*3088717bSVictor Perevertkin DeviceExtension - device extension
2580*3088717bSVictor Perevertkin RetriedCount - already retried count.
2581*3088717bSVictor Perevertkin
2582*3088717bSVictor Perevertkin Return Value:
2583*3088717bSVictor Perevertkin
2584*3088717bSVictor Perevertkin BOOLEAN - TRUE (should retry)
2585*3088717bSVictor Perevertkin Status - NTSTATUS
2586*3088717bSVictor Perevertkin RetryIntervalIn100nsUnits - retry interval
2587*3088717bSVictor Perevertkin
2588*3088717bSVictor Perevertkin --*/
2589*3088717bSVictor Perevertkin {
2590*3088717bSVictor Perevertkin NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse != 0);
2591*3088717bSVictor Perevertkin
2592*3088717bSVictor Perevertkin return RequestSenseInfoInterpret(DeviceExtension,
2593*3088717bSVictor Perevertkin DeviceExtension->ScratchContext.ScratchRequest,
2594*3088717bSVictor Perevertkin DeviceExtension->ScratchContext.ScratchSrb,
2595*3088717bSVictor Perevertkin RetriedCount,
2596*3088717bSVictor Perevertkin Status,
2597*3088717bSVictor Perevertkin RetryIntervalIn100ns);
2598*3088717bSVictor Perevertkin }
2599*3088717bSVictor Perevertkin
2600*3088717bSVictor Perevertkin
2601