ReactOS 0.4.15-dev-7907-g95bf896
sense.c File Reference
#include "stddef.h"
#include "string.h"
#include "ntddk.h"
#include "ntddstor.h"
#include "cdrom.h"
#include "ntstrsafe.h"
Include dependency graph for sense.c:

Go to the source code of this file.

Classes

struct  _ERROR_LOG_CONTEXT
 

Macros

#define TOTAL_COUNT_RETRY_DEFAULT   4
 
#define TOTAL_COUNT_RETRY_LOCK_MEDIA   1
 
#define TOTAL_COUNT_RETRY_MODESENSE   1
 
#define TOTAL_COUNT_RETRY_READ_CAPACITY   1
 
#define TOTAL_SECONDS_RETRY_TIME_WRITE   160
 
#define TOTAL_SECONDS_RETRY_TIME_MEDIUM_REMOVAL   120
 

Typedefs

typedef struct _ERROR_LOG_CONTEXT ERROR_LOG_CONTEXT
 
typedef struct _ERROR_LOG_CONTEXTPERROR_LOG_CONTEXT
 

Functions

VOID SenseInfoInterpretRefineByIoControl (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status)
 
NTSTATUS DeviceErrorHandlerForMmc (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
 
NTSTATUS DeviceErrorHandlerForHitachiGD2000 (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
 
VOID SenseInfoRequestGetInformation (_In_ WDFREQUEST Request, _Out_ UCHAR *MajorFunctionCode, _Out_ ULONG *IoControlCode, _Out_ BOOLEAN *OverrideVerifyVolume, _Out_ ULONGLONG *Total100nsSinceFirstSend)
 
BOOLEAN SenseInfoInterpretByAdditionalSenseCode (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ UCHAR AdditionalSenseCode, _In_ UCHAR AdditionalSenseCodeQual, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
 
VOID SenseInfoInterpretBySenseKey (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSENSE_DATA SenseData, _In_ UCHAR SenseKey, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
 
VOID SenseInfoInterpretBySrbStatus (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
 
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)
 
VOID SenseInfoInterpretRefineByScsiCommand (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _In_ LONGLONG Total100nsSinceFirstSend, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status, _Inout_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
 
BOOLEAN SenseInfoInterpret (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
 
BOOLEAN SenseInfoInterpretForZPODD (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Out_ NTSTATUS *Status, _Out_ _Out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
 
BOOLEAN RequestSenseInfoInterpret (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
 
BOOLEAN RequestSenseInfoInterpretForScratchBuffer (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
 

Macro Definition Documentation

◆ TOTAL_COUNT_RETRY_DEFAULT

#define TOTAL_COUNT_RETRY_DEFAULT   4

Definition at line 69 of file sense.c.

◆ TOTAL_COUNT_RETRY_LOCK_MEDIA

#define TOTAL_COUNT_RETRY_LOCK_MEDIA   1

Definition at line 70 of file sense.c.

◆ TOTAL_COUNT_RETRY_MODESENSE

#define TOTAL_COUNT_RETRY_MODESENSE   1

Definition at line 71 of file sense.c.

◆ TOTAL_COUNT_RETRY_READ_CAPACITY

#define TOTAL_COUNT_RETRY_READ_CAPACITY   1

Definition at line 72 of file sense.c.

◆ TOTAL_SECONDS_RETRY_TIME_MEDIUM_REMOVAL

#define TOTAL_SECONDS_RETRY_TIME_MEDIUM_REMOVAL   120

Definition at line 76 of file sense.c.

◆ TOTAL_SECONDS_RETRY_TIME_WRITE

#define TOTAL_SECONDS_RETRY_TIME_WRITE   160

Definition at line 75 of file sense.c.

Typedef Documentation

◆ ERROR_LOG_CONTEXT

◆ PERROR_LOG_CONTEXT

Function Documentation

◆ DeviceErrorHandlerForHitachiGD2000()

NTSTATUS DeviceErrorHandlerForHitachiGD2000 ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_Inout_ PNTSTATUS  Status,
_Inout_ PBOOLEAN  Retry 
)

Definition at line 361 of file sense.c.

394{
395 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
396
398 {
399 return STATUS_SUCCESS; //nobody cares about this return value yet.
400 }
401
402 if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_HARDWARE_ERROR) &&
403 (senseBuffer->AdditionalSenseCode == 0x44))
404 {
405 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
406 "DeviceErrorHandlerForHitachiGD2000 (%p) => Internal Target "
407 "Failure Detected -- spinning up drive\n", DeviceExtension->Device));
408
409 // the request should be retried because the device isn't ready
410 *Retry = TRUE;
412
413 // send a START_STOP unit to spin up the drive
414 // NOTE: this temporarily violates the StartIo serialization
415 // mechanism, but the completion routine on this will NOT
416 // call StartNextPacket(), so it's a temporary disruption
417 // of the serialization only.
418 DeviceSendStartUnit(DeviceExtension->Device);
419 }
420
421 return STATUS_SUCCESS;
422}
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
VOID DeviceSendStartUnit(_In_ WDFDEVICE Device)
Definition: common.c:877
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
#define TRUE
Definition: types.h:120
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
Status
Definition: gdiplustypes.h:25
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
PVOID SenseInfoBuffer
Definition: srb.h:264
UCHAR SrbStatus
Definition: srb.h:251
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
UCHAR SenseKey
Definition: cdrw_hw.h:1167

◆ DeviceErrorHandlerForMmc()

NTSTATUS DeviceErrorHandlerForMmc ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_Inout_ PNTSTATUS  Status,
_Inout_ PBOOLEAN  Retry 
)

Definition at line 87 of file sense.c.

117{
118 BOOLEAN mediaChange = FALSE;
119 PCDB cdb = (PCDB)Srb->Cdb;
120
122 {
123 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
124
125 // the following sense keys could indicate a change in capabilities.
126
127 // we used to expect this to be serialized, and only hit from our
128 // own routine. we now allow some requests to continue during our
129 // processing of the capabilities update in order to allow
130 // IoReadPartitionTable() to succeed.
131 switch (senseBuffer->SenseKey & 0xf)
132 {
133
135 {
137 {
138 if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
139 {
140 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
141 "DeviceErrorHandlerForMmc: media removed, writes will be "
142 "failed until new media detected\n"));
143 }
144
145 // NOTE - REF #0002
146 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
147 }
148 else if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)
149 {
151 {
152 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
153 "DeviceErrorHandlerForMmc: media becoming ready, "
154 "SHOULD notify shell of change time by sending "
155 "GESN request immediately!\n"));
156 }
159 ) &&
160 ((Srb->Cdb[0] == SCSIOP_READ) ||
161 (Srb->Cdb[0] == SCSIOP_READ6) ||
162 (Srb->Cdb[0] == SCSIOP_READ_CAPACITY) ||
163 (Srb->Cdb[0] == SCSIOP_READ_CD) ||
164 (Srb->Cdb[0] == SCSIOP_READ_CD_MSF) ||
165 (Srb->Cdb[0] == SCSIOP_READ_TOC) ||
166 (Srb->Cdb[0] == SCSIOP_WRITE) ||
167 (Srb->Cdb[0] == SCSIOP_WRITE6) ||
170 )
171 )
172 {
173 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
174 "DeviceErrorHandlerForMmc: LONG_WRITE or "
175 "OP_IN_PROGRESS for limited subset of cmds -- "
176 "setting retry to TRUE\n"));
177 *Retry = TRUE;
179 }
180 }
181 break;
182 } // end SCSI_SENSE_NOT_READY
183
185 {
186 switch (senseBuffer->AdditionalSenseCode)
187 {
189 {
190 // always update if the medium may have changed
191
192 // NOTE - REF #0002
193 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
194 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
195
196 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
197 "DeviceErrorHandlerForMmc: media change detected, need to "
198 "update drive capabilities\n"));
199 mediaChange = TRUE;
200 break;
201
202 } // end SCSI_ADSENSE_MEDIUM_CHANGED
203
205 {
206 // NOTE - REF #0002
207 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
208 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
209
210 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
211 "DeviceErrorHandlerForMmc: bus reset detected, need to "
212 "update drive capabilities\n"));
213 break;
214
215 } // end SCSI_ADSENSE_BUS_RESET
216
218 {
219
220 BOOLEAN b = FALSE;
221
222 switch (senseBuffer->AdditionalSenseCodeQualifier)
223 {
225 {
226 // eject notification currently handled by classpnp
227 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
228 "DeviceErrorHandlerForMmc: Eject requested by user\n"));
229 *Retry = TRUE;
231 break;
232 }
233
235 b = TRUE;
237 {
238 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
239 "DeviceErrorHandlerForMmc: Write protect %s requested "
240 "by user\n",
241 (b ? "disable" : "enable")));
242 *Retry = TRUE;
244 // NOTE - REF #0002
245 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
246 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
247
248 break;
249 }
250
251 } // end of AdditionalSenseCodeQualifier switch
252
253
254 break;
255
256 } // end SCSI_ADSENSE_OPERATOR_REQUEST
257
258 default:
259 {
260 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
261 "DeviceErrorHandlerForMmc: Unit attention %02x/%02x\n",
262 senseBuffer->AdditionalSenseCode,
263 senseBuffer->AdditionalSenseCodeQualifier));
264 break;
265 }
266
267 } // end of AdditionSenseCode switch
268 break;
269
270 } // end SCSI_SENSE_UNIT_ATTENTION
271
273 {
275 {
276 if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
277 {
278 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
279 "DeviceErrorHandlerForMmc: media was writable, but "
280 "failed request with WRITE_PROTECT error...\n"));
281 }
282 // NOTE - REF #0002
283 // do not update all the capabilities just because
284 // we can't write to the disc.
285 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
286 }
287 break;
288 } // end SCSI_SENSE_ILLEGAL_REQUEST
289
290 } // end of SenseKey switch
291
292 // Check if we failed to set the DVD region key and send appropriate error
293 if (cdb->CDB16.OperationCode == SCSIOP_SEND_KEY)
294 {
295 if (cdb->SEND_KEY.KeyFormat == DvdSetRpcKey)
296 {
298 {
299 // media of appropriate region required
301 *Retry = FALSE;
302 }
303 else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
306 {
307 // media of appropriate region required
309 *Retry = FALSE;
310 }
311 else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
314 {
315 // media of appropriate region required
317 *Retry = FALSE;
318 }
319 }
320 }
321 } // end of SRB_STATUS_AUTOSENSE_VALID
322
323 // On media change, if device speed should be reset to default then
324 // queue a workitem to send the commands to the device. Do this on
325 // media arrival as some device will fail this command if no media
326 // is present. Ignore the fake media change from classpnp driver.
327 if ((mediaChange == TRUE) && (*Status != STATUS_MEDIA_CHANGED))
328 {
329 if (DeviceExtension->DeviceAdditionalData.RestoreDefaults == TRUE)
330 {
332 WDF_OBJECT_ATTRIBUTES attributes;
333 WDF_WORKITEM_CONFIG workitemConfig;
334 WDFWORKITEM workItem;
335
336 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
337 attributes.ParentObject = DeviceExtension->Device;
338
339 WDF_WORKITEM_CONFIG_INIT(&workitemConfig,
341
342 status = WdfWorkItemCreate(&workitemConfig,
343 &attributes,
344 &workItem);
345 if (!NT_SUCCESS(status))
346 {
347 return STATUS_SUCCESS;
348 }
349
350 WdfWorkItemEnqueue(workItem);
351
352 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
353 "DeviceErrorHandlerForMmc: Restore device default speed for %p\n",
354 DeviceExtension->DeviceObject));
355 }
356 }
357 return STATUS_SUCCESS;
358}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
EVT_WDF_WORKITEM DeviceRestoreDefaultSpeed
Definition: cdrom.h:1180
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_READ_CD
Definition: cdrw_hw.h:967
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SCSI_SENSEQ_INCOMPATIBLE_FORMAT
Definition: cdrw_hw.h:1323
#define SCSIOP_READ_TOC
Definition: cdrw_hw.h:927
#define SCSI_ADSENSE_WRITE_PROTECT
Definition: cdrw_hw.h:1268
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
#define SCSIOP_READ6
Definition: cdrw_hw.h:874
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define SCSIOP_SEND_KEY
Definition: cdrw_hw.h:951
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define SCSIOP_READ_CD_MSF
Definition: cdrw_hw.h:964
union _CDB * PCDB
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
if(dx< 0)
Definition: linetemp.h:194
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
@ DvdSetRpcKey
Definition: ntddcdvd.h:169
#define SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
#define SCSIOP_READ_TRACK_INFORMATION
Definition: scsi.h:315
#define SCSI_SENSEQ_WRITE_PROTECT_DISABLE
Definition: scsi.h:881
#define SCSIOP_READ_DISK_INFORMATION
Definition: scsi.h:313
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define SCSI_SENSEQ_WRITE_PROTECT_ENABLE
Definition: scsi.h:880
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UCHAR Cdb[16]
Definition: srb.h:279
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
WDFOBJECT ParentObject
Definition: wdfobject.h:130
Definition: ps.c:97
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
Definition: cdrw_hw.h:28
struct _CDB::_SEND_KEY SEND_KEY
struct _CDB::_CDB16 CDB16
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85

◆ RequestSenseInfoInterpret()

BOOLEAN RequestSenseInfoInterpret ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ WDFREQUEST  Request,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  RetriedCount,
_Out_ NTSTATUS Status,
_Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG RetryIntervalIn100ns 
)

Definition at line 2467 of file sense.c.

2500{
2501 BOOLEAN retry = FALSE;
2502 LONGLONG retryIntervalIn100ns = 0;
2503 PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
2504
2506 {
2507 // request succeeded.
2508 if ((zpoddInfo != NULL) &&
2509 (zpoddInfo->BecomingReadyRetryCount > 0))
2510 {
2511 zpoddInfo->BecomingReadyRetryCount = 0;
2512 }
2513
2515 retry = FALSE;
2516 }
2517 else
2518 {
2519 // request failed. We need to process the error.
2520
2521 // 1. Release the queue if it is frozen.
2523 {
2524 DeviceReleaseQueue(DeviceExtension->Device);
2525 }
2526
2527 if ((zpoddInfo != NULL) &&
2528 ((zpoddInfo->RetryFirstCommand != FALSE) || (zpoddInfo->BecomingReadyRetryCount > 0)))
2529 {
2530 retry = SenseInfoInterpretForZPODD(DeviceExtension,
2531 Srb,
2532 Status,
2533 &retryIntervalIn100ns);
2534 }
2535
2536 if (retry == FALSE)
2537 {
2538 // 2. Error Processing
2539 if ((zpoddInfo != NULL) &&
2540 (zpoddInfo->BecomingReadyRetryCount > 0))
2541 {
2542 zpoddInfo->BecomingReadyRetryCount = 0;
2543 }
2544
2545 retry = SenseInfoInterpret(DeviceExtension,
2546 Request,
2547 Srb,
2548 RetriedCount,
2549 Status,
2550 &retryIntervalIn100ns);
2551 }
2552 }
2553
2554 if (RetryIntervalIn100ns != NULL)
2555 {
2556 *RetryIntervalIn100ns = retryIntervalIn100ns;
2557 }
2558
2559 return retry;
2560}
VOID DeviceReleaseQueue(_In_ WDFDEVICE Device)
Definition: common.c:1179
#define NULL
Definition: types.h:112
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
BOOLEAN SenseInfoInterpretForZPODD(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Out_ NTSTATUS *Status, _Out_ _Out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2341
BOOLEAN SenseInfoInterpret(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2038
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
int64_t LONGLONG
Definition: typedefs.h:68
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547

Referenced by _IRQL_requires_max_(), and RequestSenseInfoInterpretForScratchBuffer().

◆ RequestSenseInfoInterpretForScratchBuffer()

BOOLEAN RequestSenseInfoInterpretForScratchBuffer ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ ULONG  RetriedCount,
_Out_ NTSTATUS Status,
_Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG RetryIntervalIn100ns 
)

Definition at line 2564 of file sense.c.

2589{
2590 NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse != 0);
2591
2592 return RequestSenseInfoInterpret(DeviceExtension,
2593 DeviceExtension->ScratchContext.ScratchRequest,
2594 DeviceExtension->ScratchContext.ScratchSrb,
2595 RetriedCount,
2596 Status,
2597 RetryIntervalIn100ns);
2598}
BOOLEAN RequestSenseInfoInterpret(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2467
#define NT_ASSERT
Definition: rtlfuncs.h:3310

Referenced by RequestIssueShutdownFlush(), and ScratchBuffer_ReadWriteCompletionRoutine().

◆ SenseInfoInterpret()

BOOLEAN SenseInfoInterpret ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ WDFREQUEST  Request,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  RetriedCount,
_Out_ NTSTATUS Status,
_Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG RetryIntervalIn100ns 
)

Definition at line 2038 of file sense.c.

2073{
2074 ULONG retryIntervalInSeconds = 0;
2075 BOOLEAN retry = TRUE;
2076 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
2077 ULONG readSector = 0;
2078 ERROR_LOG_CONTEXT logContext;
2079
2080 UCHAR majorFunctionCode = 0;
2081 ULONG ioControlCode = 0;
2082 BOOLEAN overrideVerifyVolume = FALSE;
2083 ULONGLONG total100nsSinceFirstSend = 0;
2084 PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
2085
2086 //
2088
2089 RtlZeroMemory(&logContext, sizeof(ERROR_LOG_CONTEXT));
2090 logContext.ErrorCode = -1;
2091
2092 // Get Original Request related information
2094 &majorFunctionCode,
2095 &ioControlCode,
2096 &overrideVerifyVolume,
2097 &total100nsSinceFirstSend);
2098
2100 {
2101 // Log anything remotely incorrect about paging i/o
2102 logContext.LogError = TRUE;
2103 logContext.UniqueErrorValue = 301;
2105 }
2106
2107 // must handle the SRB_STATUS_INTERNAL_ERROR case first,
2108 // as it has all the flags set.
2110 {
2111 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
2112 "SenseInfoInterpret: Internal Error code is %x\n",
2114
2115 retry = FALSE;
2117 }
2119 {
2120 retry = FALSE;
2122 logContext.LogError = FALSE;
2123 }
2125 (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)))
2126 {
2127 UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f);
2129 UCHAR additionalSenseCodeQual = 0;
2130
2131 // Zero the additional sense code and additional sense code qualifier
2132 // if they were not returned by the device.
2133 readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength);
2134 if (readSector > Srb->SenseInfoBufferLength)
2135 {
2136 readSector = Srb->SenseInfoBufferLength;
2137 }
2138
2140 senseBuffer->AdditionalSenseCode : 0;
2141 additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ?
2142 senseBuffer->AdditionalSenseCodeQualifier : 0;
2143
2144 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2145 "SCSI Error - \n"
2146 "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
2147 "\tsrb status: %X; sense: %02X/%02X/%02X; Retried count: %d\n\n",
2148 Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5],
2149 Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11],
2150 Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15],
2152 senseKey,
2154 additionalSenseCodeQual,
2155 RetriedCount));
2156
2158 {
2159 ULONG mediaChangeCount;
2160
2161 // A media change may have occured so increment the change count for the physical device
2162 mediaChangeCount = InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
2163 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2164 "SenseInfoInterpret: Media change count for device %d incremented to %#lx\n",
2165 DeviceExtension->DeviceNumber, mediaChangeCount));
2166 }
2167
2168 if ((zpoddInfo != NULL) &&
2169 (((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode == SCSIOP_TEST_UNIT_READY))
2170 {
2171 // This sense code is in response to the Test Unit Ready sent during delayed power down
2172 // request. Copy the sense data into the zpoddInfo structure for later processing.
2173 zpoddInfo->SenseKey = senseKey;
2175 zpoddInfo->AdditionalSenseCodeQualifier = additionalSenseCodeQual;
2176 }
2177
2178 // Interpret error by specific ASC & ASCQ first,
2179 // If the error is not handled, interpret using f
2180 {
2181 BOOLEAN notHandled = FALSE;
2182 notHandled = SenseInfoInterpretByAdditionalSenseCode(DeviceExtension,
2183 Srb,
2185 additionalSenseCodeQual,
2186 Status,
2187 &retry,
2188 &retryIntervalInSeconds,
2189 &logContext);
2190
2191 if (notHandled)
2192 {
2193 SenseInfoInterpretBySenseKey(DeviceExtension,
2194 senseBuffer,
2195 senseKey,
2196 Status,
2197 &retry,
2198 &retryIntervalInSeconds,
2199 &logContext);
2200 }
2201 }
2202
2203 // Try to determine the bad sector from the inquiry data.
2204 if ((IS_SCSIOP_READWRITE(((PCDB)Srb->Cdb)->CDB10.OperationCode)) ||
2205 (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY) ||
2206 (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY16))
2207 {
2208 ULONG index;
2209 readSector = 0;
2210
2211 for (index = 0; index < 4; index++)
2212 {
2213 logContext.BadSector = (logContext.BadSector << 8) | senseBuffer->Information[index];
2214 }
2215
2216 for (index = 0; index < 4; index++)
2217 {
2218 readSector = (readSector << 8) | Srb->Cdb[index+2];
2219 }
2220
2221 index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) |
2222 ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb;
2223
2224 // Make sure the bad sector is within the read sectors.
2225 if (!(logContext.BadSector >= readSector && logContext.BadSector < (readSector + index)))
2226 {
2227 logContext.BadSector = readSector;
2228 }
2229 }
2230 }
2231 else
2232 {
2233 // Request sense buffer not valid. No sense information
2234 // to pinpoint the error. Return general request fail.
2235 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2236 "SCSI Error - \n"
2237 "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
2238 "\tsrb status: %X; sense info not valid; Retried count: %d\n\n",
2239 Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5],
2240 Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11],
2241 Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15],
2243 RetriedCount));
2244
2245 SenseInfoInterpretBySrbStatus(DeviceExtension,
2246 Srb,
2247 RetriedCount,
2248 Status,
2249 &retry,
2250 &retryIntervalInSeconds,
2251 &logContext);
2252 }
2253
2254 // all functions using unit - seconds for retry Interval already be called.
2255 *RetryIntervalIn100ns = SECONDS_TO_100NS_UNITS(retryIntervalInSeconds);
2256
2257 // call the device specific error handler if it has one.
2258 // DeviceErrorHandlerForMmmc() for all MMC devices
2259 // or DeviceErrorHandlerForHitachiGD2000() for HITACHI GD-2000, HITACHI DVD-ROM GD-2000
2260 if (DeviceExtension->DeviceAdditionalData.ErrorHandler)
2261 {
2262 DeviceExtension->DeviceAdditionalData.ErrorHandler(DeviceExtension, Srb, Status, &retry);
2263 }
2264
2265 // Refine retry based on SCSI command
2267 Srb,
2268 RetriedCount,
2269 total100nsSinceFirstSend,
2270 overrideVerifyVolume,
2271 &retry,
2272 Status,
2273 RetryIntervalIn100ns);
2274
2275 // Refine retry based on IOCTL code.
2276 if (majorFunctionCode == IRP_MJ_DEVICE_CONTROL)
2277 {
2279 ioControlCode,
2280 overrideVerifyVolume,
2281 &retry,
2282 Status);
2283 }
2284
2285 // LOG the error:
2286 // Always log the error in our internal log.
2287 // If logError is set, also log the error in the system log.
2288 SenseInfoLogError(DeviceExtension,
2289 Srb,
2290 majorFunctionCode,
2291 ioControlCode,
2292 RetriedCount,
2293 Status,
2294 &retry,
2295 &logContext);
2296
2297 // all process about the error done. check if the irp was cancelled.
2298 if ((!NT_SUCCESS(*Status)) && retry)
2299 {
2300 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
2301
2302 if ((requestContext->OriginalRequest != NULL) &&
2303 WdfRequestIsCanceled(requestContext->OriginalRequest)
2304 )
2305 {
2306 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2307 "Request %p was cancelled when it would have been retried\n",
2308 requestContext->OriginalRequest));
2309
2311 retry = FALSE;
2312 *RetryIntervalIn100ns = 0;
2313 }
2314 }
2315
2316 // now, all decisions are made. display trace information.
2317 if (retry)
2318 {
2319 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2320 "Command shall be retried in %2I64d.%03I64d seconds\n",
2321 (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND),
2322 (*RetryIntervalIn100ns / 10000) % 1000
2323 ));
2324 }
2325 else
2326 {
2327 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2328 "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n",
2329 senseBuffer->SenseKey,
2330 senseBuffer->AdditionalSenseCode,
2331 senseBuffer->AdditionalSenseCodeQualifier
2332 ));
2333 }
2334
2335 return retry;
2336
2337} // end SenseInfoInterpret()
#define InterlockedIncrement
Definition: armddk.h:53
#define index(s, c)
Definition: various.h:29
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
#define SECONDS_TO_100NS_UNITS(x)
Definition: cdrom.h:1488
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
#define UNIT_100NS_PER_SECOND
Definition: cdrom.h:1487
#define SCSISTAT_RESERVATION_CONFLICT
Definition: cdrw_hw.h:1084
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define SCSIOP_VERIFY16
Definition: scsi.h:916
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:373
GLuint index
Definition: glext.h:6031
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define offsetof(TYPE, MEMBER)
UCHAR additionalSenseCode
Definition: scsi.h:4020
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCodeQualifier
Definition: scsi.h:3748
UCHAR senseKey
Definition: scsi.h:4019
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCode
Definition: scsi.h:3746
VOID SenseInfoInterpretBySenseKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSENSE_DATA SenseData, _In_ UCHAR SenseKey, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
Definition: sense.c:1080
VOID SenseInfoInterpretRefineByScsiCommand(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _In_ LONGLONG Total100nsSinceFirstSend, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status, _Inout_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:1663
VOID SenseInfoInterpretBySrbStatus(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
Definition: sense.c:1262
VOID SenseInfoInterpretRefineByIoControl(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status)
Definition: sense.c:1953
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)
Definition: sense.c:1430
VOID SenseInfoRequestGetInformation(_In_ WDFREQUEST Request, _Out_ UCHAR *MajorFunctionCode, _Out_ ULONG *IoControlCode, _Out_ BOOLEAN *OverrideVerifyVolume, _Out_ ULONGLONG *Total100nsSinceFirstSend)
Definition: sense.c:426
BOOLEAN SenseInfoInterpretByAdditionalSenseCode(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ UCHAR AdditionalSenseCode, _In_ UCHAR AdditionalSenseCodeQual, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
Definition: sense.c:484
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
BOOLEAN LogError
Definition: sense.c:79
NTSTATUS ErrorCode
Definition: sense.c:81
ULONG UniqueErrorValue
Definition: sense.c:82
ULONG BadSector
Definition: sense.c:83
UCHAR SenseInfoBufferLength
Definition: srb.h:259
UCHAR ScsiStatus
Definition: srb.h:252
ULONG InternalStatus
Definition: srb.h:269
ULONG SrbFlags
Definition: srb.h:260
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
UCHAR Information[4]
Definition: cdrw_hw.h:1172
UCHAR AdditionalSenseCode
Definition: cdromp.h:280
UCHAR AdditionalSenseCodeQualifier
Definition: cdromp.h:281
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by RequestSenseInfoInterpret().

◆ SenseInfoInterpretByAdditionalSenseCode()

BOOLEAN SenseInfoInterpretByAdditionalSenseCode ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ UCHAR  AdditionalSenseCode,
_In_ UCHAR  AdditionalSenseCodeQual,
_Inout_ NTSTATUS Status,
_Inout_ BOOLEAN Retry,
_Out_ _Deref_out_range_(0, 100) ULONG RetryIntervalInSeconds,
_Inout_ PERROR_LOG_CONTEXT  LogContext 
)

Definition at line 484 of file sense.c.

500{
501 BOOLEAN needFurtherInterpret = TRUE;
503
504 // set default values for retry fields.
506 *Retry = TRUE;
507 *RetryIntervalInSeconds = 0;
508
510 {
512 {
513 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
514 "SenseInfoInterpretByAdditionalSenseCode: Lun not ready\n"));
515
516 //
517 // Many non-WHQL certified drives (mostly CD-RW) return
518 // 2/4/0 when they have no media instead of the obvious choice of:
519 //
520 // SCSI_SENSE_NOT_READY/SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
521 //
522 // These drives should not pass WHQL certification due to this discrepency.
523 //
524 // However, we have to retry on 2/4/0 (Not ready, LUN not ready, no info)
525 // and also 3/2/0 (no seek complete).
526 //
527 // These conditions occur when the shell tries to examine an
528 // injected CD (e.g. for autoplay) before the CD is spun up.
529 //
530 // The drive should be returning an ASCQ of SCSI_SENSEQ_BECOMING_READY
531 // (0x01) in order to comply with WHQL standards.
532 //
533 // The default retry timeout of one second is acceptable to balance
534 // these discrepencies. don't modify the status, though....
535 //
536
537 switch (AdditionalSenseCodeQual)
538 {
540 {
541 DEVICE_EVENT_BECOMING_READY notReady = {0};
542
543 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
544 "SenseInfoInterpretByAdditionalSenseCode: Operation In Progress\n"));
545
546 needFurtherInterpret = FALSE;
547
548 *Retry = TRUE;
549 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
551
552 notReady.Version = 1;
553 notReady.Reason = 2;
554 notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10;
555 DeviceSendNotification(DeviceExtension,
556 &GUID_IO_DEVICE_BECOMING_READY,
558 &notReady);
559
560 break;
561 }
562
564 {
565 DEVICE_EVENT_BECOMING_READY notReady = {0};
566
567 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
568 "SenseInfoInterpretByAdditionalSenseCode: In process of becoming ready\n"));
569
570 needFurtherInterpret = FALSE;
571
572 *Retry = TRUE;
573 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
575
576 notReady.Version = 1;
577 notReady.Reason = 1;
578 notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10;
579 DeviceSendNotification(DeviceExtension,
580 &GUID_IO_DEVICE_BECOMING_READY,
582 &notReady);
583
584 break;
585 }
586
588 {
589 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
590 "SenseInfoInterpretByAdditionalSenseCode: Long write in progress\n"));
591
592 needFurtherInterpret = FALSE;
593
594 // This has been seen as a transcient failure on some drives
596 *Retry = TRUE;
597 // Set retry interval to be 0 as the drive can be ready at anytime.
598 *RetryIntervalInSeconds = 0;
599
600 break;
601 }
602
604 {
605 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
606 "SenseInfoInterpretByAdditionalSenseCode: Manual intervention required\n"));
607
608 needFurtherInterpret = FALSE;
609
611 *Retry = FALSE;
612 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
613
614 break;
615 }
616
618 {
619 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
620 "SenseInfoInterpretByAdditionalSenseCode: Format in progress\n"));
621
622 needFurtherInterpret = FALSE;
623
625 *Retry = FALSE;
626 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
627
628 break;
629 }
630
633 default:
634 {
635 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
636 "SenseInfoInterpretByAdditionalSenseCode: Initializing command required\n"));
637
638 needFurtherInterpret = FALSE;
639
641 *Retry = TRUE;
642 *RetryIntervalInSeconds = 0;
643
644 // This sense code/additional sense code combination may indicate
645 // that the device needs to be started.
646 if (TEST_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT) &&
648 {
649 DeviceSendStartUnit(DeviceExtension->Device);
650 }
651
652 break;
653 }
654 } // end switch (AdditionalSenseCodeQual)
655 break;
656
657 } // end case (SCSI_ADSENSE_LUN_NOT_READY)
658
660 {
661 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
662 "SenseInfoInterpretByAdditionalSenseCode: No Media in device.\n"));
663
664 needFurtherInterpret = FALSE;
665
667 *Retry = FALSE;
668
669 if (AdditionalSenseCodeQual == 0xCC)
670 {
671 // The IMAPIv1 filter returns this ASCQ value while it is burning CD media, and we want
672 // to preserve this functionality for compatibility reasons.
673 // We want to indicate that the media is not present to most applications;
674 // but RSM has to know that the media is still in the drive (i.e. the drive is not free).
676 }
677 else
678 {
680 }
681
682 break;
683 } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
684
686 {
687 switch (AdditionalSenseCodeQual)
688 {
689
691 {
692 needFurtherInterpret = FALSE;
693
694 // Log error only if this is a paging request
696 *Retry = FALSE;
697
698 LogContext->LogError = TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING);
699 LogContext->UniqueErrorValue = 256;
700 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
701
702 break;
703 }
704
706 {
707 needFurtherInterpret = FALSE;
708
710 *Retry = FALSE;
711
712 LogContext->LogError = FALSE;
713
714 break;
715 }
716
718 {
719 needFurtherInterpret = FALSE;
720
722 *Retry = FALSE;
723
724 LogContext->LogError = FALSE;
725 LogContext->UniqueErrorValue = 256;
726 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
727 break;
728 }
729
730 default:
731 {
732 needFurtherInterpret = TRUE;
733 break;
734 }
735 } // end case AdditionalSenseCodeQual
736
737 break;
738 } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
739
741 {
742 switch (AdditionalSenseCodeQual)
743 {
744
745 case 0x00:
746 {
747 needFurtherInterpret = FALSE;
748
750 *Retry = TRUE;
751 *RetryIntervalInSeconds = 0;
752 LogContext->LogError = TRUE;
753 LogContext->UniqueErrorValue = 256;
754 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
755 break;
756 }
757
758 default:
759 {
760 needFurtherInterpret = TRUE;
761 break;
762 }
763 }
764
765 break;
766 } // end case SCSI_ADSENSE_NO_SEEK_COMPLETE
767
769 {
770 switch (AdditionalSenseCodeQual)
771 {
772
774 {
775 needFurtherInterpret = FALSE;
776
778 *Retry = TRUE;
779 *RetryIntervalInSeconds = 1;
780 LogContext->LogError = TRUE;
781 LogContext->UniqueErrorValue = 257;
782 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
783 break;
784 }
785
786 default:
787 {
788 needFurtherInterpret = TRUE;
789 break;
790 }
791 }
792
793 break;
794 } // end case SCSI_ADSENSE_LUN_COMMUNICATION
795
797 {
798 needFurtherInterpret = FALSE;
799
800 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
801 "SenseInfoInterpretByAdditionalSenseCode: Illegal block address\n"));
803 *Retry = FALSE;
804 break;
805 }
806
808 {
809 needFurtherInterpret = FALSE;
810
811 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
812 "SenseInfoInterpretByAdditionalSenseCode: Invalid LUN\n"));
814 *Retry = FALSE;
815 break;
816 }
817
819 {
820 needFurtherInterpret = FALSE;
821
822 *Retry = FALSE;
823
824 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
825 "SenseInfoInterpretByAdditionalSenseCode: Key - Copy protection failure\n"));
826
827 switch (AdditionalSenseCodeQual)
828 {
830 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
831 "SenseInfoInterpretByAdditionalSenseCode: Authentication failure\n"));
833 break;
835 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
836 "SenseInfoInterpretByAdditionalSenseCode: Key not present\n"));
838 break;
840 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
841 "SenseInfoInterpretByAdditionalSenseCode: Key not established\n"));
843 break;
845 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
846 "SenseInfoInterpretByAdditionalSenseCode: Read of scrambled sector w/o authentication\n"));
848 break;
850 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
851 "SenseInfoInterpretByAdditionalSenseCode: Media region does not logical unit region\n"));
853 break;
855 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
856 "SenseInfoInterpretByAdditionalSenseCode: Region set error -- region may be permanent\n"));
858 break;
859
860 default:
862 break;
863 } // end switch of ASCQ for COPY_PROTECTION_FAILURE
864
865 break;
866 }
867
869 {
870 needFurtherInterpret = FALSE;
871
872 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
873 "SenseInfoInterpretByAdditionalSenseCode: Key - Invalid CDB\n"));
874
876 *Retry = FALSE;
877
878 // Note: the retry interval is not typically used.
879 // it is set here only because a ClassErrorHandler
880 // cannot set the RetryIntervalInSeconds, and the error may
881 // require a few commands to be sent to clear whatever
882 // caused this condition (i.e. disk clears the write
883 // cache, requiring at least two commands)
884 //
885 // hopefully, this shortcoming can be changed for blackcomb.
886 *RetryIntervalInSeconds = 3;
887
888 break;
889 }
890
892 {
893 needFurtherInterpret = FALSE;
894 *RetryIntervalInSeconds = 0;
895
896 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
897 "SenseInfoInterpretByAdditionalSenseCode: Media changed\n"));
898
900
901 // special process for Media Change
902 if (IsVolumeMounted(DeviceExtension->DeviceObject))
903 {
904 // Set bit to indicate that media may have changed and volume needs verification.
905 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
906
908 *Retry = FALSE;
909 }
910 else
911 {
913 *Retry = TRUE;
914 }
915 break;
916 }
917
919 {
920 switch (AdditionalSenseCodeQual)
921 {
923 {
924 needFurtherInterpret = FALSE;
925 *RetryIntervalInSeconds = 0;
926
927 InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
928
929 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
930 "SenseInfoInterpretByAdditionalSenseCode: Ejection request received!\n"));
931 //Send eject notification.
932 DeviceSendNotification(DeviceExtension,
933 &GUID_IO_MEDIA_EJECT_REQUEST,
934 0,
935 NULL);
936 // special process for Media Change
937 if (IsVolumeMounted(DeviceExtension->DeviceObject))
938 {
939 // Set bit to indicate that media may have changed and volume needs verification.
940 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
941
943 *Retry = FALSE;
944 }
945 else
946 {
948 *Retry = TRUE;
949 }
950 break;
951 }
952 default:
953 {
954 needFurtherInterpret = TRUE;
955 break;
956 }
957 }
958 break;
959 }
960
962 {
963 needFurtherInterpret = FALSE;
964 *RetryIntervalInSeconds = 5;
965
966 InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
967
968 // Device information has changed, we need to rescan the
969 // bus for changed information such as the capacity.
970 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
971 "SenseInfoInterpretByAdditionalSenseCode: Device information changed. Invalidate the bus\n"));
972
973 IoInvalidateDeviceRelations(DeviceExtension->LowerPdo, BusRelations);
974
975 // special process for Media Change
976 if (IsVolumeMounted(DeviceExtension->DeviceObject))
977 {
978 // Set bit to indicate that media may have changed and volume needs verification.
979 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
980
982 *Retry = FALSE;
983 }
984 else
985 {
987 *Retry = TRUE;
988 }
989 break;
990 } //end Case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
991
992
995 {
996 needFurtherInterpret = FALSE;
997
999 *Retry = FALSE;
1000 LogContext->LogError = TRUE;
1001 LogContext->UniqueErrorValue = 258;
1002 LogContext->ErrorCode = IO_RECOVERED_VIA_ECC;
1003
1004 if (senseBuffer->IncorrectLength)
1005 {
1006 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1007 "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n"));
1009 }
1010 break;
1011 }
1012
1014 {
1015 UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
1016
1017 *((PULONG)wmiEventData) = sizeof(UCHAR);
1018 wmiEventData[sizeof(ULONG)] = AdditionalSenseCodeQual;
1019
1020 needFurtherInterpret = FALSE;
1021
1022 // Don't log another eventlog if we have already logged once
1023 // NOTE: this should have been interlocked, but the structure
1024 // was publicly defined to use a BOOLEAN (char). Since
1025 // media only reports these errors once per X minutes,
1026 // the potential race condition is nearly non-existant.
1027 // the worst case is duplicate log entries, so ignore.
1028
1030 *Retry = FALSE;
1031 LogContext->UniqueErrorValue = 258;
1032 LogContext->LogError = TRUE;
1033 LogContext->ErrorCode = IO_WRN_FAILURE_PREDICTED;
1034
1035 if (senseBuffer->IncorrectLength)
1036 {
1037 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1038 "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n"));
1040 }
1041 break;
1042 }
1043
1044 case 0x57:
1045 {
1046 // UNABLE_TO_RECOVER_TABLE_OF_CONTENTS
1047 // the Matshita CR-585 returns this for all read commands
1048 // on blank CD-R and CD-RW media, and we need to handle
1049 // this for READ_CD detection ability.
1050 switch (AdditionalSenseCodeQual)
1051 {
1052 case 0x00:
1053 {
1054 needFurtherInterpret = FALSE;
1055
1057 *Retry = FALSE;
1058 break;
1059 }
1060 default:
1061 {
1062 needFurtherInterpret = TRUE;
1063 break;
1064 }
1065 }
1066 break;
1067 } //end case Matshita specific error 0x57
1068
1069 default:
1070 {
1071 needFurtherInterpret = TRUE;
1072 break;
1073 }
1074 }
1075
1076 return needFurtherInterpret;
1077}
VOID DeviceSetMediaChangeStateEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:751
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
FORCEINLINE BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
@ MediaPresent
Definition: cdromp.h:82
@ MediaNotPresent
Definition: cdromp.h:83
@ MediaUnavailable
Definition: cdromp.h:84
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
#define SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED
Definition: cdrw_hw.h:1315
#define SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED
Definition: cdrw_hw.h:1324
#define SCSI_SENSEQ_AUTHENTICATION_FAILURE
Definition: cdrw_hw.h:1390
#define SCSI_ADSENSE_REC_DATA_NOECC
Definition: cdrw_hw.h:1211
#define SCSI_ADSENSE_INVALID_LUN
Definition: cdrw_hw.h:1266
#define SCSI_ADSENSE_INVALID_CDB
Definition: cdrw_hw.h:1265
#define SCSI_SENSEQ_KEY_NOT_ESTABLISHED
Definition: cdrw_hw.h:1392
#define SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION
Definition: cdrw_hw.h:1393
struct _SENSE_DATA * PSENSE_DATA
#define SCSI_SENSEQ_UNKNOWN_FORMAT
Definition: cdrw_hw.h:1322
#define SCSI_SENSEQ_CAUSE_NOT_REPORTABLE
Definition: cdrw_hw.h:1312
#define SCSI_SENSEQ_KEY_NOT_PRESENT
Definition: cdrw_hw.h:1391
#define SCSI_ADSENSE_REC_DATA_ECC
Definition: cdrw_hw.h:1212
#define NOT_READY_RETRY_INTERVAL
Definition: cdrw_hw.h:1094
#define SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR
Definition: cdrw_hw.h:1395
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
switch(r->id)
Definition: btrfs.c:3046
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define IO_RECOVERED_VIA_ECC
Definition: ntiologc.h:60
#define IO_ERR_BAD_BLOCK
Definition: ntiologc.h:34
#define STATUS_CLEANER_CARTRIDGE_INSTALLED
Definition: ntstatus.h:218
#define STATUS_CSS_AUTHENTICATION_FAILURE
Definition: ntstatus.h:882
#define STATUS_COPY_PROTECTION_FAILURE
Definition: ntstatus.h:881
#define STATUS_CSS_KEY_NOT_ESTABLISHED
Definition: ntstatus.h:884
#define STATUS_CSS_SCRAMBLED_SECTOR
Definition: ntstatus.h:885
#define STATUS_CSS_KEY_NOT_PRESENT
Definition: ntstatus.h:883
#define STATUS_CSS_RESETS_EXHAUSTED
Definition: ntstatus.h:887
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED
Definition: scsi.h:692
#define SCSI_SESNEQ_COMM_CRC_ERROR
Definition: scsi.h:738
#define SCSI_ADSENSE_LUN_COMMUNICATION
Definition: scsi.h:653
#define SCSI_ADSENSE_NO_SEEK_COMPLETE
Definition: scsi.h:650
#define SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
Definition: scsi.h:684
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
UCHAR IncorrectLength
Definition: cdrw_hw.h:1169
uint32_t * PULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_NONEXISTENT_SECTOR
Definition: udferr_usr.h:143
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
@ BusRelations
Definition: iotypes.h:2152

Referenced by SenseInfoInterpret().

◆ SenseInfoInterpretBySenseKey()

VOID SenseInfoInterpretBySenseKey ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSENSE_DATA  SenseData,
_In_ UCHAR  SenseKey,
_Inout_ NTSTATUS Status,
_Inout_ BOOLEAN Retry,
_Out_ _Deref_out_range_(0, 100) ULONG RetryIntervalInSeconds,
_Inout_ PERROR_LOG_CONTEXT  LogContext 
)

Definition at line 1080 of file sense.c.

1089{
1090 // set default values for retry fields.
1092 *Retry = TRUE;
1093 *RetryIntervalInSeconds = 0;
1094
1095 switch (SenseKey)
1096 {
1098 {
1099 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1100 "SenseInfoInterpretBySenseKey: Key - Not Ready (bad block)\n"));
1101
1103 *Retry = TRUE;
1104
1105 // for unprocessed "not ready" codes, retry the command immediately.
1106 *RetryIntervalInSeconds = 0;
1107 break;
1108 }
1109
1111 {
1112 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1113 "SenseInfoInterpretBySenseKey: Key - Media write protected\n"));
1115 *Retry = FALSE;
1116 break;
1117 }
1118
1120 {
1121 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1122 "SenseInfoInterpretBySenseKey: Key - Medium Error (bad block)\n"));
1123
1125 *Retry = FALSE;
1126 LogContext->LogError = TRUE;
1127 LogContext->UniqueErrorValue = 256;
1128 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
1129
1130 break;
1131 } // end SCSI_SENSE_MEDIUM_ERROR
1132
1134 {
1135 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1136 "SenseInfoInterpretBySenseKey: Key - Hardware error\n"));
1137
1139 *Retry = TRUE;
1140 LogContext->LogError = TRUE;
1141 LogContext->UniqueErrorValue = 257;
1142 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1143
1144 break;
1145 } // end SCSI_SENSE_HARDWARE_ERROR
1146
1148 {
1149 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1150 "SenseInfoInterpretBySenseKey: Key - Illegal SCSI request\n"));
1152 *Retry = FALSE;
1153
1154 break;
1155 } // end SCSI_SENSE_ILLEGAL_REQUEST
1156
1158 {
1159 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1160 "SenseInfoInterpretBySenseKey: Key - Unit Attention\n"));
1161
1162 // A media change may have occured so increment the change
1163 // count for the physical device
1164 InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
1165
1166 if (IsVolumeMounted(DeviceExtension->DeviceObject))
1167 {
1168 // Set bit to indicate that media may have changed
1169 // and volume needs verification.
1170 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
1171
1173 *Retry = FALSE;
1174 }
1175 else
1176 {
1178 *Retry = TRUE;
1179 }
1180
1181 break;
1182
1183 } // end SCSI_SENSE_UNIT_ATTENTION
1184
1186 {
1187 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1188 "SenseInfoInterpretBySenseKey: Command aborted\n"));
1190 *Retry = TRUE;
1191 *RetryIntervalInSeconds = 1;
1192 break;
1193 } // end SCSI_SENSE_ABORTED_COMMAND
1194
1196 {
1197 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1198 "SenseInfoInterpretBySenseKey: Media blank check\n"));
1199 *Retry = FALSE;
1201 break;
1202 } // end SCSI_SENSE_BLANK_CHECK
1203
1205 {
1206 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1207 "SenseInfoInterpretBySenseKey: Recovered error\n"));
1209 *Retry = FALSE;
1210 LogContext->LogError = TRUE;
1211 LogContext->UniqueErrorValue = 258;
1212 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1213
1214 if (SenseData->IncorrectLength)
1215 {
1216 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1217 "SenseInfoInterpretBySenseKey: Incorrect length detected.\n"));
1219 }
1220
1221 break;
1222 } // end SCSI_SENSE_RECOVERED_ERROR
1223
1225 {
1226 // Check other indicators.
1227 if (SenseData->IncorrectLength)
1228 {
1229 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1230 "SenseInfoInterpretBySenseKey: Incorrect length detected.\n"));
1232 *Retry = FALSE;
1233 }
1234 else
1235 {
1236 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1237 "SenseInfoInterpretBySenseKey: No specific sense key\n"));
1239 *Retry = TRUE;
1240 }
1241
1242 break;
1243 } // end SCSI_SENSE_NO_SENSE
1244
1245 default:
1246 {
1247 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1248 "SenseInfoInterpretBySenseKey: Unrecognized sense code\n"));
1250 *Retry = TRUE;
1251 *RetryIntervalInSeconds = 0;
1252
1253 break;
1254 }
1255
1256 } // end switch (SenseKey)
1257
1258 return;
1259}
#define SCSI_SENSE_NO_SENSE
Definition: cdrw_hw.h:1187
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
#define SCSI_SENSE_MEDIUM_ERROR
Definition: cdrw_hw.h:1190
#define SCSI_SENSE_BLANK_CHECK
Definition: cdrw_hw.h:1195
#define SCSI_SENSE_RECOVERED_ERROR
Definition: cdrw_hw.h:1188
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
_In_ UCHAR _Out_opt_ PUCHAR SenseKey
Definition: scsi.h:3745
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131

Referenced by SenseInfoInterpret().

◆ SenseInfoInterpretBySrbStatus()

VOID SenseInfoInterpretBySrbStatus ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  RetriedCount,
_Inout_ NTSTATUS Status,
_Inout_ BOOLEAN Retry,
_Out_ _Deref_out_range_(0, 100) ULONG RetryIntervalInSeconds,
_Inout_ PERROR_LOG_CONTEXT  LogContext 
)

Definition at line 1262 of file sense.c.

1271{
1272 BOOLEAN incrementErrorCount = FALSE;
1273
1274 // set default values for retry fields.
1276 *Retry = TRUE;
1277 *RetryIntervalInSeconds = 0;
1278
1279 switch (SRB_STATUS(Srb->SrbStatus))
1280 {
1284 case SRB_STATUS_NO_HBA:
1286 {
1288 *Retry = FALSE;
1289 break;
1290 }
1291
1293 case SRB_STATUS_TIMEOUT:
1294 {
1295 // Update the error count for the device.
1297 *Retry = TRUE;
1298 *RetryIntervalInSeconds = 0;
1299 incrementErrorCount = TRUE;
1300 break;
1301 }
1302
1303 case SRB_STATUS_ABORTED:
1304 {
1305 // Update the error count for the device.
1307 *Retry = TRUE;
1308 *RetryIntervalInSeconds = 1;
1309 incrementErrorCount = TRUE;
1310 break;
1311 }
1312
1314 {
1316 *Retry = FALSE;
1317 *RetryIntervalInSeconds = 2;
1318 LogContext->LogError = TRUE;
1319 LogContext->ErrorCode = IO_ERR_NOT_READY;
1320 LogContext->UniqueErrorValue = 260;
1321 break;
1322 }
1323
1325 {
1327 *Retry = FALSE;
1328 break;
1329 }
1330
1332 {
1333 // Update the error count for the device.
1334 incrementErrorCount = TRUE;
1336
1337 // If there was phase sequence error then limit the number of retries.
1338 *Retry = (RetriedCount <= 1);
1339
1340 break;
1341 }
1342
1344 {
1345 // If the status needs verification bit is set. Then set
1346 // the status to need verification and no retry; otherwise,
1347 // just retry the request.
1348 if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME))
1349 {
1351 *Retry = FALSE;
1352 }
1353 else
1354 {
1356 *Retry = TRUE;
1357 }
1358
1359 break;
1360 }
1361
1363 {
1365 *Retry = FALSE;
1366 break;
1367 }
1368
1371 // Update the error count for the device and fall through to below
1372 incrementErrorCount = TRUE;
1373
1375 {
1377 *Retry = TRUE;
1378 break;
1379 }
1380
1381 case SRB_STATUS_ERROR:
1382 {
1384 *Retry = TRUE;
1385
1386 if (Srb->ScsiStatus == 0)
1387 {
1388 // This is some strange return code. Update the error
1389 // count for the device.
1390 incrementErrorCount = TRUE;
1391 }
1392
1394 {
1396 }
1397
1398 break;
1399 }
1400
1401 default:
1402 {
1404 *Retry = TRUE;
1405 LogContext->LogError = TRUE;
1406 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1407 LogContext->UniqueErrorValue = 259;
1408 LogContext->ErrorUnhandled = TRUE;
1409 break;
1410 }
1411
1412 } //end of (SRB_STATUS(Srb->SrbStatus))
1413
1414 if (incrementErrorCount)
1415 {
1416 // if any error count occurred, delay the retry of this io by
1417 // at least one second, if caller supports it.
1418 if (*RetryIntervalInSeconds == 0)
1419 {
1420 *RetryIntervalInSeconds = 1;
1421 }
1422
1423 DevicePerfIncrementErrorCount(DeviceExtension);
1424 }
1425
1426 return;
1427}
VOID DevicePerfIncrementErrorCount(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: common.c:1378
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:362
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:361
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE
Definition: srb.h:359
#define SRB_STATUS_NO_HBA
Definition: srb.h:356
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:363
#define SRB_STATUS_UNEXPECTED_BUS_FREE
Definition: srb.h:358
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_ABORTED
Definition: srb.h:342
#define SRB_STATUS_INVALID_PATH_ID
Definition: srb.h:347
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:351
#define SRB_STATUS_PARITY_ERROR
Definition: srb.h:354
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
#define IO_ERR_NOT_READY
Definition: ntiologc.h:42
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163

Referenced by SenseInfoInterpret().

◆ SenseInfoInterpretForZPODD()

BOOLEAN SenseInfoInterpretForZPODD ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_Out_ NTSTATUS Status,
_Out_ _Out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG RetryIntervalIn100ns 
)

Definition at line 2341 of file sense.c.

2372{
2373 BOOLEAN retry = FALSE;
2374 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
2375 ULONG readSector = 0;
2376 PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
2377
2379 *RetryIntervalIn100ns = 0;
2380
2381 if (zpoddInfo->RetryFirstCommand != FALSE)
2382 {
2383 // The first command to the logical unit after power resumed will be terminated
2384 // with CHECK CONDITION Status, 6/29/00 POWER ON, RESET, OR BUS DEVICE RESET OCCURRED
2385
2386 // We have observed some devices return a different sense code, and thus as long as
2387 // the first command after power resume fails, we just retry one more time.
2388 zpoddInfo->RetryFirstCommand = FALSE;
2389
2390 retry = TRUE;
2391 }
2393 (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)))
2394 {
2395 UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f);
2397 UCHAR additionalSenseCodeQual = 0;
2398
2399 // Zero the additional sense code and additional sense code qualifier
2400 // if they were not returned by the device.
2401 readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength);
2402 if (readSector > Srb->SenseInfoBufferLength)
2403 {
2404 readSector = Srb->SenseInfoBufferLength;
2405 }
2406
2408 senseBuffer->AdditionalSenseCode : 0;
2409 additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ?
2410 senseBuffer->AdditionalSenseCodeQualifier : 0;
2411
2412 // If sense code is 2/4/1, device is becoming ready from ZPODD mode. According to Mt Fuji, device
2413 // could take up to 800msec to be fully operational.
2416 (additionalSenseCodeQual == SCSI_SENSEQ_BECOMING_READY))
2417 {
2418 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2419 "SenseInfoInterpretForZPODD: In process of becoming ready\n"));
2420
2421 zpoddInfo->BecomingReadyRetryCount--;
2422
2423 if (zpoddInfo->BecomingReadyRetryCount > 0)
2424 {
2425 DEVICE_EVENT_BECOMING_READY notReady = {0};
2426
2427 retry = TRUE;
2429 *RetryIntervalIn100ns = BECOMING_READY_RETRY_INTERNVAL_IN_100NS;
2430
2431 notReady.Version = 1;
2432 notReady.Reason = 1;
2433 notReady.Estimated100msToReady = (ULONG) *RetryIntervalIn100ns / (1000 * 1000);
2434 DeviceSendNotification(DeviceExtension,
2435 &GUID_IO_DEVICE_BECOMING_READY,
2437 &notReady);
2438 }
2439 }
2440 }
2441
2442 // now, all decisions are made. display trace information.
2443 if (retry)
2444 {
2445 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2446 "Command shall be retried in %2I64d.%03I64d seconds\n",
2447 (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND),
2448 (*RetryIntervalIn100ns / 10000) % 1000
2449 ));
2450 }
2451 else
2452 {
2453 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2454 "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n",
2455 senseBuffer->SenseKey,
2456 senseBuffer->AdditionalSenseCode,
2457 senseBuffer->AdditionalSenseCodeQualifier
2458 ));
2459 }
2460
2461 return retry;
2462
2463} // end SenseInfoInterpret()
#define BECOMING_READY_RETRY_INTERNVAL_IN_100NS
Definition: cdromp.h:262

Referenced by RequestSenseInfoInterpret().

◆ SenseInfoInterpretRefineByIoControl()

VOID SenseInfoInterpretRefineByIoControl ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ ULONG  IoControlCode,
_In_ BOOLEAN  OverrideVerifyVolume,
_Inout_ BOOLEAN Retry,
_Inout_ NTSTATUS Status 
)

Definition at line 1953 of file sense.c.

1985{
1986 PAGED_CODE();
1987
1993 {
1995 {
1997 *Retry = FALSE;
1998 }
1999 }
2000
2002 {
2003 PLAY_ACTIVE(DeviceExtension) = FALSE;
2004 }
2005
2006 // If the status is verified required and the this request
2007 // should bypass verify required then retry the request.
2008 if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED))
2009 {
2010 // note: status gets overwritten here
2012 *Retry = TRUE;
2013
2018 )
2019 {
2020 // Update the geometry information, as the media could have changed.
2021 (VOID) MediaReadCapacity(DeviceExtension->Device);
2022 } // end of ioctls to update capacity
2023 }
2024
2026 {
2027 // If set speed request fails then we should disable the restore speed option.
2028 // Otherwise we will try to restore to default speed on next media change,
2029 // if requested by the caller.
2030 DeviceExtension->DeviceAdditionalData.RestoreDefaults = FALSE;
2031 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "Disable restore default\n"));
2032 }
2033
2034 return;
2035}
#define PAGED_CODE()
#define VOID
Definition: acefi.h:82
#define PLAY_ACTIVE(x)
Definition: cdrom.h:698
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:103
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325

Referenced by SenseInfoInterpret().

◆ SenseInfoInterpretRefineByScsiCommand()

VOID SenseInfoInterpretRefineByScsiCommand ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ ULONG  RetriedCount,
_In_ LONGLONG  Total100nsSinceFirstSend,
_In_ BOOLEAN  OverrideVerifyVolume,
_Inout_ BOOLEAN Retry,
_Inout_ NTSTATUS Status,
_Inout_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG RetryIntervalIn100ns 
)

Definition at line 1663 of file sense.c.

1696{
1697 UCHAR const opCode = Srb->Cdb[0];
1698 CDB const* cdb = (CDB const*)(Srb->Cdb);
1700
1701 if (opCode == SCSIOP_MEDIUM_REMOVAL)
1702 {
1703 if (( cdb->AsByte[1] == 0) &&
1704 ( cdb->AsByte[2] == 0) &&
1705 ( cdb->AsByte[3] == 0) &&
1706 ((cdb->AsByte[4] & 0xFC) == 0)
1707 )
1708 {
1709 // byte[4] == 0x3 or byte[4] == 0x1 == UNLOCK OF MEDIA
1710 if ((cdb->AsByte[4] & 0x01) == 0)
1711 {
1712 if (RetriedCount < TOTAL_COUNT_RETRY_DEFAULT)
1713 {
1714 // keep retrying unlock operation for several times
1715 *Retry = TRUE;
1716 }
1717 }
1718 else // LOCK REQUEST
1719 {
1720 // do not retry LOCK requests more than once (per CLASSPNP code)
1721 if (RetriedCount > TOTAL_COUNT_RETRY_LOCK_MEDIA)
1722 {
1723 *Retry = FALSE;
1724 }
1725 }
1726 }
1727
1728 // want a minimum time to retry of 2 seconds
1729 if ((*Status == STATUS_DEVICE_NOT_READY) &&
1731 {
1732 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1733 }
1735 {
1736 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1737 }
1738 }
1739 else if ((opCode == SCSIOP_MODE_SENSE) || (opCode == SCSIOP_MODE_SENSE10))
1740 {
1741 // want a minimum time to retry of 2 seconds
1742 if ((*Status == STATUS_DEVICE_NOT_READY) &&
1744 {
1745 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1746 }
1748 {
1749 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1750 }
1751
1752 // Want to ignore a STATUS_VERIFY_REQUIRED error because it either
1753 // doesn't make sense or is required to satisfy the VERIFY.
1755 {
1756 *Retry = TRUE;
1757 }
1759 {
1760 /*
1761 * This is a HACK.
1762 * Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
1763 * underrun (i.e. success, and the buffer is longer than needed).
1764 * So treat this as a success.
1765 * When the caller of this function sees that the status was changed to success,
1766 * it will add the transferred length to the original irp.
1767 */
1769 *Retry = FALSE;
1770 }
1771
1772 // limit the count of retries
1773 if (RetriedCount > TOTAL_COUNT_RETRY_MODESENSE)
1774 {
1775 *Retry = FALSE;
1776 }
1777 }
1778 else if ((opCode == SCSIOP_READ_CAPACITY) || (opCode == SCSIOP_READ_CAPACITY16))
1779 {
1780 // Want to ignore a STATUS_VERIFY_REQUIRED error because it either
1781 // doesn't make sense or is required to satisfy the VERIFY.
1783 {
1784 *Retry = TRUE;
1785 }
1786
1787 if (RetriedCount > TOTAL_COUNT_RETRY_READ_CAPACITY)
1788 {
1789 *Retry = FALSE;
1790 }
1791 }
1792 else if ((opCode == SCSIOP_RESERVE_UNIT) || (opCode == SCSIOP_RELEASE_UNIT))
1793 {
1794 // The RESERVE(6) / RELEASE(6) commands are optional.
1795 // So if they aren't supported, try the 10-byte equivalents
1797 {
1798 PCDB tempCdb = (PCDB)Srb->Cdb;
1799
1800 Srb->CdbLength = 10;
1801 tempCdb->CDB10.OperationCode = (tempCdb->CDB6GENERIC.OperationCode == SCSIOP_RESERVE_UNIT)
1804
1805 SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6);
1806 *Retry = TRUE;
1807 }
1808 }
1809 else if (IS_SCSIOP_READWRITE(opCode))
1810 {
1811 // Retry if still verifying a (possibly) reloaded disk/cdrom.
1812 if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED))
1813 {
1815 *Retry = TRUE;
1816 }
1817
1818 // Special case for streaming READ/WRITE commands
1819 if (((opCode == SCSIOP_READ12) && (cdb->READ12.Streaming == 1)) ||
1820 ((opCode == SCSIOP_WRITE12) && (cdb->WRITE12.Streaming == 1)))
1821 {
1822 // We've got a failure while performing a streaming operation and now need to guess if
1823 // it's likely to be a permanent error because the drive does not support streaming at all
1824 // (in which case we're going to fall back to normal reads/writes), or a transient error
1825 // (in which case we quickly fail the request but contrinue to use streaming).
1826 //
1827 // We analyze the sense information to make that decision. Bus resets and device timeouts
1828 // are treated as permanent errors, because some non-compliant devices may even hang when
1829 // they get a command that they do not expect.
1830
1831 BOOLEAN disableStreaming = FALSE;
1832
1837 {
1838 disableStreaming = TRUE;
1839 }
1840 else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_UNIT_ATTENTION)
1841 {
1842 if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET ||
1844 {
1845 disableStreaming = TRUE;
1846 }
1847 }
1848 else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_ILLEGAL_REQUEST)
1849 {
1850 // LBA Out of Range is an exception, as it's more likely to be caused by
1851 // upper layers attempting to read/write a wrong LBA.
1853 {
1854 disableStreaming = TRUE;
1855 }
1856 }
1857
1858 if (disableStreaming)
1859 {
1860 // if the failure looks permanent, we disable streaming for all future reads/writes
1861 // and retry the command immediately
1862 SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_STREAMING);
1863 *Retry = TRUE;
1864 *RetryIntervalIn100ns = 0;
1865 }
1866 else
1867 {
1868 // if the failure looks transient, we simply fail the current request without retries
1869 // to minimize the time of processing
1870 *Retry = FALSE;
1871 }
1872 }
1873
1874 // Special-case handling of READ/WRITE commands. These commands now have a 120 second timeout,
1875 // but the preferred behavior (and that taken by many drives) is to immediately report 2/4/x
1876 // on OPC and similar commands. Thus, retries must occur for at least 160 seconds
1877 // (120 seconds + four 10 second retries) as a conservative guess.
1878 // Note: 160s retry time is also a result of discussion with OEMs for case of 2/4/7 and 2/4/8.
1879 if (*Retry)
1880 {
1881 if ((Total100nsSinceFirstSend < 0) ||
1882 (((senseBuffer->SenseKey &0xf) == SCSI_SENSE_HARDWARE_ERROR) && (senseBuffer->AdditionalSenseCode == 0x09)))
1883 {
1884 // time information is not valid. use default retry count.
1885 // or if it's SERVO FAILURE, use retry count instead of 160s retry.
1886 *Retry = (RetriedCount <= TOTAL_COUNT_RETRY_DEFAULT);
1887 }
1888 else if (Total100nsSinceFirstSend > SECONDS_TO_100NS_UNITS(TOTAL_SECONDS_RETRY_TIME_WRITE))
1889 {
1890 *Retry = FALSE;
1891 }
1892
1893 // How long should we request a delay for during writing? This depends entirely on
1894 // the current write speed of the drive. If we request retries too quickly,
1895 // we can overload the processor on the drive (resulting in garbage being written),
1896 // but too slowly results in lesser performance.
1897 //
1898 *RetryIntervalIn100ns = DeviceExtension->DeviceAdditionalData.ReadWriteRetryDelay100nsUnits;
1899
1900 } // end retry for 160 seconds modification
1901 }
1902 else if (opCode == SCSIOP_GET_PERFORMANCE)
1903 {
1905 {
1906 // This is a HACK.
1907 // Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
1908 // underrun (i.e. success, and the buffer is longer than needed).
1909 // So treat this as a success.
1910 // When the caller of this function sees that the status was changed to success,
1911 // it will add the transferred length to the original irp.
1913 *Retry = FALSE;
1914 }
1915
1918 {
1919 // If get configuration command is failing and if the request type is TYPE ONE
1920 // then most likely the device does not support this request type. Set the
1921 // flag so that the TYPE ONE requests will be tried as TYPE ALL requets.
1924 (((PCDB)Srb->Cdb)->GET_CONFIGURATION.RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE))
1925 {
1926
1927 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1928 "TYPE ONE GetConfiguration failed. Set hack flag and retry.\n"));
1929 SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG);
1930 *Retry = TRUE;
1931 }
1932 }
1933
1934 // limit retries to GET_PERFORMANCE commands to default retry count
1935 if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT)
1936 {
1937 *Retry = FALSE;
1938 }
1939 }
1940 else // default handler -- checks for retry count only.
1941 {
1942 if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT)
1943 {
1944 *Retry = FALSE;
1945 }
1946 }
1947
1948 return;
1949}
#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG
Definition: cdrom.h:99
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
#define FDO_HACK_NO_STREAMING
Definition: cdromp.h:137
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSIOP_RELEASE_UNIT
Definition: cdrw_hw.h:893
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define SCSIOP_GET_PERFORMANCE
Definition: cdrw_hw.h:959
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE
Definition: ntddmmc.h:17
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
#define SCSI_ADSENSE_INSUFFICIENT_TIME_FOR_OPERATION
Definition: scsi.h:677
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
#define TOTAL_SECONDS_RETRY_TIME_WRITE
Definition: sense.c:75
#define TOTAL_COUNT_RETRY_READ_CAPACITY
Definition: sense.c:72
#define TOTAL_COUNT_RETRY_MODESENSE
Definition: sense.c:71
#define TOTAL_COUNT_RETRY_DEFAULT
Definition: sense.c:69
#define TOTAL_COUNT_RETRY_LOCK_MEDIA
Definition: sense.c:70
UCHAR CdbLength
Definition: srb.h:258
#define max(a, b)
Definition: svc.c:63
struct _CDB::_CDB10 CDB10
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_READ12 READ12
struct _CDB::_WRITE12 WRITE12

Referenced by SenseInfoInterpret().

◆ SenseInfoLogError()

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 
)

Definition at line 1430 of file sense.c.

1440{
1441 // Always log the error in our internal log.
1442 // If logError is set, also log the error in the system log.
1444 ULONG totalSize = 0;
1445 ULONG senseBufferSize = 0;
1446 IO_ERROR_LOG_PACKET staticErrLogEntry = {0};
1447 CDROM_ERROR_LOG_DATA staticErrLogData = {0};
1448
1449 // Calculate the total size of the error log entry.
1450 // add to totalSize in the order that they are used.
1451 // the advantage to calculating all the sizes here is
1452 // that we don't have to do a bunch of extraneous checks
1453 // later on in this code path.
1454 totalSize = sizeof(IO_ERROR_LOG_PACKET) // required
1455 + sizeof(CDROM_ERROR_LOG_DATA); // struct for ease
1456
1457 // also save any available extra sense data, up to the maximum errlog
1458 // packet size . WMI should be used for real-time analysis.
1459 // the event log should only be used for post-mortem debugging.
1461 {
1462 ULONG validSenseBytes;
1464
1465 // make sure we can at least access the AdditionalSenseLength field
1466 validSense = RTL_CONTAINS_FIELD(senseBuffer,
1468 AdditionalSenseLength);
1469 if (validSense)
1470 {
1471 // if extra info exists, copy the maximum amount of available
1472 // sense data that is safe into the the errlog.
1473 validSenseBytes = senseBuffer->AdditionalSenseLength
1474 + offsetof(SENSE_DATA, AdditionalSenseLength);
1475
1476 // this is invalid because it causes overflow!
1477 // whoever sent this type of request would cause
1478 // a system crash.
1479 NT_ASSERT(validSenseBytes < MAX_ADDITIONAL_SENSE_BYTES);
1480
1481 // set to save the most sense buffer possible
1482 senseBufferSize = max(validSenseBytes, sizeof(SENSE_DATA));
1483 senseBufferSize = min(senseBufferSize, Srb->SenseInfoBufferLength);
1484 }
1485 else
1486 {
1487 // it's smaller than required to read the total number of
1488 // valid bytes, so just use the SenseInfoBufferLength field.
1489 senseBufferSize = Srb->SenseInfoBufferLength;
1490 }
1491
1492 // Bump totalSize by the number of extra senseBuffer bytes
1493 // (beyond the default sense buffer within CDROM_ERROR_LOG_DATA).
1494 // Make sure to never allocate more than ERROR_LOG_MAXIMUM_SIZE.
1495 if (senseBufferSize > sizeof(SENSE_DATA))
1496 {
1497 totalSize += senseBufferSize-sizeof(SENSE_DATA);
1498 if (totalSize > ERROR_LOG_MAXIMUM_SIZE)
1499 {
1500 senseBufferSize -= totalSize-ERROR_LOG_MAXIMUM_SIZE;
1501 totalSize = ERROR_LOG_MAXIMUM_SIZE;
1502 }
1503 }
1504 }
1505
1506 // If we've used up all of our retry attempts, set the final status to
1507 // reflect the appropriate result.
1508 //
1509 // ISSUE: the test below should also check RetriedCount to determine if we will actually retry,
1510 // but there is no easy test because we'd have to consider the original retry count
1511 // for the op; besides, InterpretTransferPacketError sometimes ignores the retry
1512 // decision returned by this function. So just ErrorRetried to be true in the majority case.
1513 //
1514 if (*Retry)
1515 {
1516 staticErrLogEntry.FinalStatus = STATUS_SUCCESS;
1517 staticErrLogData.ErrorRetried = TRUE;
1518 }
1519 else
1520 {
1521 staticErrLogEntry.FinalStatus = *Status;
1522 }
1523
1524 // Don't log generic IO_WARNING_PAGING_FAILURE message if either the
1525 // I/O is retried, or it completed successfully.
1526 if ((LogContext->ErrorCode == IO_WARNING_PAGING_FAILURE) &&
1527 (*Retry || NT_SUCCESS(*Status)) )
1528 {
1529 LogContext->LogError = FALSE;
1530 }
1531
1533 {
1534 staticErrLogData.ErrorPaging = TRUE;
1535 }
1536
1537 staticErrLogData.ErrorUnhandled = LogContext->ErrorUnhandled;
1538
1539 // Calculate the device offset if there is a geometry.
1540 staticErrLogEntry.DeviceOffset.QuadPart = (LONGLONG)LogContext->BadSector;
1541 staticErrLogEntry.DeviceOffset.QuadPart *= (LONGLONG)DeviceExtension->DiskGeometry.BytesPerSector;
1542
1543 if (LogContext->ErrorCode == -1)
1544 {
1545 staticErrLogEntry.ErrorCode = STATUS_IO_DEVICE_ERROR;
1546 }
1547 else
1548 {
1549 staticErrLogEntry.ErrorCode = LogContext->ErrorCode;
1550 }
1551
1552 // The dump data follows the IO_ERROR_LOG_PACKET
1553 staticErrLogEntry.DumpDataSize = (USHORT)totalSize - sizeof(IO_ERROR_LOG_PACKET);
1554
1555 staticErrLogEntry.SequenceNumber = 0;
1556 staticErrLogEntry.MajorFunctionCode = MajorFunctionCode;
1557 staticErrLogEntry.IoControlCode = IoControlCode;
1558 staticErrLogEntry.RetryCount = (UCHAR)RetriedCount;
1559 staticErrLogEntry.UniqueErrorValue = LogContext->UniqueErrorValue;
1560
1561 KeQueryTickCount(&staticErrLogData.TickCount);
1562 staticErrLogData.PortNumber = (ULONG)-1;
1563
1564 // Save the entire contents of the SRB.
1565 staticErrLogData.Srb = *Srb;
1566
1567 // For our private log, save just the default length of the SENSE_DATA.
1568 if (senseBufferSize != 0)
1569 {
1570 RtlCopyMemory(&staticErrLogData.SenseData, senseBuffer, min(senseBufferSize, sizeof(SENSE_DATA)));
1571 }
1572
1573 // Save the error log in our context.
1574 // We only save the default sense buffer length.
1575 {
1576 KIRQL oldIrql;
1577 KeAcquireSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, &oldIrql);
1578 DeviceExtension->PrivateFdoData->ErrorLogs[DeviceExtension->PrivateFdoData->ErrorLogNextIndex] = staticErrLogData;
1579 DeviceExtension->PrivateFdoData->ErrorLogNextIndex++;
1580 DeviceExtension->PrivateFdoData->ErrorLogNextIndex %= NUM_ERROR_LOG_ENTRIES;
1581 KeReleaseSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, oldIrql);
1582 }
1583
1584 // If logError is set, also save this log in the system's error log.
1585 // But make sure we don't log TUR failures over and over
1586 // (e.g. if an external drive was switched off and we're still sending TUR's to it every second).
1587 if (LogContext->LogError)
1588 {
1589 // We do not want to log certain system events repetitively
1590 switch (((PCDB)Srb->Cdb)->CDB10.OperationCode)
1591 {
1593 {
1594 if (DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO)
1595 {
1596 LogContext->LogError = FALSE;
1597 }
1598 else
1599 {
1600 DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO = TRUE;
1601 }
1602
1603 break;
1604 }
1605
1607 {
1608 if (DeviceExtension->PrivateFdoData->LoggedSYNCFailure)
1609 {
1610 LogContext->LogError = FALSE;
1611 }
1612 else
1613 {
1614 DeviceExtension->PrivateFdoData->LoggedSYNCFailure = TRUE;
1615 }
1616
1617 break;
1618 }
1619 }
1620
1621 // Do not log 5/21/00 LOGICAL BLOCK ADDRESS OUT OF RANGE if the disc is blank,
1622 // it is known to litter the Event Log with repetitive errors
1623 // Do not log this error for READ, as it's known that File System mount process reads different sectors from media.
1625 senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST &&
1626 senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK &&
1627 senseBuffer->AdditionalSenseCodeQualifier == 0 &&
1628 IS_SCSIOP_READ(((PCDB)Srb->Cdb)->CDB10.OperationCode))
1629 {
1630 LogContext->LogError = FALSE;
1631 }
1632 }
1633
1634 // Write the error log packet to the system error logging thread.
1635 if (LogContext->LogError)
1636 {
1637 PIO_ERROR_LOG_PACKET errorLogEntry;
1638 PCDROM_ERROR_LOG_DATA errlogData;
1639
1640 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DeviceExtension->DeviceObject, (UCHAR)totalSize);
1641 if (errorLogEntry)
1642 {
1643 errlogData = (PCDROM_ERROR_LOG_DATA)errorLogEntry->DumpData;
1644
1645 *errorLogEntry = staticErrLogEntry;
1646 *errlogData = staticErrLogData;
1647
1648 // For the system log, copy as much of the sense buffer as possible.
1649 if (senseBufferSize != 0)
1650 {
1651 RtlCopyMemory(&errlogData->SenseData, senseBuffer, senseBufferSize);
1652 }
1653
1654 // errorLogEntry - It will be freed by the kernel.
1655 IoWriteErrorLogEntry(errorLogEntry);
1656 }
1657 }
1658
1659 return;
1660}
#define IS_SCSIOP_READ(opCode)
Definition: cdrom.h:791
struct _CDROM_ERROR_LOG_DATA * PCDROM_ERROR_LOG_DATA
#define NUM_ERROR_LOG_ENTRIES
Definition: cdromp.h:323
struct _SENSE_DATA SENSE_DATA
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:484
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define min(a, b)
Definition: monoChain.cc:55
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:675
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
unsigned short USHORT
Definition: pedump.c:61
#define MAX_ADDITIONAL_SENSE_BYTES
Definition: scsi.h:600
BOOLEAN validSense
Definition: scsi.h:4018
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
LARGE_INTEGER TickCount
Definition: cdromp.h:303
SCSI_REQUEST_BLOCK Srb
Definition: cdromp.h:313
SENSE_DATA SenseData
Definition: cdromp.h:319
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2042
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET

Referenced by SenseInfoInterpret().

◆ SenseInfoRequestGetInformation()

VOID SenseInfoRequestGetInformation ( _In_ WDFREQUEST  Request,
_Out_ UCHAR MajorFunctionCode,
_Out_ ULONG IoControlCode,
_Out_ BOOLEAN OverrideVerifyVolume,
_Out_ ULONGLONG Total100nsSinceFirstSend 
)

Definition at line 426 of file sense.c.

433{
434 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
435
437 *IoControlCode = 0;
438 *OverrideVerifyVolume = FALSE;
439 *Total100nsSinceFirstSend = 0;
440
441 if (requestContext->OriginalRequest != NULL)
442 {
443 PIO_STACK_LOCATION originalIrpStack = NULL;
444
445 PIRP originalIrp = WdfRequestWdmGetIrp(requestContext->OriginalRequest);
446
447 if (originalIrp != NULL)
448 {
449 originalIrpStack = IoGetCurrentIrpStackLocation(originalIrp);
450 }
451
452 if (originalIrpStack != NULL)
453 {
454 *MajorFunctionCode = originalIrpStack->MajorFunction;
455
457 {
458 *IoControlCode = originalIrpStack->Parameters.DeviceIoControl.IoControlCode;
459 }
460
461 *OverrideVerifyVolume = TEST_FLAG(originalIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);
462 }
463 }
464
465 // Calculate time past since the request was first time sent.
466 if (requestContext->TimeSentDownFirstTime.QuadPart > 0)
467 {
468 LARGE_INTEGER tmp;
469 KeQueryTickCount(&tmp);
470 tmp.QuadPart -= requestContext->TimeSentDownFirstTime.QuadPart;
472 *Total100nsSinceFirstSend = tmp.QuadPart;
473 }
474 else
475 {
476 // set to -1 if field TimeSentDownFirstTime not set.
477 *Total100nsSinceFirstSend = (ULONGLONG) -1;
478 }
479
480 return;
481}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
LARGE_INTEGER TimeSentDownFirstTime
Definition: cdrom.h:636
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
union _IO_STACK_LOCATION::@1564 Parameters
LONGLONG QuadPart
Definition: typedefs.h:114
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823

Referenced by SenseInfoInterpret().