ReactOS  0.4.15-dev-1374-g8d3e80e
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 
397  if (!TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
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 }
UCHAR SenseKey
Definition: cdrw_hw.h:1167
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
VOID DeviceSendStartUnit(_In_ WDFDEVICE Device)
Definition: common.c:877
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
Status
Definition: gdiplustypes.h:24
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define STATUS_SUCCESS
Definition: shellext.h:65
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

◆ 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 
134  case SCSI_SENSE_NOT_READY:
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) ||
168  (Srb->Cdb[0] == SCSIOP_READ_TRACK_INFORMATION) ||
169  (Srb->Cdb[0] == SCSIOP_READ_DISK_INFORMATION)
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  {
274  if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_WRITE_PROTECT)
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 }
#define SCSIOP_READ_TOC
Definition: cdrw_hw.h:927
#define SCSI_ADSENSE_WRITE_PROTECT
Definition: cdrw_hw.h:1268
UCHAR SenseKey
Definition: cdrw_hw.h:1167
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
#define SCSI_SENSEQ_INCOMPATIBLE_FORMAT
Definition: cdrw_hw.h:1323
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
#define SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define SCSIOP_SEND_KEY
Definition: cdrw_hw.h:951
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
struct _CDB::_CDB16 CDB16
struct _CDB::_SEND_KEY SEND_KEY
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
#define FALSE
Definition: types.h:117
#define SCSIOP_READ_CD_MSF
Definition: cdrw_hw.h:964
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define SCSIOP_READ6
Definition: cdrw_hw.h:874
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
unsigned char BOOLEAN
union _CDB * PCDB
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
Status
Definition: gdiplustypes.h:24
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SCSIOP_READ_TRACK_INFORMATION
Definition: scsi.h:315
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SCSIOP_READ_DISK_INFORMATION
Definition: scsi.h:313
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
WDFOBJECT ParentObject
Definition: wdfobject.h:130
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
#define SCSI_SENSEQ_WRITE_PROTECT_ENABLE
Definition: scsi.h:880
#define SCSIOP_READ_CD
Definition: cdrw_hw.h:967
#define STATUS_SUCCESS
Definition: shellext.h:65
EVT_WDF_WORKITEM DeviceRestoreDefaultSpeed
Definition: cdrom.h:1180
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
#define SCSI_SENSEQ_WRITE_PROTECT_DISABLE
Definition: scsi.h:881
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
Definition: ps.c:97

◆ 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 
2505  if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
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.
2522  if (Srb->SrbStatus & SRB_STATUS_QUEUE_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 }
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define SRB_STATUS(Status)
Definition: srb.h:381
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
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
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
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
VOID DeviceReleaseQueue(_In_ WDFDEVICE Device)
Definition: common.c:1179
#define NULL
Definition: types.h:112
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define STATUS_SUCCESS
Definition: shellext.h:65
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49

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 }
Status
Definition: gdiplustypes.h:24
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:3312

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 
2099  if(TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING))
2100  {
2101  // Log anything remotely incorrect about paging i/o
2102  logContext.LogError = TRUE;
2103  logContext.UniqueErrorValue = 301;
2104  logContext.ErrorCode = IO_WARNING_PAGING_FAILURE;
2105  }
2106 
2107  // must handle the SRB_STATUS_INTERNAL_ERROR case first,
2108  // as it has all the flags set.
2109  if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_INTERNAL_ERROR)
2110  {
2111  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
2112  "SenseInfoInterpret: Internal Error code is %x\n",
2113  Srb->InternalStatus));
2114 
2115  retry = FALSE;
2116  *Status = Srb->InternalStatus;
2117  }
2118  else if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT)
2119  {
2120  retry = FALSE;
2122  logContext.LogError = FALSE;
2123  }
2124  else if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
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],
2151  SRB_STATUS(Srb->SrbStatus),
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],
2242  SRB_STATUS(Srb->SrbStatus),
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
2266  SenseInfoInterpretRefineByScsiCommand(DeviceExtension,
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  {
2278  SenseInfoInterpretRefineByIoControl(DeviceExtension,
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()
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
UCHAR AdditionalSenseCode
Definition: cdromp.h:280
UCHAR SenseKey
Definition: cdrw_hw.h:1167
NTSTATUS ErrorCode
Definition: sense.c:81
UCHAR AdditionalSenseCodeQualifier
Definition: cdromp.h:281
UCHAR senseKey
Definition: scsi.h:4019
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
Definition: cdrw_hw.h:28
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
ULONG BadSector
Definition: sense.c:83
#define SRB_STATUS(Status)
Definition: srb.h:381
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
VOID SenseInfoRequestGetInformation(_In_ WDFREQUEST Request, _Out_ UCHAR *MajorFunctionCode, _Out_ ULONG *IoControlCode, _Out_ BOOLEAN *OverrideVerifyVolume, _Out_ ULONGLONG *Total100nsSinceFirstSend)
Definition: sense.c:426
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define offsetof(TYPE, MEMBER)
union _CDB * PCDB
ULONG UniqueErrorValue
Definition: sense.c:82
GLuint index
Definition: glext.h:6031
UCHAR Information[4]
Definition: cdrw_hw.h:1172
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCodeQualifier
Definition: scsi.h:3748
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
UCHAR additionalSenseCode
Definition: scsi.h:4020
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
Status
Definition: gdiplustypes.h:24
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
#define SCSIOP_VERIFY16
Definition: scsi.h:916
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define SCSISTAT_RESERVATION_CONFLICT
Definition: cdrw_hw.h:1084
BOOLEAN LogError
Definition: sense.c:79
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
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
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
unsigned char UCHAR
Definition: xmlstorage.h:181
#define index(s, c)
Definition: various.h:29
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:365
VOID SenseInfoInterpretRefineByIoControl(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status)
Definition: sense.c:1953
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
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
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCode
Definition: scsi.h:3744
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
#define InterlockedIncrement
Definition: armddk.h:53
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
#define UNIT_100NS_PER_SECOND
Definition: cdrom.h:1487
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
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
#define NULL
Definition: types.h:112
#define SECONDS_TO_100NS_UNITS(x)
Definition: cdrom.h:1488
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
signed int * PLONG
Definition: retypes.h:5
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52

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;
502  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
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 
899  DeviceSetMediaChangeStateEx(DeviceExtension, MediaPresent, NULL);
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 }
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
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 SCSI_SENSEQ_INCOMPATIBLE_FORMAT
Definition: cdrw_hw.h:1323
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
#define TRUE
Definition: types.h:120
#define SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
#define SCSI_SESNEQ_COMM_CRC_ERROR
Definition: scsi.h:738
__inline BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#define SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION
Definition: cdrw_hw.h:1393
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define STATUS_CSS_KEY_NOT_ESTABLISHED
Definition: ntstatus.h:884
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
#define STATUS_NONEXISTENT_SECTOR
Definition: udferr_usr.h:143
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define SCSI_ADSENSE_REC_DATA_NOECC
Definition: cdrw_hw.h:1211
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
#define SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED
Definition: cdrw_hw.h:1315
#define FALSE
Definition: types.h:117
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
unsigned char BOOLEAN
#define NOT_READY_RETRY_INTERVAL
Definition: cdrw_hw.h:1094
#define STATUS_CSS_RESETS_EXHAUSTED
Definition: ntstatus.h:887
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
VOID DeviceSendStartUnit(_In_ WDFDEVICE Device)
Definition: common.c:877
switch(r->id)
Definition: btrfs.c:2980
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
Status
Definition: gdiplustypes.h:24
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
#define SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED
Definition: scsi.h:692
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define SCSI_ADSENSE_NO_SEEK_COMPLETE
Definition: scsi.h:650
#define SCSI_ADSENSE_LUN_COMMUNICATION
Definition: scsi.h:653
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define SCSI_ADSENSE_REC_DATA_ECC
Definition: cdrw_hw.h:1212
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
Definition: scsi.h:684
#define SCSI_SENSEQ_KEY_NOT_ESTABLISHED
Definition: cdrw_hw.h:1392
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SCSI_SENSEQ_UNKNOWN_FORMAT
Definition: cdrw_hw.h:1322
#define SCSI_SENSEQ_KEY_NOT_PRESENT
Definition: cdrw_hw.h:1391
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define SCSI_SENSEQ_CAUSE_NOT_REPORTABLE
Definition: cdrw_hw.h:1312
#define IO_ERR_BAD_BLOCK
Definition: ntiologc.h:34
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED
Definition: cdrw_hw.h:1324
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCode
Definition: scsi.h:3744
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:2486
#define InterlockedIncrement
Definition: armddk.h:53
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
UCHAR IncorrectLength
Definition: cdrw_hw.h:1169
#define STATUS_CSS_SCRAMBLED_SECTOR
Definition: ntstatus.h:885
#define SCSI_SENSEQ_AUTHENTICATION_FAILURE
Definition: cdrw_hw.h:1390
struct _SENSE_DATA * PSENSE_DATA
#define SCSI_ADSENSE_INVALID_LUN
Definition: cdrw_hw.h:1266
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_CSS_AUTHENTICATION_FAILURE
Definition: ntstatus.h:882
#define STATUS_SUCCESS
Definition: shellext.h:65
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
signed int * PLONG
Definition: retypes.h:5
#define STATUS_CSS_KEY_NOT_PRESENT
Definition: ntstatus.h:883
#define STATUS_COPY_PROTECTION_FAILURE
Definition: ntstatus.h:881
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define SCSI_ADSENSE_INVALID_CDB
Definition: cdrw_hw.h:1265
#define SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR
Definition: cdrw_hw.h:1395
#define IO_RECOVERED_VIA_ECC
Definition: ntiologc.h:60
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
#define STATUS_CLEANER_CARTRIDGE_INSTALLED
Definition: ntstatus.h:218

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  {
1097  case SCSI_SENSE_NOT_READY:
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 
1224  case SCSI_SENSE_NO_SENSE:
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 TRUE
Definition: types.h:120
__inline BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define SCSI_SENSE_MEDIUM_ERROR
Definition: cdrw_hw.h:1190
#define FALSE
Definition: types.h:117
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
Status
Definition: gdiplustypes.h:24
#define SCSI_SENSE_BLANK_CHECK
Definition: cdrw_hw.h:1195
_In_ UCHAR _Out_opt_ PUCHAR SenseKey
Definition: scsi.h:3744
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define SCSI_SENSE_RECOVERED_ERROR
Definition: cdrw_hw.h:1188
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131
#define SCSI_SENSE_NO_SENSE
Definition: cdrw_hw.h:1187
#define IO_ERR_BAD_BLOCK
Definition: ntiologc.h:34
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define InterlockedIncrement
Definition: armddk.h:53
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
#define STATUS_SUCCESS
Definition: shellext.h:65
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
signed int * PLONG
Definition: retypes.h:5
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

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  {
1283  case SRB_STATUS_NO_DEVICE:
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 
1374  case SRB_STATUS_BUS_RESET:
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 
1393  if (Srb->ScsiStatus == SCSISTAT_BUSY)
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 }
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:338
#define SRB_STATUS_BUS_RESET
Definition: srb.h:345
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define TRUE
Definition: types.h:120
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:353
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:343
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:340
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE
Definition: srb.h:351
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:355
#define SRB_STATUS(Status)
Definition: srb.h:381
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define SRB_STATUS_ERROR
Definition: srb.h:336
#define SRB_STATUS_PARITY_ERROR
Definition: srb.h:346
#define FALSE
Definition: types.h:117
VOID DevicePerfIncrementErrorCount(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: common.c:1378
unsigned char BOOLEAN
#define SRB_STATUS_NO_HBA
Definition: srb.h:348
#define SRB_STATUS_ABORTED
Definition: srb.h:334
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
Status
Definition: gdiplustypes.h:24
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:349
#define IO_ERR_NOT_READY
Definition: ntiologc.h:42
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:342
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:354
#define SRB_STATUS_TIMEOUT
Definition: srb.h:341
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define SRB_STATUS_UNEXPECTED_BUS_FREE
Definition: srb.h:350
#define SRB_STATUS_INVALID_PATH_ID
Definition: srb.h:339
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

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  }
2392  else if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
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()
UCHAR SenseKey
Definition: cdrw_hw.h:1167
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
UCHAR senseKey
Definition: scsi.h:4019
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define offsetof(TYPE, MEMBER)
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCodeQualifier
Definition: scsi.h:3748
UCHAR additionalSenseCode
Definition: scsi.h:4020
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
Status
Definition: gdiplustypes.h:24
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define BECOMING_READY_RETRY_INTERNVAL_IN_100NS
Definition: cdromp.h:262
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
unsigned char UCHAR
Definition: xmlstorage.h:181
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCode
Definition: scsi.h:3744
#define UNIT_100NS_PER_SECOND
Definition: cdrom.h:1487
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
unsigned int ULONG
Definition: retypes.h:1
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

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  {
1994  if (*Status == STATUS_DATA_OVERRUN)
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 STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define TRUE
Definition: types.h:120
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:103
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define FALSE
Definition: types.h:117
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
Status
Definition: gdiplustypes.h:24
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define VOID
Definition: acefi.h:82
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:318
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
#define PLAY_ACTIVE(DeviceExtension)
Definition: cdrom.c:190
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
#define STATUS_SUCCESS
Definition: shellext.h:65
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
#define PAGED_CODE()

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);
1699  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
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  }
1734  else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)
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  }
1747  else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)
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  }
1758  else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)
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 
1833  if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_TIMEOUT ||
1834  SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_COMMAND_TIMEOUT ||
1835  SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT ||
1836  SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_BUS_RESET)
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.
1852  if (senseBuffer->AdditionalSenseCode != SCSI_ADSENSE_ILLEGAL_BLOCK)
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  {
1904  if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)
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 
1916  if ((Srb->SenseInfoBufferLength < RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA,AdditionalSenseCodeQualifier)) ||
1917  !TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
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.
1922  if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
1923  (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_DATA_OVERRUN) &&
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 SRB_STATUS_BUS_RESET
Definition: srb.h:345
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
#define TOTAL_COUNT_RETRY_LOCK_MEDIA
Definition: sense.c:70
UCHAR SenseKey
Definition: cdrw_hw.h:1167
#define max(a, b)
Definition: svc.c:63
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
#define TOTAL_COUNT_RETRY_READ_CAPACITY
Definition: sense.c:72
#define SCSIOP_RELEASE_UNIT
Definition: cdrw_hw.h:893
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define TOTAL_COUNT_RETRY_MODESENSE
Definition: sense.c:71
Definition: cdrw_hw.h:28
struct _CDB::_READ12 READ12
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:343
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
struct _CDB::_WRITE12 WRITE12
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
struct _CDB::_CDB10 CDB10
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define SRB_STATUS(Status)
Definition: srb.h:381
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
union _CDB * PCDB
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCodeQualifier
Definition: scsi.h:3748
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
Status
Definition: gdiplustypes.h:24
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:349
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:342
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE
Definition: ntddmmc.h:17
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define SCSI_ADSENSE_INSUFFICIENT_TIME_FOR_OPERATION
Definition: scsi.h:677
#define TOTAL_COUNT_RETRY_DEFAULT
Definition: sense.c:69
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
#define SRB_STATUS_TIMEOUT
Definition: srb.h:341
#define TOTAL_SECONDS_RETRY_TIME_WRITE
Definition: sense.c:75
struct _CDB::_CDB6GENERIC CDB6GENERIC
#define SECONDS_TO_100NS_UNITS(x)
Definition: cdrom.h:1488
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define FDO_HACK_NO_STREAMING
Definition: cdromp.h:137
struct _SENSE_DATA * PSENSE_DATA
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG
Definition: cdrom.h:99
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define STATUS_SUCCESS
Definition: shellext.h:65
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
#define SCSIOP_GET_PERFORMANCE
Definition: cdrw_hw.h:959
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
UCHAR AsByte[16]
Definition: scsi.h:1988
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70

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.
1443  PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
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.
1460  if (TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID))
1461  {
1462  ULONG validSenseBytes;
1464 
1465  // make sure we can at least access the AdditionalSenseLength field
1466  validSense = RTL_CONTAINS_FIELD(senseBuffer,
1467  Srb->SenseInfoBufferLength,
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 
1532  if (TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING))
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 }
SENSE_DATA SenseData
Definition: cdromp.h:319
#define max(a, b)
Definition: svc.c:63
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
SCSI_REQUEST_BLOCK Srb
Definition: cdromp.h:313
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
#define MAX_ADDITIONAL_SENSE_BYTES
Definition: scsi.h:600
Definition: cdrw_hw.h:28
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
struct _SENSE_DATA SENSE_DATA
unsigned char BOOLEAN
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2022
#define offsetof(TYPE, MEMBER)
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCodeQualifier
Definition: scsi.h:3748
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
Status
Definition: gdiplustypes.h:24
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
int64_t LONGLONG
Definition: typedefs.h:68
#define NUM_ERROR_LOG_ENTRIES
Definition: cdromp.h:323
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
LARGE_INTEGER TickCount
Definition: cdromp.h:303
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:482
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
unsigned char UCHAR
Definition: xmlstorage.h:181
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:318
#define IS_SCSIOP_READ(opCode)
Definition: cdrom.h:791
struct _CDROM_ERROR_LOG_DATA * PCDROM_ERROR_LOG_DATA
unsigned short USHORT
Definition: pedump.c:61
#define min(a, b)
Definition: monoChain.cc:55
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:676
struct _SENSE_DATA * PSENSE_DATA
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
BOOLEAN validSense
Definition: scsi.h:4018
#define NT_ASSERT
Definition: rtlfuncs.h:3312

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 
436  *MajorFunctionCode = 0;
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 }
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define FALSE
Definition: types.h:117
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1803
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
uint64_t ULONGLONG
Definition: typedefs.h:67
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:482
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:318
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
#define NULL
Definition: types.h:112
LARGE_INTEGER TimeSentDownFirstTime
Definition: cdrom.h:636
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
LONGLONG QuadPart
Definition: typedefs.h:114
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52

Referenced by SenseInfoInterpret().