ReactOS  0.4.15-dev-1636-gf634010
sense.c
Go to the documentation of this file.
1 /*--
2 
3 Copyright (C) Microsoft Corporation. All rights reserved.
4 
5 Module Name:
6 
7  sense.c
8 
9 Abstract:
10 
11  This file contains the methods needed to accurately
12  determine how to retry requests on CDROM device types.
13 
14 Environment:
15 
16  kernel mode only
17 
18 Revision History:
19 
20 --*/
21 
22 #include "stddef.h"
23 #include "string.h"
24 
25 #include "ntddk.h"
26 #include "ntddstor.h"
27 #include "cdrom.h"
28 #include "ntstrsafe.h"
29 
30 
31 #ifdef DEBUG_USE_WPP
32 #include "sense.tmh"
33 #endif
34 
35 // Forward declarations
36 VOID
38  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
40  _In_ BOOLEAN OverrideVerifyVolume,
43  );
44 
45 
46 #ifdef ALLOC_PRAGMA
47 
48 #pragma alloc_text(PAGE, SenseInfoInterpretRefineByIoControl)
49 
50 #endif
51 
52 
53 //
54 // FROM CLASSPNP\CLASSP.H
55 // Lots of retries of synchronized SCSI commands that devices may not
56 // even support really slows down the system (especially while booting).
57 // (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
58 // If a disk cannot return a small initialization buffer at startup
59 // in two attempts (with delay interval) then we cannot expect it to return
60 // data consistently with four retries.
61 // So don't set the retry counts as high here as for data SRBs.
62 //
63 // If we find that these requests are failing consecutively,
64 // despite the retry interval, on otherwise reliable media,
65 // then we should either increase the retry interval for
66 // that failure or (by all means) increase these retry counts as appropriate.
67 //
68 
69 #define TOTAL_COUNT_RETRY_DEFAULT 4
70 #define TOTAL_COUNT_RETRY_LOCK_MEDIA 1
71 #define TOTAL_COUNT_RETRY_MODESENSE 1
72 #define TOTAL_COUNT_RETRY_READ_CAPACITY 1
73 
74 
75 #define TOTAL_SECONDS_RETRY_TIME_WRITE 160
76 #define TOTAL_SECONDS_RETRY_TIME_MEDIUM_REMOVAL 120
77 
78 typedef struct _ERROR_LOG_CONTEXT {
85 
88  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
92  )
93 /*++
94 
95 Routine Description:
96 
97  this routine will be used for error handler for all MMC devices.
98  it's invoked by DeviceErrorHandler()that invoked by SenseInfoInterpret() or GESN
99 
100  This routine just checks for media change sense/asc/ascq and
101  also for other events, such as bus resets. this is used to
102  determine if the device behaviour has changed, to allow for
103  read and write operations to be allowed and/or disallowed.
104 
105 Arguments:
106 
107  DeviceExtension - device context
108  Srb - SRB structure for analyze
109 
110 Return Value:
111 
112  NTSTATUS
113  Status -
114  Retry -
115 
116 --*/
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 }
359 
360 NTSTATUS
362  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
366  )
367 /*++
368 
369 Routine Description:
370 
371  error handler for HITACHI CDR-1750S, CDR-3650/1650S
372 
373  This routine checks the type of error. If the error suggests that the
374  drive has spun down and cannot reinitialize itself, send a
375  START_UNIT or READ to the device. This will force the drive to spin
376  up. This drive also loses the AGIDs it has granted when it spins down,
377  which may result in playback failure the first time around.
378 
379 Arguments:
380 
381  DeviceExtension - the device object.
382 
383  Srb - Supplies a pointer to the failing Srb.
384 
385  Status - return the final status for this command?
386 
387  Retry - return if the command should be retried.
388 
389 Return Value:
390 
391  None.
392 
393 --*/
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 }
423 
424 
425 VOID
427  _In_ WDFREQUEST Request,
430  _Out_ BOOLEAN* OverrideVerifyVolume,
431  _Out_ ULONGLONG* Total100nsSinceFirstSend
432  )
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 }
482 
483 BOOLEAN
485  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
488  _In_ UCHAR AdditionalSenseCodeQual,
491  _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds,
492  _Inout_ PERROR_LOG_CONTEXT LogContext
493  )
494 /*
495  This function will interpret error based on ASC/ASCQ.
496 
497  If the error code is not processed in this function, e.g. return value is TRUE,
498  caller needs to call SenseInfoInterpretBySenseKey() for further interpret.
499 */
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 }
1078 
1079 VOID
1081  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1082  _In_ PSENSE_DATA SenseData,
1086  _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds,
1087  _Inout_ PERROR_LOG_CONTEXT LogContext
1088  )
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 }
1260 
1261 VOID
1263  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1265  _In_ ULONG RetriedCount,
1268  _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds,
1269  _Inout_ PERROR_LOG_CONTEXT LogContext
1270  )
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 }
1428 
1429 VOID
1431  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1435  _In_ ULONG RetriedCount,
1436  _In_ NTSTATUS* Status,
1437  _In_ BOOLEAN* Retry,
1438  _Inout_ PERROR_LOG_CONTEXT LogContext
1439  )
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 }
1661 
1662 VOID
1664  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1666  _In_ ULONG RetriedCount,
1667  _In_ LONGLONG Total100nsSinceFirstSend,
1668  _In_ BOOLEAN OverrideVerifyVolume,
1672  LONGLONG* RetryIntervalIn100ns
1673  )
1674 /*++
1675 
1676 Routine Description:
1677 
1678  Based on SCSI command, modify the interpretion result.
1679 
1680 Arguments:
1681 
1682  DeviceExtension - device extension.
1683  Srb - Supplies the scsi request block which failed.
1684  RetriedCount - retried count.
1685  Total100nsUnitsSinceFirstSend - time spent after the request was sent down first time.
1686  OverrideVerifyVolume - should override verify volume request.
1687 
1688 Return Value:
1689 
1690  Retry - the reques should be retried or not.
1691  Status - Returns the status for the request.
1692  RetryInterval - waiting time (in 100ns) before the request should be retried.
1693  Zero indicates the request should be immediately retried.
1694 
1695 --*/
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 }
1950 
1951 
1952 VOID
1954  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1956  _In_ BOOLEAN OverrideVerifyVolume,
1959  )
1960 /*++
1961 
1962 Routine Description:
1963 
1964  Based on IOCTL code, modify the interpretion result.
1965 
1966 Arguments:
1967 
1968  Device - Supplies the device object associated with this request.
1969  OriginalRequest - the irp that error occurs on.
1970  Srb - Supplies the scsi request block which failed.
1971  MajorFunctionCode - Supplies the function code to be used for logging.
1972  IoDeviceCode - Supplies the device code to be used for logging.
1973  PreviousRetryCount - retried count.
1974  RequestHistory_DoNotUse - the history list
1975 
1976 Return Value:
1977 
1978  BOOLEAN TRUE: Drivers should retry this request.
1979  FALSE: Drivers should not retry this request.
1980  Status - Returns the status for the request.
1981  RetryInterval - Number of seconds before the request should be retried.
1982  Zero indicates the request should be immediately retried.
1983 
1984 --*/
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 }
2036 
2037 BOOLEAN
2039  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2040  _In_ WDFREQUEST Request,
2042  _In_ ULONG RetriedCount,
2045  LONGLONG* RetryIntervalIn100ns
2046  )
2047 /*++
2048 
2049 SenseInfoInterpret()
2050 
2051 Routine Description:
2052 
2053  This routine interprets the data returned from the SCSI request sense.
2054  It determines the status to return in the IRP
2055  and whether this request can be retried.
2056 
2057 Arguments:
2058 
2059  Device - Supplies the device object associated with this request.
2060  Srb - Supplies the scsi request block which failed.
2061  MajorFunctionCode - Supplies the function code to be used for logging.
2062  IoDeviceCode - Supplies the device code to be used for logging.
2063 
2064 Return Value:
2065 
2066  BOOLEAN TRUE: Drivers should retry this request.
2067  FALSE: Drivers should not retry this request.
2068  Status - Returns the status for the request.
2069  RetryInterval - Number of seconds before the request should be retried.
2070  Zero indicates the request should be immediately retried.
2071 
2072 --*/
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()
2338 
2339 
2340 BOOLEAN
2342  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2346  LONGLONG* RetryIntervalIn100ns
2347  )
2348 /*++
2349 
2350 SenseInfoInterpretForZPODD()
2351 
2352 Routine Description:
2353 
2354  This routine interprets the data returned from the SCSI request sense.
2355  It determines the status to return in the IRP
2356  and whether this request can be retried.
2357 
2358 Arguments:
2359 
2360  Device - Supplies the device object associated with this request.
2361  Srb - Supplies the scsi request block which failed.
2362 
2363 Return Value:
2364 
2365  BOOLEAN TRUE: Drivers should retry this request.
2366  FALSE: Drivers should not retry this request.
2367  Status - Returns the status for the request.
2368  RetryInterval - Number of seconds before the request should be retried.
2369  Zero indicates the request should be immediately retried.
2370 
2371 --*/
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()
2464 
2465 
2466 BOOLEAN
2468  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2469  _In_ WDFREQUEST Request,
2471  _In_ ULONG RetriedCount,
2474  LONGLONG* RetryIntervalIn100ns
2475  )
2476 /*++
2477 
2478 Routine Description:
2479 
2480 Interpret the error, process it.
2481  1. Release device queue if it's frozen.
2482  2. Interpret and process the error.
2483 
2484 Arguments:
2485 
2486  DeviceExtension - Supplies the device object associated with this request.
2487  Request - the Request that error occurs on.
2488  Srb - Supplies the scsi request block which failed.
2489  RetriedCount - retried count.
2490 
2491 Return Value:
2492 
2493  BOOLEAN TRUE: Drivers should retry this request.
2494  FALSE: Drivers should not retry this request.
2495  Status - Returns the status for the request.
2496  RetryIntervalIn100nsUnits - Number of 100ns before the request should be retried.
2497  Zero indicates the request should be immediately retried.
2498 
2499 --*/
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 }
2561 
2562 
2563 BOOLEAN
2565  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2566  _In_ ULONG RetriedCount,
2569  LONGLONG* RetryIntervalIn100ns
2570  )
2571 /*++
2572 
2573 Routine Description:
2574 
2575  to analyze the error occurred and set the status, retry interval and decide to retry or not.
2576 
2577 Arguments:
2578 
2579  DeviceExtension - device extension
2580  RetriedCount - already retried count.
2581 
2582 Return Value:
2583 
2584  BOOLEAN - TRUE (should retry)
2585  Status - NTSTATUS
2586  RetryIntervalIn100nsUnits - retry interval
2587 
2588 --*/
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 }
2599 
2600 
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
SENSE_DATA SenseData
Definition: cdromp.h:319
* PNTSTATUS
Definition: strlen.c:14
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:338
#define SCSIOP_READ_TOC
Definition: cdrw_hw.h:927
#define SRB_STATUS_BUS_RESET
Definition: srb.h:345
#define SCSI_ADSENSE_WRITE_PROTECT
Definition: cdrw_hw.h:1268
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
UCHAR AdditionalSenseCode
Definition: cdromp.h:280
#define TOTAL_COUNT_RETRY_LOCK_MEDIA
Definition: sense.c:70
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
UCHAR SenseKey
Definition: cdrw_hw.h:1167
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define max(a, b)
Definition: svc.c:63
NTSTATUS ErrorCode
Definition: sense.c:81
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
VOID DeviceSetMediaChangeStateEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:751
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
SCSI_REQUEST_BLOCK Srb
Definition: cdromp.h:313
UCHAR AdditionalSenseCodeQualifier
Definition: cdromp.h:281
UCHAR senseKey
Definition: scsi.h:4019
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define SCSI_SENSEQ_INCOMPATIBLE_FORMAT
Definition: cdrw_hw.h:1323
#define TOTAL_COUNT_RETRY_READ_CAPACITY
Definition: sense.c:72
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
#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 SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define SCSI_SESNEQ_COMM_CRC_ERROR
Definition: scsi.h:738
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:103
#define MAX_ADDITIONAL_SENSE_BYTES
Definition: scsi.h:600
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
#define TOTAL_COUNT_RETRY_MODESENSE
Definition: sense.c:71
struct _ERROR_LOG_CONTEXT ERROR_LOG_CONTEXT
#define SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION
Definition: cdrw_hw.h:1393
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:353
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define SCSIOP_SEND_KEY
Definition: cdrw_hw.h:951
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
struct _CDB::_READ12 READ12
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define STATUS_CSS_KEY_NOT_ESTABLISHED
Definition: ntstatus.h:884
#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
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE
Definition: srb.h:351
struct _CDB::_WRITE12 WRITE12
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
struct _CDB::_CDB10 CDB10
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:355
ULONG BadSector
Definition: sense.c:83
#define SRB_STATUS(Status)
Definition: srb.h:381
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
#define STATUS_NONEXISTENT_SECTOR
Definition: udferr_usr.h:143
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
struct _CDB::_CDB16 CDB16
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define SRB_STATUS_ERROR
Definition: srb.h:336
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define SCSI_SENSE_MEDIUM_ERROR
Definition: cdrw_hw.h:1190
struct _CDB::_SEND_KEY SEND_KEY
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define SCSI_ADSENSE_REC_DATA_NOECC
Definition: cdrw_hw.h:1211
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
VOID SenseInfoRequestGetInformation(_In_ WDFREQUEST Request, _Out_ UCHAR *MajorFunctionCode, _Out_ ULONG *IoControlCode, _Out_ BOOLEAN *OverrideVerifyVolume, _Out_ ULONGLONG *Total100nsSinceFirstSend)
Definition: sense.c:426
#define SRB_STATUS_PARITY_ERROR
Definition: srb.h:346
#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 SCSIOP_READ_CD_MSF
Definition: cdrw_hw.h:964
VOID DevicePerfIncrementErrorCount(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: common.c:1378
BOOLEAN ErrorUnhandled
Definition: sense.c:80
#define SCSIOP_READ
Definition: cdrw_hw.h:905
struct _SENSE_DATA SENSE_DATA
#define SCSIOP_READ6
Definition: cdrw_hw.h:874
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
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: sense.c:2564
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
unsigned char BOOLEAN
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define NOT_READY_RETRY_INTERVAL
Definition: cdrw_hw.h:1094
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
#define SRB_STATUS_NO_HBA
Definition: srb.h:348
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2039
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
#define STATUS_CSS_RESETS_EXHAUSTED
Definition: ntstatus.h:887
#define offsetof(TYPE, MEMBER)
#define SRB_STATUS_ABORTED
Definition: srb.h:334
union _CDB * PCDB
#define _Out_
Definition: no_sal2.h:160
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 SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1820
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
ULONG UniqueErrorValue
Definition: sense.c:82
#define _Out_range_(l, h)
Definition: no_sal2.h:370
GLuint index
Definition: glext.h:6031
switch(r->id)
Definition: btrfs.c:2980
UCHAR Information[4]
Definition: cdrw_hw.h:1172
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
_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
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
#define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS
Definition: cdromp.h:50
Status
Definition: gdiplustypes.h:24
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
int64_t LONGLONG
Definition: typedefs.h:68
#define _Out_opt_
Definition: no_sal2.h:214
#define NUM_ERROR_LOG_ENTRIES
Definition: cdromp.h:323
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define SCSI_SENSE_BLANK_CHECK
Definition: cdrw_hw.h:1195
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
#define SCSIOP_VERIFY16
Definition: scsi.h:916
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 SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
#define SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED
Definition: scsi.h:692
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 STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
#define SCSI_ADSENSE_NO_SEEK_COMPLETE
Definition: scsi.h:650
#define SCSIOP_READ_TRACK_INFORMATION
Definition: scsi.h:315
uint64_t ULONGLONG
Definition: typedefs.h:67
#define SCSI_ADSENSE_LUN_COMMUNICATION
Definition: scsi.h:653
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define SCSI_ADSENSE_REC_DATA_ECC
Definition: cdrw_hw.h:1212
#define BECOMING_READY_RETRY_INTERNVAL_IN_100NS
Definition: cdromp.h:262
#define SCSISTAT_RESERVATION_CONFLICT
Definition: cdrw_hw.h:1084
LARGE_INTEGER TickCount
Definition: cdromp.h:303
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:482
BOOLEAN LogError
Definition: sense.c:79
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define _Inout_
Definition: no_sal2.h:162
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:349
#define SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
Definition: scsi.h:684
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_READ_DISK_INFORMATION
Definition: scsi.h:313
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define SCSI_SENSEQ_KEY_NOT_ESTABLISHED
Definition: cdrw_hw.h:1392
_In_ UCHAR _Out_opt_ PUCHAR SenseKey
Definition: scsi.h:3744
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
#define IO_ERR_NOT_READY
Definition: ntiologc.h:42
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
#define index(s, c)
Definition: various.h:29
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:365
#define SCSI_SENSEQ_UNKNOWN_FORMAT
Definition: cdrw_hw.h:1322
#define SCSI_SENSEQ_KEY_NOT_PRESENT
Definition: cdrw_hw.h:1391
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define VOID
Definition: acefi.h:82
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
_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 IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:342
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE
Definition: ntddmmc.h:17
#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_SENSEQ_CAUSE_NOT_REPORTABLE
Definition: cdrw_hw.h:1312
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
#define SCSI_SENSE_NO_SENSE
Definition: cdrw_hw.h:1187
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:354
VOID SenseInfoInterpretRefineByIoControl(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status)
Definition: sense.c:1953
#define _Deref_out_range_(l, h)
Definition: no_sal2.h:376
#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
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
#define _In_
Definition: no_sal2.h:158
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define IS_SCSIOP_READ(opCode)
Definition: cdrom.h:791
#define SCSI_ADSENSE_INSUFFICIENT_TIME_FOR_OPERATION
Definition: scsi.h:677
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
#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 SenseInfoLogError(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoControlCode, _In_ ULONG RetriedCount, _In_ NTSTATUS *Status, _In_ BOOLEAN *Retry, _Inout_ PERROR_LOG_CONTEXT LogContext)
Definition: sense.c:1430
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:2419
#define InterlockedIncrement
Definition: armddk.h:53
#define TOTAL_COUNT_RETRY_DEFAULT
Definition: sense.c:69
VOID DeviceReleaseQueue(_In_ WDFDEVICE Device)
Definition: common.c:1179
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
struct _CDROM_ERROR_LOG_DATA * PCDROM_ERROR_LOG_DATA
unsigned short USHORT
Definition: pedump.c:61
#define SRB_STATUS_TIMEOUT
Definition: srb.h:341
struct _ERROR_LOG_CONTEXT * PERROR_LOG_CONTEXT
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
#define UNIT_100NS_PER_SECOND
Definition: cdrom.h:1487
#define TOTAL_SECONDS_RETRY_TIME_WRITE
Definition: sense.c:75
struct _CDB::_CDB6GENERIC CDB6GENERIC
#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
WDFOBJECT ParentObject
Definition: wdfobject.h:130
NTSTATUS DeviceErrorHandlerForHitachiGD2000(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
Definition: sense.c:361
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
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
UCHAR IncorrectLength
Definition: cdrw_hw.h:1169
#define STATUS_CSS_SCRAMBLED_SECTOR
Definition: ntstatus.h:885
FORCEINLINE BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define SECONDS_TO_100NS_UNITS(x)
Definition: cdrom.h:1488
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:675
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
LARGE_INTEGER TimeSentDownFirstTime
Definition: cdrom.h:636
#define FDO_HACK_NO_STREAMING
Definition: cdromp.h:137
#define SCSI_SENSEQ_AUTHENTICATION_FAILURE
Definition: cdrw_hw.h:1390
NTSTATUS DeviceErrorHandlerForMmc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
Definition: sense.c:87
struct _SENSE_DATA * PSENSE_DATA
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
#define SCSI_SENSEQ_WRITE_PROTECT_ENABLE
Definition: scsi.h:880
#define SCSI_ADSENSE_INVALID_LUN
Definition: cdrw_hw.h:1266
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_CSS_AUTHENTICATION_FAILURE
Definition: ntstatus.h:882
#define PLAY_ACTIVE(DeviceExtension)
Definition: cdrom.c:190
#define SRB_STATUS_UNEXPECTED_BUS_FREE
Definition: srb.h:350
#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG
Definition: cdrom.h:99
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define SCSIOP_READ_CD
Definition: cdrw_hw.h:967
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define SRB_STATUS_INVALID_PATH_ID
Definition: srb.h:339
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
#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
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3124
#define SCSIOP_GET_PERFORMANCE
Definition: cdrw_hw.h:959
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
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 SCSI_SENSEQ_WRITE_PROTECT_DISABLE
Definition: scsi.h:881
#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 SCSI_ADSENSE_INVALID_CDB
Definition: cdrw_hw.h:1265
#define SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR
Definition: cdrw_hw.h:1395
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define IO_RECOVERED_VIA_ECC
Definition: ntiologc.h:60
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
LONGLONG QuadPart
Definition: typedefs.h:114
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
BOOLEAN validSense
Definition: scsi.h:4018
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define PAGED_CODE()
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
#define NT_ASSERT
Definition: rtlfuncs.h:3312
#define STATUS_CLEANER_CARTRIDGE_INSTALLED
Definition: ntstatus.h:218
Definition: ps.c:97