ReactOS 0.4.16-dev-125-g798ea90
sense.c
Go to the documentation of this file.
1/*--
2
3Copyright (C) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 sense.c
8
9Abstract:
10
11 This file contains the methods needed to accurately
12 determine how to retry requests on CDROM device types.
13
14Environment:
15
16 kernel mode only
17
18Revision 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
36VOID
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
78typedef struct _ERROR_LOG_CONTEXT {
85
88 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
92 )
93/*++
94
95Routine 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
105Arguments:
106
107 DeviceExtension - device context
108 Srb - SRB structure for analyze
109
110Return 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
135 {
137 {
138 if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
139 {
140 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
141 "DeviceErrorHandlerForMmc: media removed, writes will be "
142 "failed until new media detected\n"));
143 }
144
145 // NOTE - REF #0002
146 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
147 }
148 else if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)
149 {
151 {
152 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
153 "DeviceErrorHandlerForMmc: media becoming ready, "
154 "SHOULD notify shell of change time by sending "
155 "GESN request immediately!\n"));
156 }
159 ) &&
160 ((Srb->Cdb[0] == SCSIOP_READ) ||
161 (Srb->Cdb[0] == SCSIOP_READ6) ||
162 (Srb->Cdb[0] == SCSIOP_READ_CAPACITY) ||
163 (Srb->Cdb[0] == SCSIOP_READ_CD) ||
164 (Srb->Cdb[0] == SCSIOP_READ_CD_MSF) ||
165 (Srb->Cdb[0] == SCSIOP_READ_TOC) ||
166 (Srb->Cdb[0] == SCSIOP_WRITE) ||
167 (Srb->Cdb[0] == SCSIOP_WRITE6) ||
170 )
171 )
172 {
173 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
174 "DeviceErrorHandlerForMmc: LONG_WRITE or "
175 "OP_IN_PROGRESS for limited subset of cmds -- "
176 "setting retry to TRUE\n"));
177 *Retry = TRUE;
179 }
180 }
181 break;
182 } // end SCSI_SENSE_NOT_READY
183
185 {
186 switch (senseBuffer->AdditionalSenseCode)
187 {
189 {
190 // always update if the medium may have changed
191
192 // NOTE - REF #0002
193 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
194 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
195
196 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
197 "DeviceErrorHandlerForMmc: media change detected, need to "
198 "update drive capabilities\n"));
199 mediaChange = TRUE;
200 break;
201
202 } // end SCSI_ADSENSE_MEDIUM_CHANGED
203
205 {
206 // NOTE - REF #0002
207 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
208 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
209
210 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
211 "DeviceErrorHandlerForMmc: bus reset detected, need to "
212 "update drive capabilities\n"));
213 break;
214
215 } // end SCSI_ADSENSE_BUS_RESET
216
218 {
219
220 BOOLEAN b = FALSE;
221
222 switch (senseBuffer->AdditionalSenseCodeQualifier)
223 {
225 {
226 // eject notification currently handled by classpnp
227 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
228 "DeviceErrorHandlerForMmc: Eject requested by user\n"));
229 *Retry = TRUE;
231 break;
232 }
233
235 b = TRUE;
237 {
238 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
239 "DeviceErrorHandlerForMmc: Write protect %s requested "
240 "by user\n",
241 (b ? "disable" : "enable")));
242 *Retry = TRUE;
244 // NOTE - REF #0002
245 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
246 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
247
248 break;
249 }
250
251 } // end of AdditionalSenseCodeQualifier switch
252
253
254 break;
255
256 } // end SCSI_ADSENSE_OPERATOR_REQUEST
257
258 default:
259 {
260 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
261 "DeviceErrorHandlerForMmc: Unit attention %02x/%02x\n",
262 senseBuffer->AdditionalSenseCode,
263 senseBuffer->AdditionalSenseCodeQualifier));
264 break;
265 }
266
267 } // end of AdditionSenseCode switch
268 break;
269
270 } // end SCSI_SENSE_UNIT_ATTENTION
271
273 {
275 {
276 if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
277 {
278 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
279 "DeviceErrorHandlerForMmc: media was writable, but "
280 "failed request with WRITE_PROTECT error...\n"));
281 }
282 // NOTE - REF #0002
283 // do not update all the capabilities just because
284 // we can't write to the disc.
285 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
286 }
287 break;
288 } // end SCSI_SENSE_ILLEGAL_REQUEST
289
290 } // end of SenseKey switch
291
292 // Check if we failed to set the DVD region key and send appropriate error
293 if (cdb->CDB16.OperationCode == SCSIOP_SEND_KEY)
294 {
295 if (cdb->SEND_KEY.KeyFormat == DvdSetRpcKey)
296 {
298 {
299 // media of appropriate region required
301 *Retry = FALSE;
302 }
303 else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
306 {
307 // media of appropriate region required
309 *Retry = FALSE;
310 }
311 else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
314 {
315 // media of appropriate region required
317 *Retry = FALSE;
318 }
319 }
320 }
321 } // end of SRB_STATUS_AUTOSENSE_VALID
322
323 // On media change, if device speed should be reset to default then
324 // queue a workitem to send the commands to the device. Do this on
325 // media arrival as some device will fail this command if no media
326 // is present. Ignore the fake media change from classpnp driver.
327 if ((mediaChange == TRUE) && (*Status != STATUS_MEDIA_CHANGED))
328 {
329 if (DeviceExtension->DeviceAdditionalData.RestoreDefaults == TRUE)
330 {
332 WDF_OBJECT_ATTRIBUTES attributes;
333 WDF_WORKITEM_CONFIG workitemConfig;
334 WDFWORKITEM workItem;
335
336 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
337 attributes.ParentObject = DeviceExtension->Device;
338
339 WDF_WORKITEM_CONFIG_INIT(&workitemConfig,
341
342 status = WdfWorkItemCreate(&workitemConfig,
343 &attributes,
344 &workItem);
345 if (!NT_SUCCESS(status))
346 {
347 return STATUS_SUCCESS;
348 }
349
350 WdfWorkItemEnqueue(workItem);
351
352 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
353 "DeviceErrorHandlerForMmc: Restore device default speed for %p\n",
354 DeviceExtension->DeviceObject));
355 }
356 }
357 return STATUS_SUCCESS;
358}
359
362 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
366 )
367/*++
368
369Routine 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
379Arguments:
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
389Return Value:
390
391 None.
392
393--*/
394{
395 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
396
398 {
399 return STATUS_SUCCESS; //nobody cares about this return value yet.
400 }
401
402 if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_HARDWARE_ERROR) &&
403 (senseBuffer->AdditionalSenseCode == 0x44))
404 {
405 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
406 "DeviceErrorHandlerForHitachiGD2000 (%p) => Internal Target "
407 "Failure Detected -- spinning up drive\n", DeviceExtension->Device));
408
409 // the request should be retried because the device isn't ready
410 *Retry = TRUE;
412
413 // send a START_STOP unit to spin up the drive
414 // NOTE: this temporarily violates the StartIo serialization
415 // mechanism, but the completion routine on this will NOT
416 // call StartNextPacket(), so it's a temporary disruption
417 // of the serialization only.
418 DeviceSendStartUnit(DeviceExtension->Device);
419 }
420
421 return STATUS_SUCCESS;
422}
423
424
425VOID
427 _In_ WDFREQUEST Request,
430 _Out_ BOOLEAN* OverrideVerifyVolume,
431 _Out_ ULONGLONG* Total100nsSinceFirstSend
432 )
433{
434 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
435
437 *IoControlCode = 0;
438 *OverrideVerifyVolume = FALSE;
439 *Total100nsSinceFirstSend = 0;
440
441 if (requestContext->OriginalRequest != NULL)
442 {
443 PIO_STACK_LOCATION originalIrpStack = NULL;
444
445 PIRP originalIrp = WdfRequestWdmGetIrp(requestContext->OriginalRequest);
446
447 if (originalIrp != NULL)
448 {
449 originalIrpStack = IoGetCurrentIrpStackLocation(originalIrp);
450 }
451
452 if (originalIrpStack != NULL)
453 {
454 *MajorFunctionCode = originalIrpStack->MajorFunction;
455
457 {
458 *IoControlCode = originalIrpStack->Parameters.DeviceIoControl.IoControlCode;
459 }
460
461 *OverrideVerifyVolume = TEST_FLAG(originalIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);
462 }
463 }
464
465 // Calculate time past since the request was first time sent.
466 if (requestContext->TimeSentDownFirstTime.QuadPart > 0)
467 {
468 LARGE_INTEGER tmp;
469 KeQueryTickCount(&tmp);
470 tmp.QuadPart -= requestContext->TimeSentDownFirstTime.QuadPart;
472 *Total100nsSinceFirstSend = tmp.QuadPart;
473 }
474 else
475 {
476 // set to -1 if field TimeSentDownFirstTime not set.
477 *Total100nsSinceFirstSend = (ULONGLONG) -1;
478 }
479
480 return;
481}
482
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;
503
504 // set default values for retry fields.
506 *Retry = TRUE;
507 *RetryIntervalInSeconds = 0;
508
510 {
512 {
513 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
514 "SenseInfoInterpretByAdditionalSenseCode: Lun not ready\n"));
515
516 //
517 // Many non-WHQL certified drives (mostly CD-RW) return
518 // 2/4/0 when they have no media instead of the obvious choice of:
519 //
520 // SCSI_SENSE_NOT_READY/SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
521 //
522 // These drives should not pass WHQL certification due to this discrepency.
523 //
524 // However, we have to retry on 2/4/0 (Not ready, LUN not ready, no info)
525 // and also 3/2/0 (no seek complete).
526 //
527 // These conditions occur when the shell tries to examine an
528 // injected CD (e.g. for autoplay) before the CD is spun up.
529 //
530 // The drive should be returning an ASCQ of SCSI_SENSEQ_BECOMING_READY
531 // (0x01) in order to comply with WHQL standards.
532 //
533 // The default retry timeout of one second is acceptable to balance
534 // these discrepencies. don't modify the status, though....
535 //
536
537 switch (AdditionalSenseCodeQual)
538 {
540 {
541 DEVICE_EVENT_BECOMING_READY notReady = {0};
542
543 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
544 "SenseInfoInterpretByAdditionalSenseCode: Operation In Progress\n"));
545
546 needFurtherInterpret = FALSE;
547
548 *Retry = TRUE;
549 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
551
552 notReady.Version = 1;
553 notReady.Reason = 2;
554 notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10;
555 DeviceSendNotification(DeviceExtension,
556 &GUID_IO_DEVICE_BECOMING_READY,
558 &notReady);
559
560 break;
561 }
562
564 {
565 DEVICE_EVENT_BECOMING_READY notReady = {0};
566
567 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
568 "SenseInfoInterpretByAdditionalSenseCode: In process of becoming ready\n"));
569
570 needFurtherInterpret = FALSE;
571
572 *Retry = TRUE;
573 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
575
576 notReady.Version = 1;
577 notReady.Reason = 1;
578 notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10;
579 DeviceSendNotification(DeviceExtension,
580 &GUID_IO_DEVICE_BECOMING_READY,
582 &notReady);
583
584 break;
585 }
586
588 {
589 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
590 "SenseInfoInterpretByAdditionalSenseCode: Long write in progress\n"));
591
592 needFurtherInterpret = FALSE;
593
594 // This has been seen as a transcient failure on some drives
596 *Retry = TRUE;
597 // Set retry interval to be 0 as the drive can be ready at anytime.
598 *RetryIntervalInSeconds = 0;
599
600 break;
601 }
602
604 {
605 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
606 "SenseInfoInterpretByAdditionalSenseCode: Manual intervention required\n"));
607
608 needFurtherInterpret = FALSE;
609
611 *Retry = FALSE;
612 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
613
614 break;
615 }
616
618 {
619 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
620 "SenseInfoInterpretByAdditionalSenseCode: Format in progress\n"));
621
622 needFurtherInterpret = FALSE;
623
625 *Retry = FALSE;
626 *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL;
627
628 break;
629 }
630
633 default:
634 {
635 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
636 "SenseInfoInterpretByAdditionalSenseCode: Initializing command required\n"));
637
638 needFurtherInterpret = FALSE;
639
641 *Retry = TRUE;
642 *RetryIntervalInSeconds = 0;
643
644 // This sense code/additional sense code combination may indicate
645 // that the device needs to be started.
646 if (TEST_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT) &&
648 {
649 DeviceSendStartUnit(DeviceExtension->Device);
650 }
651
652 break;
653 }
654 } // end switch (AdditionalSenseCodeQual)
655 break;
656
657 } // end case (SCSI_ADSENSE_LUN_NOT_READY)
658
660 {
661 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
662 "SenseInfoInterpretByAdditionalSenseCode: No Media in device.\n"));
663
664 needFurtherInterpret = FALSE;
665
667 *Retry = FALSE;
668
669 if (AdditionalSenseCodeQual == 0xCC)
670 {
671 // The IMAPIv1 filter returns this ASCQ value while it is burning CD media, and we want
672 // to preserve this functionality for compatibility reasons.
673 // We want to indicate that the media is not present to most applications;
674 // but RSM has to know that the media is still in the drive (i.e. the drive is not free).
676 }
677 else
678 {
680 }
681
682 break;
683 } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
684
686 {
687 switch (AdditionalSenseCodeQual)
688 {
689
691 {
692 needFurtherInterpret = FALSE;
693
694 // Log error only if this is a paging request
696 *Retry = FALSE;
697
698 LogContext->LogError = TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING);
699 LogContext->UniqueErrorValue = 256;
700 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
701
702 break;
703 }
704
706 {
707 needFurtherInterpret = FALSE;
708
710 *Retry = FALSE;
711
712 LogContext->LogError = FALSE;
713
714 break;
715 }
716
718 {
719 needFurtherInterpret = FALSE;
720
722 *Retry = FALSE;
723
724 LogContext->LogError = FALSE;
725 LogContext->UniqueErrorValue = 256;
726 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
727 break;
728 }
729
730 default:
731 {
732 needFurtherInterpret = TRUE;
733 break;
734 }
735 } // end case AdditionalSenseCodeQual
736
737 break;
738 } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
739
741 {
742 switch (AdditionalSenseCodeQual)
743 {
744
745 case 0x00:
746 {
747 needFurtherInterpret = FALSE;
748
750 *Retry = TRUE;
751 *RetryIntervalInSeconds = 0;
752 LogContext->LogError = TRUE;
753 LogContext->UniqueErrorValue = 256;
754 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
755 break;
756 }
757
758 default:
759 {
760 needFurtherInterpret = TRUE;
761 break;
762 }
763 }
764
765 break;
766 } // end case SCSI_ADSENSE_NO_SEEK_COMPLETE
767
769 {
770 switch (AdditionalSenseCodeQual)
771 {
772
774 {
775 needFurtherInterpret = FALSE;
776
778 *Retry = TRUE;
779 *RetryIntervalInSeconds = 1;
780 LogContext->LogError = TRUE;
781 LogContext->UniqueErrorValue = 257;
782 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
783 break;
784 }
785
786 default:
787 {
788 needFurtherInterpret = TRUE;
789 break;
790 }
791 }
792
793 break;
794 } // end case SCSI_ADSENSE_LUN_COMMUNICATION
795
797 {
798 needFurtherInterpret = FALSE;
799
800 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
801 "SenseInfoInterpretByAdditionalSenseCode: Illegal block address\n"));
803 *Retry = FALSE;
804 break;
805 }
806
808 {
809 needFurtherInterpret = FALSE;
810
811 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
812 "SenseInfoInterpretByAdditionalSenseCode: Invalid LUN\n"));
814 *Retry = FALSE;
815 break;
816 }
817
819 {
820 needFurtherInterpret = FALSE;
821
822 *Retry = FALSE;
823
824 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
825 "SenseInfoInterpretByAdditionalSenseCode: Key - Copy protection failure\n"));
826
827 switch (AdditionalSenseCodeQual)
828 {
830 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
831 "SenseInfoInterpretByAdditionalSenseCode: Authentication failure\n"));
833 break;
835 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
836 "SenseInfoInterpretByAdditionalSenseCode: Key not present\n"));
838 break;
840 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
841 "SenseInfoInterpretByAdditionalSenseCode: Key not established\n"));
843 break;
845 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
846 "SenseInfoInterpretByAdditionalSenseCode: Read of scrambled sector w/o authentication\n"));
848 break;
850 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
851 "SenseInfoInterpretByAdditionalSenseCode: Media region does not logical unit region\n"));
853 break;
855 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
856 "SenseInfoInterpretByAdditionalSenseCode: Region set error -- region may be permanent\n"));
858 break;
859
860 default:
862 break;
863 } // end switch of ASCQ for COPY_PROTECTION_FAILURE
864
865 break;
866 }
867
869 {
870 needFurtherInterpret = FALSE;
871
872 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
873 "SenseInfoInterpretByAdditionalSenseCode: Key - Invalid CDB\n"));
874
876 *Retry = FALSE;
877
878 // Note: the retry interval is not typically used.
879 // it is set here only because a ClassErrorHandler
880 // cannot set the RetryIntervalInSeconds, and the error may
881 // require a few commands to be sent to clear whatever
882 // caused this condition (i.e. disk clears the write
883 // cache, requiring at least two commands)
884 //
885 // hopefully, this shortcoming can be changed for blackcomb.
886 *RetryIntervalInSeconds = 3;
887
888 break;
889 }
890
892 {
893 needFurtherInterpret = FALSE;
894 *RetryIntervalInSeconds = 0;
895
896 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
897 "SenseInfoInterpretByAdditionalSenseCode: Media changed\n"));
898
900
901 // special process for Media Change
902 if (IsVolumeMounted(DeviceExtension->DeviceObject))
903 {
904 // Set bit to indicate that media may have changed and volume needs verification.
905 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
906
908 *Retry = FALSE;
909 }
910 else
911 {
913 *Retry = TRUE;
914 }
915 break;
916 }
917
919 {
920 switch (AdditionalSenseCodeQual)
921 {
923 {
924 needFurtherInterpret = FALSE;
925 *RetryIntervalInSeconds = 0;
926
927 InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
928
929 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
930 "SenseInfoInterpretByAdditionalSenseCode: Ejection request received!\n"));
931 //Send eject notification.
932 DeviceSendNotification(DeviceExtension,
933 &GUID_IO_MEDIA_EJECT_REQUEST,
934 0,
935 NULL);
936 // special process for Media Change
937 if (IsVolumeMounted(DeviceExtension->DeviceObject))
938 {
939 // Set bit to indicate that media may have changed and volume needs verification.
940 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
941
943 *Retry = FALSE;
944 }
945 else
946 {
948 *Retry = TRUE;
949 }
950 break;
951 }
952 default:
953 {
954 needFurtherInterpret = TRUE;
955 break;
956 }
957 }
958 break;
959 }
960
962 {
963 needFurtherInterpret = FALSE;
964 *RetryIntervalInSeconds = 5;
965
966 InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
967
968 // Device information has changed, we need to rescan the
969 // bus for changed information such as the capacity.
970 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
971 "SenseInfoInterpretByAdditionalSenseCode: Device information changed. Invalidate the bus\n"));
972
973 IoInvalidateDeviceRelations(DeviceExtension->LowerPdo, BusRelations);
974
975 // special process for Media Change
976 if (IsVolumeMounted(DeviceExtension->DeviceObject))
977 {
978 // Set bit to indicate that media may have changed and volume needs verification.
979 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
980
982 *Retry = FALSE;
983 }
984 else
985 {
987 *Retry = TRUE;
988 }
989 break;
990 } //end Case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
991
992
995 {
996 needFurtherInterpret = FALSE;
997
999 *Retry = FALSE;
1000 LogContext->LogError = TRUE;
1001 LogContext->UniqueErrorValue = 258;
1002 LogContext->ErrorCode = IO_RECOVERED_VIA_ECC;
1003
1004 if (senseBuffer->IncorrectLength)
1005 {
1006 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1007 "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n"));
1009 }
1010 break;
1011 }
1012
1014 {
1015 UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
1016
1017 *((PULONG)wmiEventData) = sizeof(UCHAR);
1018 wmiEventData[sizeof(ULONG)] = AdditionalSenseCodeQual;
1019
1020 needFurtherInterpret = FALSE;
1021
1022 // Don't log another eventlog if we have already logged once
1023 // NOTE: this should have been interlocked, but the structure
1024 // was publicly defined to use a BOOLEAN (char). Since
1025 // media only reports these errors once per X minutes,
1026 // the potential race condition is nearly non-existant.
1027 // the worst case is duplicate log entries, so ignore.
1028
1030 *Retry = FALSE;
1031 LogContext->UniqueErrorValue = 258;
1032 LogContext->LogError = TRUE;
1033 LogContext->ErrorCode = IO_WRN_FAILURE_PREDICTED;
1034
1035 if (senseBuffer->IncorrectLength)
1036 {
1037 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1038 "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n"));
1040 }
1041 break;
1042 }
1043
1044 case 0x57:
1045 {
1046 // UNABLE_TO_RECOVER_TABLE_OF_CONTENTS
1047 // the Matshita CR-585 returns this for all read commands
1048 // on blank CD-R and CD-RW media, and we need to handle
1049 // this for READ_CD detection ability.
1050 switch (AdditionalSenseCodeQual)
1051 {
1052 case 0x00:
1053 {
1054 needFurtherInterpret = FALSE;
1055
1057 *Retry = FALSE;
1058 break;
1059 }
1060 default:
1061 {
1062 needFurtherInterpret = TRUE;
1063 break;
1064 }
1065 }
1066 break;
1067 } //end case Matshita specific error 0x57
1068
1069 default:
1070 {
1071 needFurtherInterpret = TRUE;
1072 break;
1073 }
1074 }
1075
1076 return needFurtherInterpret;
1077}
1078
1079VOID
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 {
1098 {
1099 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1100 "SenseInfoInterpretBySenseKey: Key - Not Ready (bad block)\n"));
1101
1103 *Retry = TRUE;
1104
1105 // for unprocessed "not ready" codes, retry the command immediately.
1106 *RetryIntervalInSeconds = 0;
1107 break;
1108 }
1109
1111 {
1112 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1113 "SenseInfoInterpretBySenseKey: Key - Media write protected\n"));
1115 *Retry = FALSE;
1116 break;
1117 }
1118
1120 {
1121 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1122 "SenseInfoInterpretBySenseKey: Key - Medium Error (bad block)\n"));
1123
1125 *Retry = FALSE;
1126 LogContext->LogError = TRUE;
1127 LogContext->UniqueErrorValue = 256;
1128 LogContext->ErrorCode = IO_ERR_BAD_BLOCK;
1129
1130 break;
1131 } // end SCSI_SENSE_MEDIUM_ERROR
1132
1134 {
1135 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1136 "SenseInfoInterpretBySenseKey: Key - Hardware error\n"));
1137
1139 *Retry = TRUE;
1140 LogContext->LogError = TRUE;
1141 LogContext->UniqueErrorValue = 257;
1142 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1143
1144 break;
1145 } // end SCSI_SENSE_HARDWARE_ERROR
1146
1148 {
1149 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1150 "SenseInfoInterpretBySenseKey: Key - Illegal SCSI request\n"));
1152 *Retry = FALSE;
1153
1154 break;
1155 } // end SCSI_SENSE_ILLEGAL_REQUEST
1156
1158 {
1159 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1160 "SenseInfoInterpretBySenseKey: Key - Unit Attention\n"));
1161
1162 // A media change may have occured so increment the change
1163 // count for the physical device
1164 InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
1165
1166 if (IsVolumeMounted(DeviceExtension->DeviceObject))
1167 {
1168 // Set bit to indicate that media may have changed
1169 // and volume needs verification.
1170 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
1171
1173 *Retry = FALSE;
1174 }
1175 else
1176 {
1178 *Retry = TRUE;
1179 }
1180
1181 break;
1182
1183 } // end SCSI_SENSE_UNIT_ATTENTION
1184
1186 {
1187 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1188 "SenseInfoInterpretBySenseKey: Command aborted\n"));
1190 *Retry = TRUE;
1191 *RetryIntervalInSeconds = 1;
1192 break;
1193 } // end SCSI_SENSE_ABORTED_COMMAND
1194
1196 {
1197 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1198 "SenseInfoInterpretBySenseKey: Media blank check\n"));
1199 *Retry = FALSE;
1201 break;
1202 } // end SCSI_SENSE_BLANK_CHECK
1203
1205 {
1206 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1207 "SenseInfoInterpretBySenseKey: Recovered error\n"));
1209 *Retry = FALSE;
1210 LogContext->LogError = TRUE;
1211 LogContext->UniqueErrorValue = 258;
1212 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1213
1214 if (SenseData->IncorrectLength)
1215 {
1216 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1217 "SenseInfoInterpretBySenseKey: Incorrect length detected.\n"));
1219 }
1220
1221 break;
1222 } // end SCSI_SENSE_RECOVERED_ERROR
1223
1225 {
1226 // Check other indicators.
1227 if (SenseData->IncorrectLength)
1228 {
1229 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
1230 "SenseInfoInterpretBySenseKey: Incorrect length detected.\n"));
1232 *Retry = FALSE;
1233 }
1234 else
1235 {
1236 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1237 "SenseInfoInterpretBySenseKey: No specific sense key\n"));
1239 *Retry = TRUE;
1240 }
1241
1242 break;
1243 } // end SCSI_SENSE_NO_SENSE
1244
1245 default:
1246 {
1247 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1248 "SenseInfoInterpretBySenseKey: Unrecognized sense code\n"));
1250 *Retry = TRUE;
1251 *RetryIntervalInSeconds = 0;
1252
1253 break;
1254 }
1255
1256 } // end switch (SenseKey)
1257
1258 return;
1259}
1260
1261VOID
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 {
1284 case SRB_STATUS_NO_HBA:
1286 {
1288 *Retry = FALSE;
1289 break;
1290 }
1291
1293 case SRB_STATUS_TIMEOUT:
1294 {
1295 // Update the error count for the device.
1297 *Retry = TRUE;
1298 *RetryIntervalInSeconds = 0;
1299 incrementErrorCount = TRUE;
1300 break;
1301 }
1302
1303 case SRB_STATUS_ABORTED:
1304 {
1305 // Update the error count for the device.
1307 *Retry = TRUE;
1308 *RetryIntervalInSeconds = 1;
1309 incrementErrorCount = TRUE;
1310 break;
1311 }
1312
1314 {
1316 *Retry = FALSE;
1317 *RetryIntervalInSeconds = 2;
1318 LogContext->LogError = TRUE;
1319 LogContext->ErrorCode = IO_ERR_NOT_READY;
1320 LogContext->UniqueErrorValue = 260;
1321 break;
1322 }
1323
1325 {
1327 *Retry = FALSE;
1328 break;
1329 }
1330
1332 {
1333 // Update the error count for the device.
1334 incrementErrorCount = TRUE;
1336
1337 // If there was phase sequence error then limit the number of retries.
1338 *Retry = (RetriedCount <= 1);
1339
1340 break;
1341 }
1342
1344 {
1345 // If the status needs verification bit is set. Then set
1346 // the status to need verification and no retry; otherwise,
1347 // just retry the request.
1348 if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME))
1349 {
1351 *Retry = FALSE;
1352 }
1353 else
1354 {
1356 *Retry = TRUE;
1357 }
1358
1359 break;
1360 }
1361
1363 {
1365 *Retry = FALSE;
1366 break;
1367 }
1368
1371 // Update the error count for the device and fall through to below
1372 incrementErrorCount = TRUE;
1373
1375 {
1377 *Retry = TRUE;
1378 break;
1379 }
1380
1381 case SRB_STATUS_ERROR:
1382 {
1384 *Retry = TRUE;
1385
1386 if (Srb->ScsiStatus == 0)
1387 {
1388 // This is some strange return code. Update the error
1389 // count for the device.
1390 incrementErrorCount = TRUE;
1391 }
1392
1394 {
1396 }
1397
1398 break;
1399 }
1400
1401 default:
1402 {
1404 *Retry = TRUE;
1405 LogContext->LogError = TRUE;
1406 LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR;
1407 LogContext->UniqueErrorValue = 259;
1408 LogContext->ErrorUnhandled = TRUE;
1409 break;
1410 }
1411
1412 } //end of (SRB_STATUS(Srb->SrbStatus))
1413
1414 if (incrementErrorCount)
1415 {
1416 // if any error count occurred, delay the retry of this io by
1417 // at least one second, if caller supports it.
1418 if (*RetryIntervalInSeconds == 0)
1419 {
1420 *RetryIntervalInSeconds = 1;
1421 }
1422
1423 DevicePerfIncrementErrorCount(DeviceExtension);
1424 }
1425
1426 return;
1427}
1428
1429VOID
1431 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1435 _In_ ULONG RetriedCount,
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.
1444 ULONG totalSize = 0;
1445 ULONG senseBufferSize = 0;
1446 IO_ERROR_LOG_PACKET staticErrLogEntry = {0};
1447 CDROM_ERROR_LOG_DATA staticErrLogData = {0};
1448
1449 // Calculate the total size of the error log entry.
1450 // add to totalSize in the order that they are used.
1451 // the advantage to calculating all the sizes here is
1452 // that we don't have to do a bunch of extraneous checks
1453 // later on in this code path.
1454 totalSize = sizeof(IO_ERROR_LOG_PACKET) // required
1455 + sizeof(CDROM_ERROR_LOG_DATA); // struct for ease
1456
1457 // also save any available extra sense data, up to the maximum errlog
1458 // packet size . WMI should be used for real-time analysis.
1459 // the event log should only be used for post-mortem debugging.
1461 {
1462 ULONG validSenseBytes;
1464
1465 // make sure we can at least access the AdditionalSenseLength field
1466 validSense = RTL_CONTAINS_FIELD(senseBuffer,
1468 AdditionalSenseLength);
1469 if (validSense)
1470 {
1471 // if extra info exists, copy the maximum amount of available
1472 // sense data that is safe into the the errlog.
1473 validSenseBytes = senseBuffer->AdditionalSenseLength
1474 + offsetof(SENSE_DATA, AdditionalSenseLength);
1475
1476 // this is invalid because it causes overflow!
1477 // whoever sent this type of request would cause
1478 // a system crash.
1479 NT_ASSERT(validSenseBytes < MAX_ADDITIONAL_SENSE_BYTES);
1480
1481 // set to save the most sense buffer possible
1482 senseBufferSize = max(validSenseBytes, sizeof(SENSE_DATA));
1483 senseBufferSize = min(senseBufferSize, Srb->SenseInfoBufferLength);
1484 }
1485 else
1486 {
1487 // it's smaller than required to read the total number of
1488 // valid bytes, so just use the SenseInfoBufferLength field.
1489 senseBufferSize = Srb->SenseInfoBufferLength;
1490 }
1491
1492 // Bump totalSize by the number of extra senseBuffer bytes
1493 // (beyond the default sense buffer within CDROM_ERROR_LOG_DATA).
1494 // Make sure to never allocate more than ERROR_LOG_MAXIMUM_SIZE.
1495 if (senseBufferSize > sizeof(SENSE_DATA))
1496 {
1497 totalSize += senseBufferSize-sizeof(SENSE_DATA);
1498 if (totalSize > ERROR_LOG_MAXIMUM_SIZE)
1499 {
1500 senseBufferSize -= totalSize-ERROR_LOG_MAXIMUM_SIZE;
1501 totalSize = ERROR_LOG_MAXIMUM_SIZE;
1502 }
1503 }
1504 }
1505
1506 // If we've used up all of our retry attempts, set the final status to
1507 // reflect the appropriate result.
1508 //
1509 // ISSUE: the test below should also check RetriedCount to determine if we will actually retry,
1510 // but there is no easy test because we'd have to consider the original retry count
1511 // for the op; besides, InterpretTransferPacketError sometimes ignores the retry
1512 // decision returned by this function. So just ErrorRetried to be true in the majority case.
1513 //
1514 if (*Retry)
1515 {
1516 staticErrLogEntry.FinalStatus = STATUS_SUCCESS;
1517 staticErrLogData.ErrorRetried = TRUE;
1518 }
1519 else
1520 {
1521 staticErrLogEntry.FinalStatus = *Status;
1522 }
1523
1524 // Don't log generic IO_WARNING_PAGING_FAILURE message if either the
1525 // I/O is retried, or it completed successfully.
1526 if ((LogContext->ErrorCode == IO_WARNING_PAGING_FAILURE) &&
1527 (*Retry || NT_SUCCESS(*Status)) )
1528 {
1529 LogContext->LogError = FALSE;
1530 }
1531
1533 {
1534 staticErrLogData.ErrorPaging = TRUE;
1535 }
1536
1537 staticErrLogData.ErrorUnhandled = LogContext->ErrorUnhandled;
1538
1539 // Calculate the device offset if there is a geometry.
1540 staticErrLogEntry.DeviceOffset.QuadPart = (LONGLONG)LogContext->BadSector;
1541 staticErrLogEntry.DeviceOffset.QuadPart *= (LONGLONG)DeviceExtension->DiskGeometry.BytesPerSector;
1542
1543 if (LogContext->ErrorCode == -1)
1544 {
1545 staticErrLogEntry.ErrorCode = STATUS_IO_DEVICE_ERROR;
1546 }
1547 else
1548 {
1549 staticErrLogEntry.ErrorCode = LogContext->ErrorCode;
1550 }
1551
1552 // The dump data follows the IO_ERROR_LOG_PACKET
1553 staticErrLogEntry.DumpDataSize = (USHORT)totalSize - sizeof(IO_ERROR_LOG_PACKET);
1554
1555 staticErrLogEntry.SequenceNumber = 0;
1556 staticErrLogEntry.MajorFunctionCode = MajorFunctionCode;
1557 staticErrLogEntry.IoControlCode = IoControlCode;
1558 staticErrLogEntry.RetryCount = (UCHAR)RetriedCount;
1559 staticErrLogEntry.UniqueErrorValue = LogContext->UniqueErrorValue;
1560
1561 KeQueryTickCount(&staticErrLogData.TickCount);
1562 staticErrLogData.PortNumber = (ULONG)-1;
1563
1564 // Save the entire contents of the SRB.
1565 staticErrLogData.Srb = *Srb;
1566
1567 // For our private log, save just the default length of the SENSE_DATA.
1568 if (senseBufferSize != 0)
1569 {
1570 RtlCopyMemory(&staticErrLogData.SenseData, senseBuffer, min(senseBufferSize, sizeof(SENSE_DATA)));
1571 }
1572
1573 // Save the error log in our context.
1574 // We only save the default sense buffer length.
1575 {
1576 KIRQL oldIrql;
1577 KeAcquireSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, &oldIrql);
1578 DeviceExtension->PrivateFdoData->ErrorLogs[DeviceExtension->PrivateFdoData->ErrorLogNextIndex] = staticErrLogData;
1579 DeviceExtension->PrivateFdoData->ErrorLogNextIndex++;
1580 DeviceExtension->PrivateFdoData->ErrorLogNextIndex %= NUM_ERROR_LOG_ENTRIES;
1581 KeReleaseSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, oldIrql);
1582 }
1583
1584 // If logError is set, also save this log in the system's error log.
1585 // But make sure we don't log TUR failures over and over
1586 // (e.g. if an external drive was switched off and we're still sending TUR's to it every second).
1587 if (LogContext->LogError)
1588 {
1589 // We do not want to log certain system events repetitively
1590 switch (((PCDB)Srb->Cdb)->CDB10.OperationCode)
1591 {
1593 {
1594 if (DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO)
1595 {
1596 LogContext->LogError = FALSE;
1597 }
1598 else
1599 {
1600 DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO = TRUE;
1601 }
1602
1603 break;
1604 }
1605
1607 {
1608 if (DeviceExtension->PrivateFdoData->LoggedSYNCFailure)
1609 {
1610 LogContext->LogError = FALSE;
1611 }
1612 else
1613 {
1614 DeviceExtension->PrivateFdoData->LoggedSYNCFailure = TRUE;
1615 }
1616
1617 break;
1618 }
1619 }
1620
1621 // Do not log 5/21/00 LOGICAL BLOCK ADDRESS OUT OF RANGE if the disc is blank,
1622 // it is known to litter the Event Log with repetitive errors
1623 // Do not log this error for READ, as it's known that File System mount process reads different sectors from media.
1625 senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST &&
1626 senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK &&
1627 senseBuffer->AdditionalSenseCodeQualifier == 0 &&
1628 IS_SCSIOP_READ(((PCDB)Srb->Cdb)->CDB10.OperationCode))
1629 {
1630 LogContext->LogError = FALSE;
1631 }
1632 }
1633
1634 // Write the error log packet to the system error logging thread.
1635 if (LogContext->LogError)
1636 {
1637 PIO_ERROR_LOG_PACKET errorLogEntry;
1638 PCDROM_ERROR_LOG_DATA errlogData;
1639
1640 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DeviceExtension->DeviceObject, (UCHAR)totalSize);
1641 if (errorLogEntry)
1642 {
1643 errlogData = (PCDROM_ERROR_LOG_DATA)errorLogEntry->DumpData;
1644
1645 *errorLogEntry = staticErrLogEntry;
1646 *errlogData = staticErrLogData;
1647
1648 // For the system log, copy as much of the sense buffer as possible.
1649 if (senseBufferSize != 0)
1650 {
1651 RtlCopyMemory(&errlogData->SenseData, senseBuffer, senseBufferSize);
1652 }
1653
1654 // errorLogEntry - It will be freed by the kernel.
1655 IoWriteErrorLogEntry(errorLogEntry);
1656 }
1657 }
1658
1659 return;
1660}
1661
1662VOID
1664 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1666 _In_ ULONG RetriedCount,
1667 _In_ LONGLONG Total100nsSinceFirstSend,
1668 _In_ BOOLEAN OverrideVerifyVolume,
1672 LONGLONG* RetryIntervalIn100ns
1673 )
1674/*++
1675
1676Routine Description:
1677
1678 Based on SCSI command, modify the interpretion result.
1679
1680Arguments:
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
1688Return 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);
1700
1701 if (opCode == SCSIOP_MEDIUM_REMOVAL)
1702 {
1703 if (( cdb->AsByte[1] == 0) &&
1704 ( cdb->AsByte[2] == 0) &&
1705 ( cdb->AsByte[3] == 0) &&
1706 ((cdb->AsByte[4] & 0xFC) == 0)
1707 )
1708 {
1709 // byte[4] == 0x3 or byte[4] == 0x1 == UNLOCK OF MEDIA
1710 if ((cdb->AsByte[4] & 0x01) == 0)
1711 {
1712 if (RetriedCount < TOTAL_COUNT_RETRY_DEFAULT)
1713 {
1714 // keep retrying unlock operation for several times
1715 *Retry = TRUE;
1716 }
1717 }
1718 else // LOCK REQUEST
1719 {
1720 // do not retry LOCK requests more than once (per CLASSPNP code)
1721 if (RetriedCount > TOTAL_COUNT_RETRY_LOCK_MEDIA)
1722 {
1723 *Retry = FALSE;
1724 }
1725 }
1726 }
1727
1728 // want a minimum time to retry of 2 seconds
1729 if ((*Status == STATUS_DEVICE_NOT_READY) &&
1731 {
1732 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1733 }
1735 {
1736 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1737 }
1738 }
1739 else if ((opCode == SCSIOP_MODE_SENSE) || (opCode == SCSIOP_MODE_SENSE10))
1740 {
1741 // want a minimum time to retry of 2 seconds
1742 if ((*Status == STATUS_DEVICE_NOT_READY) &&
1744 {
1745 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1746 }
1748 {
1749 *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2));
1750 }
1751
1752 // Want to ignore a STATUS_VERIFY_REQUIRED error because it either
1753 // doesn't make sense or is required to satisfy the VERIFY.
1755 {
1756 *Retry = TRUE;
1757 }
1759 {
1760 /*
1761 * This is a HACK.
1762 * Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
1763 * underrun (i.e. success, and the buffer is longer than needed).
1764 * So treat this as a success.
1765 * When the caller of this function sees that the status was changed to success,
1766 * it will add the transferred length to the original irp.
1767 */
1769 *Retry = FALSE;
1770 }
1771
1772 // limit the count of retries
1773 if (RetriedCount > TOTAL_COUNT_RETRY_MODESENSE)
1774 {
1775 *Retry = FALSE;
1776 }
1777 }
1778 else if ((opCode == SCSIOP_READ_CAPACITY) || (opCode == SCSIOP_READ_CAPACITY16))
1779 {
1780 // Want to ignore a STATUS_VERIFY_REQUIRED error because it either
1781 // doesn't make sense or is required to satisfy the VERIFY.
1783 {
1784 *Retry = TRUE;
1785 }
1786
1787 if (RetriedCount > TOTAL_COUNT_RETRY_READ_CAPACITY)
1788 {
1789 *Retry = FALSE;
1790 }
1791 }
1792 else if ((opCode == SCSIOP_RESERVE_UNIT) || (opCode == SCSIOP_RELEASE_UNIT))
1793 {
1794 // The RESERVE(6) / RELEASE(6) commands are optional.
1795 // So if they aren't supported, try the 10-byte equivalents
1797 {
1798 PCDB tempCdb = (PCDB)Srb->Cdb;
1799
1800 Srb->CdbLength = 10;
1801 tempCdb->CDB10.OperationCode = (tempCdb->CDB6GENERIC.OperationCode == SCSIOP_RESERVE_UNIT)
1804
1805 SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6);
1806 *Retry = TRUE;
1807 }
1808 }
1809 else if (IS_SCSIOP_READWRITE(opCode))
1810 {
1811 // Retry if still verifying a (possibly) reloaded disk/cdrom.
1812 if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED))
1813 {
1815 *Retry = TRUE;
1816 }
1817
1818 // Special case for streaming READ/WRITE commands
1819 if (((opCode == SCSIOP_READ12) && (cdb->READ12.Streaming == 1)) ||
1820 ((opCode == SCSIOP_WRITE12) && (cdb->WRITE12.Streaming == 1)))
1821 {
1822 // We've got a failure while performing a streaming operation and now need to guess if
1823 // it's likely to be a permanent error because the drive does not support streaming at all
1824 // (in which case we're going to fall back to normal reads/writes), or a transient error
1825 // (in which case we quickly fail the request but contrinue to use streaming).
1826 //
1827 // We analyze the sense information to make that decision. Bus resets and device timeouts
1828 // are treated as permanent errors, because some non-compliant devices may even hang when
1829 // they get a command that they do not expect.
1830
1831 BOOLEAN disableStreaming = FALSE;
1832
1837 {
1838 disableStreaming = TRUE;
1839 }
1840 else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_UNIT_ATTENTION)
1841 {
1842 if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET ||
1844 {
1845 disableStreaming = TRUE;
1846 }
1847 }
1848 else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_ILLEGAL_REQUEST)
1849 {
1850 // LBA Out of Range is an exception, as it's more likely to be caused by
1851 // upper layers attempting to read/write a wrong LBA.
1853 {
1854 disableStreaming = TRUE;
1855 }
1856 }
1857
1858 if (disableStreaming)
1859 {
1860 // if the failure looks permanent, we disable streaming for all future reads/writes
1861 // and retry the command immediately
1862 SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_STREAMING);
1863 *Retry = TRUE;
1864 *RetryIntervalIn100ns = 0;
1865 }
1866 else
1867 {
1868 // if the failure looks transient, we simply fail the current request without retries
1869 // to minimize the time of processing
1870 *Retry = FALSE;
1871 }
1872 }
1873
1874 // Special-case handling of READ/WRITE commands. These commands now have a 120 second timeout,
1875 // but the preferred behavior (and that taken by many drives) is to immediately report 2/4/x
1876 // on OPC and similar commands. Thus, retries must occur for at least 160 seconds
1877 // (120 seconds + four 10 second retries) as a conservative guess.
1878 // Note: 160s retry time is also a result of discussion with OEMs for case of 2/4/7 and 2/4/8.
1879 if (*Retry)
1880 {
1881 if ((Total100nsSinceFirstSend < 0) ||
1882 (((senseBuffer->SenseKey &0xf) == SCSI_SENSE_HARDWARE_ERROR) && (senseBuffer->AdditionalSenseCode == 0x09)))
1883 {
1884 // time information is not valid. use default retry count.
1885 // or if it's SERVO FAILURE, use retry count instead of 160s retry.
1886 *Retry = (RetriedCount <= TOTAL_COUNT_RETRY_DEFAULT);
1887 }
1888 else if (Total100nsSinceFirstSend > SECONDS_TO_100NS_UNITS(TOTAL_SECONDS_RETRY_TIME_WRITE))
1889 {
1890 *Retry = FALSE;
1891 }
1892
1893 // How long should we request a delay for during writing? This depends entirely on
1894 // the current write speed of the drive. If we request retries too quickly,
1895 // we can overload the processor on the drive (resulting in garbage being written),
1896 // but too slowly results in lesser performance.
1897 //
1898 *RetryIntervalIn100ns = DeviceExtension->DeviceAdditionalData.ReadWriteRetryDelay100nsUnits;
1899
1900 } // end retry for 160 seconds modification
1901 }
1902 else if (opCode == SCSIOP_GET_PERFORMANCE)
1903 {
1905 {
1906 // This is a HACK.
1907 // Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
1908 // underrun (i.e. success, and the buffer is longer than needed).
1909 // So treat this as a success.
1910 // When the caller of this function sees that the status was changed to success,
1911 // it will add the transferred length to the original irp.
1913 *Retry = FALSE;
1914 }
1915
1918 {
1919 // If get configuration command is failing and if the request type is TYPE ONE
1920 // then most likely the device does not support this request type. Set the
1921 // flag so that the TYPE ONE requests will be tried as TYPE ALL requets.
1924 (((PCDB)Srb->Cdb)->GET_CONFIGURATION.RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE))
1925 {
1926
1927 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1928 "TYPE ONE GetConfiguration failed. Set hack flag and retry.\n"));
1929 SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG);
1930 *Retry = TRUE;
1931 }
1932 }
1933
1934 // limit retries to GET_PERFORMANCE commands to default retry count
1935 if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT)
1936 {
1937 *Retry = FALSE;
1938 }
1939 }
1940 else // default handler -- checks for retry count only.
1941 {
1942 if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT)
1943 {
1944 *Retry = FALSE;
1945 }
1946 }
1947
1948 return;
1949}
1950
1951
1952VOID
1954 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1956 _In_ BOOLEAN OverrideVerifyVolume,
1959 )
1960/*++
1961
1962Routine Description:
1963
1964 Based on IOCTL code, modify the interpretion result.
1965
1966Arguments:
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
1976Return 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 {
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
2037BOOLEAN
2039 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2040 _In_ WDFREQUEST Request,
2042 _In_ ULONG RetriedCount,
2045 LONGLONG* RetryIntervalIn100ns
2046 )
2047/*++
2048
2049SenseInfoInterpret()
2050
2051Routine 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
2057Arguments:
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
2064Return 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
2100 {
2101 // Log anything remotely incorrect about paging i/o
2102 logContext.LogError = TRUE;
2103 logContext.UniqueErrorValue = 301;
2105 }
2106
2107 // must handle the SRB_STATUS_INTERNAL_ERROR case first,
2108 // as it has all the flags set.
2110 {
2111 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
2112 "SenseInfoInterpret: Internal Error code is %x\n",
2114
2115 retry = FALSE;
2117 }
2119 {
2120 retry = FALSE;
2122 logContext.LogError = FALSE;
2123 }
2125 (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)))
2126 {
2127 UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f);
2129 UCHAR additionalSenseCodeQual = 0;
2130
2131 // Zero the additional sense code and additional sense code qualifier
2132 // if they were not returned by the device.
2133 readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength);
2134 if (readSector > Srb->SenseInfoBufferLength)
2135 {
2136 readSector = Srb->SenseInfoBufferLength;
2137 }
2138
2140 senseBuffer->AdditionalSenseCode : 0;
2141 additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ?
2142 senseBuffer->AdditionalSenseCodeQualifier : 0;
2143
2144 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2145 "SCSI Error - \n"
2146 "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
2147 "\tsrb status: %X; sense: %02X/%02X/%02X; Retried count: %d\n\n",
2148 Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5],
2149 Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11],
2150 Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15],
2152 senseKey,
2154 additionalSenseCodeQual,
2155 RetriedCount));
2156
2158 {
2159 ULONG mediaChangeCount;
2160
2161 // A media change may have occured so increment the change count for the physical device
2162 mediaChangeCount = InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
2163 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2164 "SenseInfoInterpret: Media change count for device %d incremented to %#lx\n",
2165 DeviceExtension->DeviceNumber, mediaChangeCount));
2166 }
2167
2168 if ((zpoddInfo != NULL) &&
2169 (((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode == SCSIOP_TEST_UNIT_READY))
2170 {
2171 // This sense code is in response to the Test Unit Ready sent during delayed power down
2172 // request. Copy the sense data into the zpoddInfo structure for later processing.
2173 zpoddInfo->SenseKey = senseKey;
2175 zpoddInfo->AdditionalSenseCodeQualifier = additionalSenseCodeQual;
2176 }
2177
2178 // Interpret error by specific ASC & ASCQ first,
2179 // If the error is not handled, interpret using f
2180 {
2181 BOOLEAN notHandled = FALSE;
2182 notHandled = SenseInfoInterpretByAdditionalSenseCode(DeviceExtension,
2183 Srb,
2185 additionalSenseCodeQual,
2186 Status,
2187 &retry,
2188 &retryIntervalInSeconds,
2189 &logContext);
2190
2191 if (notHandled)
2192 {
2193 SenseInfoInterpretBySenseKey(DeviceExtension,
2194 senseBuffer,
2195 senseKey,
2196 Status,
2197 &retry,
2198 &retryIntervalInSeconds,
2199 &logContext);
2200 }
2201 }
2202
2203 // Try to determine the bad sector from the inquiry data.
2204 if ((IS_SCSIOP_READWRITE(((PCDB)Srb->Cdb)->CDB10.OperationCode)) ||
2205 (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY) ||
2206 (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY16))
2207 {
2208 ULONG index;
2209 readSector = 0;
2210
2211 for (index = 0; index < 4; index++)
2212 {
2213 logContext.BadSector = (logContext.BadSector << 8) | senseBuffer->Information[index];
2214 }
2215
2216 for (index = 0; index < 4; index++)
2217 {
2218 readSector = (readSector << 8) | Srb->Cdb[index+2];
2219 }
2220
2221 index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) |
2222 ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb;
2223
2224 // Make sure the bad sector is within the read sectors.
2225 if (!(logContext.BadSector >= readSector && logContext.BadSector < (readSector + index)))
2226 {
2227 logContext.BadSector = readSector;
2228 }
2229 }
2230 }
2231 else
2232 {
2233 // Request sense buffer not valid. No sense information
2234 // to pinpoint the error. Return general request fail.
2235 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2236 "SCSI Error - \n"
2237 "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"
2238 "\tsrb status: %X; sense info not valid; Retried count: %d\n\n",
2239 Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5],
2240 Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11],
2241 Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15],
2243 RetriedCount));
2244
2245 SenseInfoInterpretBySrbStatus(DeviceExtension,
2246 Srb,
2247 RetriedCount,
2248 Status,
2249 &retry,
2250 &retryIntervalInSeconds,
2251 &logContext);
2252 }
2253
2254 // all functions using unit - seconds for retry Interval already be called.
2255 *RetryIntervalIn100ns = SECONDS_TO_100NS_UNITS(retryIntervalInSeconds);
2256
2257 // call the device specific error handler if it has one.
2258 // DeviceErrorHandlerForMmmc() for all MMC devices
2259 // or DeviceErrorHandlerForHitachiGD2000() for HITACHI GD-2000, HITACHI DVD-ROM GD-2000
2260 if (DeviceExtension->DeviceAdditionalData.ErrorHandler)
2261 {
2262 DeviceExtension->DeviceAdditionalData.ErrorHandler(DeviceExtension, Srb, Status, &retry);
2263 }
2264
2265 // Refine retry based on SCSI command
2267 Srb,
2268 RetriedCount,
2269 total100nsSinceFirstSend,
2270 overrideVerifyVolume,
2271 &retry,
2272 Status,
2273 RetryIntervalIn100ns);
2274
2275 // Refine retry based on IOCTL code.
2276 if (majorFunctionCode == IRP_MJ_DEVICE_CONTROL)
2277 {
2279 ioControlCode,
2280 overrideVerifyVolume,
2281 &retry,
2282 Status);
2283 }
2284
2285 // LOG the error:
2286 // Always log the error in our internal log.
2287 // If logError is set, also log the error in the system log.
2288 SenseInfoLogError(DeviceExtension,
2289 Srb,
2290 majorFunctionCode,
2291 ioControlCode,
2292 RetriedCount,
2293 Status,
2294 &retry,
2295 &logContext);
2296
2297 // all process about the error done. check if the irp was cancelled.
2298 if ((!NT_SUCCESS(*Status)) && retry)
2299 {
2300 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
2301
2302 if ((requestContext->OriginalRequest != NULL) &&
2303 WdfRequestIsCanceled(requestContext->OriginalRequest)
2304 )
2305 {
2306 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2307 "Request %p was cancelled when it would have been retried\n",
2308 requestContext->OriginalRequest));
2309
2311 retry = FALSE;
2312 *RetryIntervalIn100ns = 0;
2313 }
2314 }
2315
2316 // now, all decisions are made. display trace information.
2317 if (retry)
2318 {
2319 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2320 "Command shall be retried in %2I64d.%03I64d seconds\n",
2321 (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND),
2322 (*RetryIntervalIn100ns / 10000) % 1000
2323 ));
2324 }
2325 else
2326 {
2327 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
2328 "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n",
2329 senseBuffer->SenseKey,
2330 senseBuffer->AdditionalSenseCode,
2331 senseBuffer->AdditionalSenseCodeQualifier
2332 ));
2333 }
2334
2335 return retry;
2336
2337} // end SenseInfoInterpret()
2338
2339
2340BOOLEAN
2342 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2346 LONGLONG* RetryIntervalIn100ns
2347 )
2348/*++
2349
2350SenseInfoInterpretForZPODD()
2351
2352Routine 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
2358Arguments:
2359
2360 Device - Supplies the device object associated with this request.
2361 Srb - Supplies the scsi request block which failed.
2362
2363Return 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 }
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
2466BOOLEAN
2468 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2469 _In_ WDFREQUEST Request,
2471 _In_ ULONG RetriedCount,
2474 LONGLONG* RetryIntervalIn100ns
2475 )
2476/*++
2477
2478Routine Description:
2479
2480Interpret the error, process it.
2481 1. Release device queue if it's frozen.
2482 2. Interpret and process the error.
2483
2484Arguments:
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
2491Return 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
2506 {
2507 // request succeeded.
2508 if ((zpoddInfo != NULL) &&
2509 (zpoddInfo->BecomingReadyRetryCount > 0))
2510 {
2511 zpoddInfo->BecomingReadyRetryCount = 0;
2512 }
2513
2515 retry = FALSE;
2516 }
2517 else
2518 {
2519 // request failed. We need to process the error.
2520
2521 // 1. Release the queue if it is frozen.
2523 {
2524 DeviceReleaseQueue(DeviceExtension->Device);
2525 }
2526
2527 if ((zpoddInfo != NULL) &&
2528 ((zpoddInfo->RetryFirstCommand != FALSE) || (zpoddInfo->BecomingReadyRetryCount > 0)))
2529 {
2530 retry = SenseInfoInterpretForZPODD(DeviceExtension,
2531 Srb,
2532 Status,
2533 &retryIntervalIn100ns);
2534 }
2535
2536 if (retry == FALSE)
2537 {
2538 // 2. Error Processing
2539 if ((zpoddInfo != NULL) &&
2540 (zpoddInfo->BecomingReadyRetryCount > 0))
2541 {
2542 zpoddInfo->BecomingReadyRetryCount = 0;
2543 }
2544
2545 retry = SenseInfoInterpret(DeviceExtension,
2546 Request,
2547 Srb,
2548 RetriedCount,
2549 Status,
2550 &retryIntervalIn100ns);
2551 }
2552 }
2553
2554 if (RetryIntervalIn100ns != NULL)
2555 {
2556 *RetryIntervalIn100ns = retryIntervalIn100ns;
2557 }
2558
2559 return retry;
2560}
2561
2562
2563BOOLEAN
2565 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2566 _In_ ULONG RetriedCount,
2569 LONGLONG* RetryIntervalIn100ns
2570 )
2571/*++
2572
2573Routine Description:
2574
2575 to analyze the error occurred and set the status, retry interval and decide to retry or not.
2576
2577Arguments:
2578
2579 DeviceExtension - device extension
2580 RetriedCount - already retried count.
2581
2582Return 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
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
#define index(s, c)
Definition: various.h:29
VOID DeviceSetMediaChangeStateEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:751
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define PLAY_ACTIVE(x)
Definition: cdrom.h:698
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
VOID DeviceReleaseQueue(_In_ WDFDEVICE Device)
Definition: common.c:1179
#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG
Definition: cdrom.h:99
#define IS_SCSIOP_READ(opCode)
Definition: cdrom.h:791
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
FORCEINLINE BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
#define SECONDS_TO_100NS_UNITS(x)
Definition: cdrom.h:1488
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
VOID DevicePerfIncrementErrorCount(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: common.c:1378
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define UNIT_100NS_PER_SECOND
Definition: cdrom.h:1487
VOID DeviceSendStartUnit(_In_ WDFDEVICE Device)
Definition: common.c:877
EVT_WDF_WORKITEM DeviceRestoreDefaultSpeed
Definition: cdrom.h:1180
struct _CDROM_ERROR_LOG_DATA * PCDROM_ERROR_LOG_DATA
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
#define FDO_HACK_NO_STREAMING
Definition: cdromp.h:137
#define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS
Definition: cdromp.h:50
#define BECOMING_READY_RETRY_INTERNVAL_IN_100NS
Definition: cdromp.h:262
#define NUM_ERROR_LOG_ENTRIES
Definition: cdromp.h:323
@ MediaPresent
Definition: cdromp.h:82
@ MediaNotPresent
Definition: cdromp.h:83
@ MediaUnavailable
Definition: cdromp.h:84
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED
Definition: cdrw_hw.h:1315
#define SCSI_SENSE_NO_SENSE
Definition: cdrw_hw.h:1187
#define SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED
Definition: cdrw_hw.h:1324
#define SCSIOP_READ_CD
Definition: cdrw_hw.h:967
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SCSI_SENSEQ_INCOMPATIBLE_FORMAT
Definition: cdrw_hw.h:1323
#define SCSISTAT_RESERVATION_CONFLICT
Definition: cdrw_hw.h:1084
#define SCSI_SENSEQ_AUTHENTICATION_FAILURE
Definition: cdrw_hw.h:1390
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define SCSI_ADSENSE_REC_DATA_NOECC
Definition: cdrw_hw.h:1211
#define SCSI_ADSENSE_INVALID_LUN
Definition: cdrw_hw.h:1266
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
#define SCSIOP_READ_TOC
Definition: cdrw_hw.h:927
#define SCSI_ADSENSE_INVALID_CDB
Definition: cdrw_hw.h:1265
#define SCSI_ADSENSE_WRITE_PROTECT
Definition: cdrw_hw.h:1268
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSIOP_RELEASE_UNIT
Definition: cdrw_hw.h:893
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define SCSIOP_GET_PERFORMANCE
Definition: cdrw_hw.h:959
#define SCSI_SENSEQ_KEY_NOT_ESTABLISHED
Definition: cdrw_hw.h:1392
#define SCSI_SENSE_MEDIUM_ERROR
Definition: cdrw_hw.h:1190
#define SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION
Definition: cdrw_hw.h:1393
struct _SENSE_DATA * PSENSE_DATA
#define SCSI_SENSEQ_UNKNOWN_FORMAT
Definition: cdrw_hw.h:1322
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
struct _SENSE_DATA SENSE_DATA
#define SCSI_SENSEQ_CAUSE_NOT_REPORTABLE
Definition: cdrw_hw.h:1312
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define SCSI_SENSEQ_KEY_NOT_PRESENT
Definition: cdrw_hw.h:1391
#define SCSIOP_READ6
Definition: cdrw_hw.h:874
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
#define SCSI_ADSENSE_REC_DATA_ECC
Definition: cdrw_hw.h:1212
#define NOT_READY_RETRY_INTERVAL
Definition: cdrw_hw.h:1094
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
#define SCSIOP_SEND_KEY
Definition: cdrw_hw.h:951
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
#define SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR
Definition: cdrw_hw.h:1395
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define SCSIOP_READ_CD_MSF
Definition: cdrw_hw.h:964
union _CDB * PCDB
#define SCSI_SENSE_BLANK_CHECK
Definition: cdrw_hw.h:1195
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
#define SCSI_SENSE_RECOVERED_ERROR
Definition: cdrw_hw.h:1188
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:484
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
switch(r->id)
Definition: btrfs.c:3046
#define SCSIOP_VERIFY16
Definition: scsi.h:916
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:362
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:361
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE
Definition: srb.h:359
#define SRB_STATUS_NO_HBA
Definition: srb.h:356
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:363
#define SRB_STATUS_UNEXPECTED_BUS_FREE
Definition: srb.h:358
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_ABORTED
Definition: srb.h:342
#define SRB_STATUS_INVALID_PATH_ID
Definition: srb.h:347
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:373
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:351
#define SRB_STATUS_PARITY_ERROR
Definition: srb.h:354
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
Status
Definition: gdiplustypes.h:25
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
if(dx< 0)
Definition: linetemp.h:194
* PNTSTATUS
Definition: strlen.c:14
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_
Definition: ms_sal.h:378
#define _Out_range_(lb, ub)
Definition: ms_sal.h:572
#define _Deref_out_range_(lb, ub)
Definition: ms_sal.h:575
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:675
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:103
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE
Definition: ntddmmc.h:17
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IO_ERR_NOT_READY
Definition: ntiologc.h:42
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define IO_RECOVERED_VIA_ECC
Definition: ntiologc.h:60
#define IO_ERR_BAD_BLOCK
Definition: ntiologc.h:34
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
#define STATUS_CLEANER_CARTRIDGE_INSTALLED
Definition: ntstatus.h:218
#define STATUS_CSS_AUTHENTICATION_FAILURE
Definition: ntstatus.h:882
#define STATUS_COPY_PROTECTION_FAILURE
Definition: ntstatus.h:881
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
#define STATUS_CSS_KEY_NOT_ESTABLISHED
Definition: ntstatus.h:884
#define STATUS_CSS_SCRAMBLED_SECTOR
Definition: ntstatus.h:885
#define STATUS_CSS_KEY_NOT_PRESENT
Definition: ntstatus.h:883
#define STATUS_CSS_RESETS_EXHAUSTED
Definition: ntstatus.h:887
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
@ DvdSetRpcKey
Definition: ntddcdvd.h:169
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define offsetof(TYPE, MEMBER)
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
UCHAR additionalSenseCode
Definition: scsi.h:4020
#define SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
#define SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED
Definition: scsi.h:692
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
#define SCSIOP_READ_TRACK_INFORMATION
Definition: scsi.h:315
#define SCSI_SESNEQ_COMM_CRC_ERROR
Definition: scsi.h:738
#define SCSI_ADSENSE_LUN_COMMUNICATION
Definition: scsi.h:653
#define SCSI_ADSENSE_NO_SEEK_COMPLETE
Definition: scsi.h:650
#define SCSI_ADSENSE_INSUFFICIENT_TIME_FOR_OPERATION
Definition: scsi.h:677
#define SCSI_SENSEQ_WRITE_PROTECT_DISABLE
Definition: scsi.h:881
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCodeQualifier
Definition: scsi.h:3748
#define SCSIOP_READ_DISK_INFORMATION
Definition: scsi.h:313
UCHAR senseKey
Definition: scsi.h:4019
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
Definition: scsi.h:684
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
#define MAX_ADDITIONAL_SENSE_BYTES
Definition: scsi.h:600
_In_ UCHAR _Out_opt_ PUCHAR _Out_opt_ PUCHAR AdditionalSenseCode
Definition: scsi.h:3746
_In_ UCHAR _Out_opt_ PUCHAR SenseKey
Definition: scsi.h:3745
#define SCSI_SENSEQ_WRITE_PROTECT_ENABLE
Definition: scsi.h:880
BOOLEAN validSense
Definition: scsi.h:4018
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
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
NTSTATUS DeviceErrorHandlerForMmc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
Definition: sense.c:87
struct _ERROR_LOG_CONTEXT * PERROR_LOG_CONTEXT
BOOLEAN SenseInfoInterpretForZPODD(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Out_ NTSTATUS *Status, _Out_ _Out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2341
VOID SenseInfoInterpretRefineByScsiCommand(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _In_ LONGLONG Total100nsSinceFirstSend, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status, _Inout_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:1663
VOID SenseInfoInterpretBySrbStatus(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Inout_ NTSTATUS *Status, _Inout_ BOOLEAN *Retry, _Out_ _Deref_out_range_(0, 100) ULONG *RetryIntervalInSeconds, _Inout_ PERROR_LOG_CONTEXT LogContext)
Definition: sense.c:1262
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 TOTAL_SECONDS_RETRY_TIME_WRITE
Definition: sense.c:75
#define TOTAL_COUNT_RETRY_READ_CAPACITY
Definition: sense.c:72
#define TOTAL_COUNT_RETRY_MODESENSE
Definition: sense.c:71
VOID SenseInfoInterpretRefineByIoControl(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ BOOLEAN OverrideVerifyVolume, _Inout_ BOOLEAN *Retry, _Inout_ NTSTATUS *Status)
Definition: sense.c:1953
struct _ERROR_LOG_CONTEXT ERROR_LOG_CONTEXT
#define TOTAL_COUNT_RETRY_DEFAULT
Definition: sense.c:69
VOID SenseInfoLogError(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoControlCode, _In_ ULONG RetriedCount, _In_ NTSTATUS *Status, _In_ BOOLEAN *Retry, _Inout_ PERROR_LOG_CONTEXT LogContext)
Definition: sense.c:1430
VOID SenseInfoRequestGetInformation(_In_ WDFREQUEST Request, _Out_ UCHAR *MajorFunctionCode, _Out_ ULONG *IoControlCode, _Out_ BOOLEAN *OverrideVerifyVolume, _Out_ ULONGLONG *Total100nsSinceFirstSend)
Definition: sense.c:426
BOOLEAN 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
BOOLEAN SenseInfoInterpret(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2038
BOOLEAN 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
NTSTATUS DeviceErrorHandlerForHitachiGD2000(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
Definition: sense.c:361
#define TOTAL_COUNT_RETRY_LOCK_MEDIA
Definition: sense.c:70
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
LARGE_INTEGER TickCount
Definition: cdromp.h:303
SCSI_REQUEST_BLOCK Srb
Definition: cdromp.h:313
SENSE_DATA SenseData
Definition: cdromp.h:319
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
LARGE_INTEGER TimeSentDownFirstTime
Definition: cdrom.h:636
BOOLEAN LogError
Definition: sense.c:79
NTSTATUS ErrorCode
Definition: sense.c:81
ULONG UniqueErrorValue
Definition: sense.c:82
BOOLEAN ErrorUnhandled
Definition: sense.c:80
ULONG BadSector
Definition: sense.c:83
struct _IO_STACK_LOCATION::@1575::@1576 DeviceIoControl
union _IO_STACK_LOCATION::@1575 Parameters
UCHAR SenseInfoBufferLength
Definition: srb.h:259
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
PVOID SenseInfoBuffer
Definition: srb.h:264
UCHAR ScsiStatus
Definition: srb.h:252
ULONG InternalStatus
Definition: srb.h:269
ULONG SrbFlags
Definition: srb.h:260
UCHAR SrbStatus
Definition: srb.h:251
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
UCHAR Information[4]
Definition: cdrw_hw.h:1172
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
UCHAR IncorrectLength
Definition: cdrw_hw.h:1169
UCHAR SenseKey
Definition: cdrw_hw.h:1167
WDFOBJECT ParentObject
Definition: wdfobject.h:130
UCHAR AdditionalSenseCode
Definition: cdromp.h:280
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
UCHAR AdditionalSenseCodeQualifier
Definition: cdromp.h:281
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_NONEXISTENT_SECTOR
Definition: udferr_usr.h:143
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
Definition: cdrw_hw.h:28
struct _CDB::_CDB10 CDB10
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_SEND_KEY SEND_KEY
struct _CDB::_READ12 READ12
struct _CDB::_WRITE12 WRITE12
struct _CDB::_CDB16 CDB16
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
@ BusRelations
Definition: iotypes.h:2152
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2042
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
#define NT_ASSERT
Definition: rtlfuncs.h:3324
unsigned char UCHAR
Definition: xmlstorage.h:181