1 /*++
2
3 Copyright (C) Microsoft Corporation, 1991 - 2010
4
5 Module Name:
6
7 classp.h
8
9 Abstract:
10
11 Private header file for classpnp.sys modules. This contains private
12 structure and function declarations as well as constant values which do
13 not need to be exported.
14
15 Author:
16
17 Environment:
18
19 kernel mode only
20
21 Notes:
22
23
24 Revision History:
25
26 --*/
27
28 #define RTL_USE_AVL_TABLES 0
29
30 #include <stddef.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33
34 #include <ntddk.h>
35
36 #ifdef __REACTOS__
37 #include <pseh/pseh2.h>
38 #endif
39
40 #include <scsi.h>
41
42 #include <wmidata.h>
43 #include <classpnp.h>
44 #include <storduid.h>
45
46 #if CLASS_INIT_GUID
47 #include <initguid.h>
48 #endif
49
50 #include <mountdev.h>
51 #include <ioevent.h>
52 #include <ntstrsafe.h>
53 #include <ntintsafe.h>
54
55 #include <wdmguid.h>
56
57 #if (NTDDI_VERSION >= NTDDI_WIN8)
58
59 #include <ntpoapi.h>
60
61 #include <srbhelper.h>
62
63 #endif
64
65 #ifdef __REACTOS__
66 #undef MdlMappingNoExecute
67 #define MdlMappingNoExecute 0
68 #define NonPagedPoolNx NonPagedPool
69 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
70 #undef POOL_NX_ALLOCATION
71 #define POOL_NX_ALLOCATION 0
72 #endif
73
74 //
75 // Set component ID for DbgPrintEx calls
76 //
77 #ifndef DEBUG_COMP_ID
78 #define DEBUG_COMP_ID DPFLTR_CLASSPNP_ID
79 #endif
80
81 //
82 // Include header file and setup GUID for tracing
83 //
84 #include <storswtr.h>
85 #define WPP_GUID_CLASSPNP (FA8DE7C4, ACDE, 4443, 9994, C4E2359A9EDB)
86 #ifndef WPP_CONTROL_GUIDS
87 #define WPP_CONTROL_GUIDS WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_CLASSPNP)
88 #endif
89
90 /*
91 * IA64 requires 8-byte alignment for pointers, but the IA64 NT kernel expects 16-byte alignment
92 */
93 #ifdef _WIN64
94 #define PTRALIGN DECLSPEC_ALIGN(16)
95 #else
96 #define PTRALIGN
97 #endif
98
99
100 extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[];
101
102 extern GUID ClassGuidQueryRegInfoEx;
103 extern GUID ClassGuidSenseInfo2;
104 extern GUID ClassGuidWorkingSet;
105 extern GUID ClassGuidSrbSupport;
106
107 extern ULONG ClassMaxInterleavePerCriticalIo;
108
109
110 #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
111
112 #define CLASSP_REG_SUBKEY_NAME (L"Classpnp")
113
114 #define CLASSP_REG_HACK_VALUE_NAME (L"HackMask")
115 #define CLASSP_REG_MMC_DETECTION_VALUE_NAME (L"MMCDetectionState")
116 #define CLASSP_REG_WRITE_CACHE_VALUE_NAME (L"WriteCacheEnableOverride")
117 #define CLASSP_REG_PERF_RESTORE_VALUE_NAME (L"RestorePerfAtCount")
118 #define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME (L"UserRemovalPolicy")
119 #define CLASSP_REG_IDLE_INTERVAL_NAME (L"IdleInterval")
120 #define CLASSP_REG_IDLE_ACTIVE_MAX (L"IdleOutstandingIoMax")
121 #define CLASSP_REG_IDLE_PRIORITY_SUPPORTED (L"IdlePrioritySupported")
122 #define CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED (L"AccessAlignmentQueryNotSupported")
123 #define CLASSP_REG_DISBALE_IDLE_POWER_NAME (L"DisableIdlePowerManagement")
124 #define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS (L"IdleTimeoutInSeconds")
125 #define CLASSP_REG_DISABLE_D3COLD (L"DisableD3Cold")
126 #define CLASSP_REG_QERR_OVERRIDE_MODE (L"QERROverrideMode")
127 #define CLASSP_REG_LEGACY_ERROR_HANDLING (L"LegacyErrorHandling")
128 #define CLASSP_REG_COPY_OFFLOAD_MAX_TARGET_DURATION (L"CopyOffloadMaxTargetDuration")
129
130 #define CLASS_PERF_RESTORE_MINIMUM (0x10)
131 #define CLASS_ERROR_LEVEL_1 (0x4)
132 #define CLASS_ERROR_LEVEL_2 (0x8)
133 #define CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO (0x4)
134
135 #define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
136 #define FDO_HACK_GESN_IS_BAD (0x00000002)
137 #define FDO_HACK_NO_SYNC_CACHE (0x00000004)
138 #define FDO_HACK_NO_RESERVE6 (0x00000008)
139 #define FDO_HACK_GESN_IGNORE_OPCHANGE (0x00000010)
140
141 #define FDO_HACK_VALID_FLAGS (0x0000001F)
142 #define FDO_HACK_INVALID_FLAGS (~FDO_HACK_VALID_FLAGS)
143
144 /*
145 * Lots of retries of synchronized SCSI commands that devices may not
146 * even support really slows down the system (especially while booting).
147 * (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
148 * If a disk cannot return a small initialization buffer at startup
149 * in two attempts (with delay interval) then we cannot expect it to return
150 * data consistently with four retries.
151 * So don't set the retry counts as high here as for data SRBs.
152 *
153 * If we find that these requests are failing consecutively,
154 * despite the retry interval, on otherwise reliable media,
155 * then we should either increase the retry interval for
156 * that failure or (by all means) increase these retry counts as appropriate.
157 */
158 #define NUM_LOCKMEDIAREMOVAL_RETRIES 1
159 #define NUM_MODESENSE_RETRIES 1
160 #define NUM_MODESELECT_RETRIES 1
161 #define NUM_DRIVECAPACITY_RETRIES 1
162 #define NUM_THIN_PROVISIONING_RETRIES 32
163
164 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
165
166 //
167 // New code should use the MAXIMUM_RETRIES value.
168 //
169 #define NUM_IO_RETRIES MAXIMUM_RETRIES
170 #define LEGACY_NUM_IO_RETRIES 8
171
172 #else
173
174 /*
175 * We retry failed I/O requests at 1-second intervals.
176 * In the case of a failure due to bus reset, we want to make sure that we retry after the allowable
177 * reset time. For SCSI, the allowable reset time is 5 seconds. ScsiPort queues requests during
178 * a bus reset, which should cause us to retry after the reset is over; but the requests queued in
179 * the miniport are failed all the way back to us immediately. In any event, in order to make
180 * extra sure that our retries span the allowable reset time, we should retry more than 5 times.
181 */
182 #define NUM_IO_RETRIES 8
183
184 #endif // NTDDI_VERSION >= NTDDI_WINBLUE
185
186 #define CLASS_FILE_OBJECT_EXTENSION_KEY 'eteP'
187 #define CLASSP_VOLUME_VERIFY_CHECKED 0x34
188
189 #define CLASS_TAG_PRIVATE_DATA 'CPcS'
190 #define CLASS_TAG_SENSE2 '2ScS'
191 #define CLASS_TAG_WORKING_SET 'sWcS'
192 #define CLASSPNP_POOL_TAG_GENERIC 'pCcS'
193 #define CLASSPNP_POOL_TAG_TOKEN_OPERATION 'oTcS'
194 #define CLASSPNP_POOL_TAG_SRB 'rScS'
195 #define CLASSPNP_POOL_TAG_VPD 'pVcS'
196 #define CLASSPNP_POOL_TAG_LOG_MESSAGE 'mlcS'
197 #define CLASSPNP_POOL_TAG_ADDITIONAL_DATA 'DAcS'
198 #define CLASSPNP_POOL_TAG_FIRMWARE 'wFcS'
199
200 //
201 // Macros related to Token Operation commands
202 //
203 #define MAX_LIST_IDENTIFIER MAXULONG
204 #define NUM_POPULATE_TOKEN_RETRIES 1
205 #define NUM_WRITE_USING_TOKEN_RETRIES 2
206 #define NUM_RECEIVE_TOKEN_INFORMATION_RETRIES 2
207 #define MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH MAXUSHORT
208 #define MAX_RECEIVE_TOKEN_INFORMATION_PARAMETER_DATA_LENGTH MAXULONG
209 #define MAX_TOKEN_TRANSFER_SIZE MAXULONGLONG
210 #define MAX_NUMBER_BLOCKS_PER_BLOCK_DEVICE_RANGE_DESCRIPTOR MAXULONG
211 #define DEFAULT_MAX_TARGET_DURATION 4 // 4sec
212 #define DEFAULT_MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN (64ULL * 1024 * 1024) // 64MB
213 #define MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN (256ULL * 1024 * 1024) // 256MB
214 #define MIN_TOKEN_LIST_IDENTIFIERS 256
215 #define MAX_TOKEN_LIST_IDENTIFIERS MAXULONG
216 #define MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS 64
217
218 #define REG_DISK_CLASS_CONTROL L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\DISK"
219 #define REG_MAX_LIST_IDENTIFIER_VALUE L"MaximumListIdentifier"
220
221 #define VPD_PAGE_HEADER_SIZE 0x04
222
223
224 //
225 // Number of times to retry get LBA status in case of an error
226 // that can be caused by VPD data change
227 //
228
229 #define GET_LBA_STATUS_RETRY_COUNT_MAX (2)
230
231 extern ULONG MaxTokenOperationListIdentifier;
232 extern volatile ULONG TokenOperationListIdentifier;
233
234 extern LIST_ENTRY IdlePowerFDOList;
235 extern PVOID PowerSettingNotificationHandle;
236 extern PVOID ScreenStateNotificationHandle;
237 extern BOOLEAN ClasspScreenOff;
238 extern KGUARDED_MUTEX IdlePowerFDOListMutex;
239 extern ULONG DiskIdleTimeoutInMS;
240
241 //
242 // Definitions from ntos\rtl\time.c
243 //
244
245 extern CONST LARGE_INTEGER Magic10000;
246 #define SHIFT10000 13
247
248 //
249 // Constant to help wih various time conversions
250 //
251 #define CONST_MSECS_PER_SEC 1000
252
253 #define Convert100nsToMilliseconds(LARGE_INTEGER) \
254 ( \
255 RtlExtendedMagicDivide((LARGE_INTEGER), Magic10000, SHIFT10000) \
256 )
257
258 #define ConvertMillisecondsTo100ns(MILLISECONDS) ( \
259 RtlExtendedIntegerMultiply ((MILLISECONDS), 10000) \
260 )
261
262 typedef struct _MEDIA_CHANGE_DETECTION_INFO {
263
264 //
265 // Mutex to synchronize enable/disable requests and media state changes
266 //
267
268 KMUTEX MediaChangeMutex;
269
270 //
271 // The current state of the media (present, not present, unknown)
272 // protected by MediaChangeSynchronizationEvent
273 //
274
275 MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState;
276
277 //
278 // This is a count of how many time MCD has been disabled. if it is
279 // set to zero, then we'll poll the device for MCN events with the
280 // then-current method (ie. TEST UNIT READY or GESN). this is
281 // protected by MediaChangeMutex
282 //
283
284 LONG MediaChangeDetectionDisableCount;
285
286
287 //
288 // The timer value to support media change events. This is a countdown
289 // value used to determine when to poll the device for a media change.
290 // The max value for the timer is 255 seconds. This is not protected
291 // by an event -- simply InterlockedExchanged() as needed.
292 //
293
294 LONG MediaChangeCountDown;
295
296 //
297 // recent changes allowed instant retries of the MCN irp. Since this
298 // could cause an infinite loop, keep a count of how many times we've
299 // retried immediately so that we can catch if the count exceeds an
300 // arbitrary limit.
301 //
302
303 LONG MediaChangeRetryCount;
304
305 //
306 // use GESN if it's available
307 //
308
309 struct {
310 BOOLEAN Supported;
311 BOOLEAN HackEventMask;
312 UCHAR EventMask;
313 UCHAR NoChangeEventMask;
314 PUCHAR Buffer;
315 PMDL Mdl;
316 ULONG BufferSize;
317 } Gesn;
318
319 //
320 // If this value is one, then the irp is currently in use.
321 // If this value is zero, then the irp is available.
322 // Use InterlockedCompareExchange() to set from "available" to "in use".
323 // ASSERT that InterlockedCompareExchange() showed previous value of
324 // "in use" when changing back to "available" state.
325 // This also implicitly protects the MediaChangeSrb and SenseBuffer
326 //
327
328 LONG MediaChangeIrpInUse;
329
330 //
331 // Pointer to the irp to be used for media change detection.
332 // protected by Interlocked MediaChangeIrpInUse
333 //
334
335 PIRP MediaChangeIrp;
336
337 //
338 // The srb for the media change detection.
339 // protected by Interlocked MediaChangeIrpInUse
340 //
341
342 #if (NTDDI_VERSION >= NTDDI_WIN8)
343 union {
344 SCSI_REQUEST_BLOCK Srb;
345 STORAGE_REQUEST_BLOCK SrbEx;
346 UCHAR SrbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE];
347 } MediaChangeSrb;
348 #else
349 SCSI_REQUEST_BLOCK MediaChangeSrb;
350 #endif
351 PUCHAR SenseBuffer;
352 ULONG SrbFlags;
353
354 //
355 // Second timer to keep track of how long the media change IRP has been
356 // in use. If this value exceeds the timeout (#defined) then we should
357 // print out a message to the user and set the MediaChangeIrpLost flag
358 // protected by using Interlocked() operations in ClasspSendMediaStateIrp,
359 // the only routine which should modify this value.
360 //
361
362 LONG MediaChangeIrpTimeInUse;
363
364 //
365 // Set by CdRomTickHandler when we determine that the media change irp has
366 // been lost
367 //
368
369 BOOLEAN MediaChangeIrpLost;
370
371 //
372 // Buffer size of SenseBuffer
373 //
374 UCHAR SenseBufferLength;
375
376 } MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO;
377
378 typedef enum {
379 SimpleMediaLock,
380 SecureMediaLock,
381 InternalMediaLock
382 } MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
383
384 typedef struct _FAILURE_PREDICTION_INFO {
385 FAILURE_PREDICTION_METHOD Method;
386 ULONG CountDown; // Countdown timer
387 ULONG Period; // Countdown period
388
389 PIO_WORKITEM WorkQueueItem;
390
391 KEVENT Event;
392
393 //
394 // Timestamp of last time the failure prediction info was queried.
395 //
396 LARGE_INTEGER LastFailurePredictionQueryTime;
397
398 } FAILURE_PREDICTION_INFO, *PFAILURE_PREDICTION_INFO;
399
400
401
402 //
403 // This struct must always fit within four PVOIDs of info,
404 // as it uses the irp's "PVOID DriverContext[4]" to store
405 // this info
406 //
407 typedef struct _CLASS_RETRY_INFO {
408 struct _CLASS_RETRY_INFO *Next;
409 } CLASS_RETRY_INFO, *PCLASS_RETRY_INFO;
410
411 typedef struct _CSCAN_LIST {
412
413 //
414 // The current block which has an outstanding request.
415 //
416
417 ULONGLONG BlockNumber;
418
419 //
420 // The list of blocks past the CurrentBlock to which we're going to do
421 // i/o. This list is maintained in sorted order.
422 //
423
424 LIST_ENTRY CurrentSweep;
425
426 //
427 // The list of blocks behind the current block for which we'll have to
428 // wait until the next scan across the disk. This is kept as a stack,
429 // the cost of sorting it is taken when it's moved over to be the
430 // running list.
431 //
432
433 LIST_ENTRY NextSweep;
434
435 } CSCAN_LIST, *PCSCAN_LIST;
436
437 //
438 // add to the front of this structure to help prevent illegal
439 // snooping by other utilities.
440 //
441
442
443
444 typedef enum _CLASS_DETECTION_STATE {
445 ClassDetectionUnknown = 0,
446 ClassDetectionUnsupported = 1,
447 ClassDetectionSupported = 2
448 } CLASS_DETECTION_STATE, *PCLASS_DETECTION_STATE;
449
450 #if _MSC_VER >= 1600
451 #pragma warning(push)
452 #pragma warning(disable:4214) // bit field types other than int
453 #endif
454 //
455 // CLASS_ERROR_LOG_DATA will still use SCSI_REQUEST_BLOCK even
456 // when using extended SRB as an extended SRB is too large to
457 // fit into. Should revisit this code once classpnp starts to
458 // use greater than 16 byte CDB.
459 //
460 typedef struct _CLASS_ERROR_LOG_DATA {
461 LARGE_INTEGER TickCount; // Offset 0x00
462 ULONG PortNumber; // Offset 0x08
463
464 UCHAR ErrorPaging : 1; // Offset 0x0c
465 UCHAR ErrorRetried : 1;
466 UCHAR ErrorUnhandled : 1;
467 UCHAR ErrorReserved : 5;
468
469 UCHAR Reserved[3];
470
471 SCSI_REQUEST_BLOCK Srb; // Offset 0x10
472
473 /*
474 * We define the SenseData as the default length.
475 * Since the sense data returned by the port driver may be longer,
476 * SenseData must be at the end of this structure.
477 * For our internal error log, we only log the default length.
478 */
479 SENSE_DATA SenseData; // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
480
481 } CLASS_ERROR_LOG_DATA, *PCLASS_ERROR_LOG_DATA;
482 #if _MSC_VER >= 1600
483 #pragma warning(pop)
484 #endif
485
486 #define NUM_ERROR_LOG_ENTRIES 16
487 #define DBG_NUM_PACKET_LOG_ENTRIES (64*2) // 64 send&receive's
488
489 #if (NTDDI_VERSION >= NTDDI_WIN8)
490 typedef
491 VOID
492 (*PCONTINUATION_ROUTINE)(
493 _In_ PVOID Context
494 );
495 #endif
496
497 typedef struct _TRANSFER_PACKET {
498
499 LIST_ENTRY AllPktsListEntry; // entry in fdoData's static AllTransferPacketsList
500 SLIST_ENTRY SlistEntry; // for when in free list (use fast slist)
501
502 PIRP Irp;
503 PDEVICE_OBJECT Fdo;
504
505 /*
506 * This is the client IRP that this TRANSFER_PACKET is currently
507 * servicing.
508 */
509 PIRP OriginalIrp;
510 BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes;
511
512 /*
513 * Stuff for retrying the transfer.
514 */
515 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
516 UCHAR NumRetries; // Total number of retries remaining.
517 UCHAR NumThinProvisioningRetries; //Number of retries carried out so far for a request failed with THIN_PROVISIONING_SOFT_THRESHOLD_ERROR
518 UCHAR NumIoTimeoutRetries; // Number of retries remaining for a timed-out request.
519 UCHAR TimedOut; // Indicates if this packet has timed-out.
520 #else
521 ULONG NumRetries;
522 #endif
523 KTIMER RetryTimer;
524 KDPC RetryTimerDPC;
525
526 _Field_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
527 LONGLONG RetryIn100nsUnits;
528
529 /*
530 * Event for synchronizing the transfer (optional).
531 * (Note that we can't have the event in the packet itself because
532 * by the time a thread waits on an event the packet may have
533 * been completed and re-issued.
534 */
535 PKEVENT SyncEventPtr;
536
537 /*
538 * Stuff for retrying during extreme low-memory stress
539 * (when we retry 1 page at a time).
540 * NOTE: These fields are also used for StartIO-based
541 * class drivers, even when not in low memory conditions.
542 */
543 BOOLEAN DriverUsesStartIO; // if this is set, then the below low-mem flags are always used
544 BOOLEAN InLowMemRetry;
545 PUCHAR LowMemRetry_remainingBufPtr;
546 ULONG LowMemRetry_remainingBufLen;
547 LARGE_INTEGER LowMemRetry_nextChunkTargetLocation;
548
549 /*
550 * Fields used for cancelling the packet.
551 */
552 // BOOLEAN Cancelled;
553 // KEVENT CancelledEvent;
554
555 /*
556 * We keep the buffer and length values here as well
557 * as in the SRB because some miniports return
558 * the transferred length in SRB.DataTransferLength,
559 * and if the SRB failed we need that value again for the retry.
560 * We don't trust the lower stack to preserve any of these values in the SRB.
561 */
562 PUCHAR BufPtrCopy;
563 ULONG BufLenCopy;
564 LARGE_INTEGER TargetLocationCopy;
565
566 /*
567 * This is a standard SCSI structure that receives a detailed
568 * report about a SCSI error on the hardware.
569 */
570 SENSE_DATA_EX SrbErrorSenseData;
571
572 /*
573 * This is the SRB block for this TRANSFER_PACKET.
574 * For IOCTLs, the SRB block includes two DWORDs for
575 * device object and ioctl code; so these must
576 * immediately follow the SRB block.
577 */
578
579 #if (NTDDI_VERSION >= NTDDI_WIN8)
580 PSTORAGE_REQUEST_BLOCK_HEADER Srb;
581 #else
582 SCSI_REQUEST_BLOCK Srb;
583 #endif
584 // ULONG SrbIoctlDevObj; // not handling ioctls yet
585 // ULONG SrbIoctlCode;
586
587 #if DBG
588 LARGE_INTEGER DbgTimeSent;
589 LARGE_INTEGER DbgTimeReturned;
590 ULONG DbgPktId;
591 IRP DbgOriginalIrpCopy;
592 MDL DbgMdlCopy;
593 #endif
594
595 BOOLEAN UsePartialMdl;
596 PMDL PartialMdl;
597
598 PSRB_HISTORY RetryHistory;
599
600 // The time at which this request was sent to port driver.
601 ULONGLONG RequestStartTime;
602
603 #if (NTDDI_VERSION >= NTDDI_WIN8)
604 // ActivityId that is associated with the IRP that this transfer packet services.
605 GUID ActivityId;
606
607 // If non-NULL, called at packet completion with this context.
608 PCONTINUATION_ROUTINE ContinuationRoutine;
609 PVOID ContinuationContext;
610 ULONGLONG TransferCount;
611 ULONG AllocateNode;
612 #endif
613 } TRANSFER_PACKET, *PTRANSFER_PACKET;
614
615 /*
616 * MIN_INITIAL_TRANSFER_PACKETS is the minimum number of packets that
617 * we preallocate at startup for each device (we need at least one packet
618 * to guarantee forward progress during memory stress).
619 * MIN_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
620 * we allow to build up and remain for each device;
621 * we _lazily_ work down to this number when they're not needed.
622 * MAX_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
623 * that we _immediately_ reduce to when they are not needed.
624 *
625 * The absolute maximum number of packets that we will allocate is
626 * whatever is required by the current activity, up to the memory limit;
627 * as soon as stress ends, we snap down to MAX_WORKINGSET_TRANSFER_PACKETS;
628 * we then lazily work down to MIN_WORKINGSET_TRANSFER_PACKETS.
629 */
630 #define MIN_INITIAL_TRANSFER_PACKETS 1
631 #define MIN_WORKINGSET_TRANSFER_PACKETS_Client 16
632 #define MAX_WORKINGSET_TRANSFER_PACKETS_Client 32
633 #define MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound 256
634 #define MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound 32
635 #define MAX_WORKINGSET_TRANSFER_PACKETS_Server 1024
636 #define MIN_WORKINGSET_TRANSFER_PACKETS_SPACES 512
637 #define MAX_WORKINGSET_TRANSFER_PACKETS_SPACES 2048
638 #define MAX_OUTSTANDING_IO_PER_LUN_DEFAULT 16
639 #define MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE 8192
640
641
642
643 typedef struct _PNL_SLIST_HEADER {
644 DECLSPEC_CACHEALIGN SLIST_HEADER SListHeader;
645 DECLSPEC_CACHEALIGN ULONG NumFreeTransferPackets;
646 ULONG NumTotalTransferPackets;
647 ULONG DbgPeakNumTransferPackets;
648 } PNL_SLIST_HEADER, *PPNL_SLIST_HEADER;
649
650 //
651 // !!! WARNING !!!
652 // DO NOT use the following structure in code outside of classpnp
653 // as structure will not be guaranteed between OS versions.
654 //
655 // add to the front of this structure to help prevent illegal
656 // snooping by other utilities.
657 //
658 struct _CLASS_PRIVATE_FDO_DATA {
659
660 //
661 // The amount of time allowed for a target to complete a copy offload
662 // operation, in seconds. Default is 4s, but it can be modified via
663 // registry key.
664 //
665 ULONG CopyOffloadMaxTargetDuration;
666
667
668 #if (NTDDI_VERSION >= NTDDI_WIN8)
669
670 //
671 // Periodic timer for polling for media change detection, failure prediction
672 // and class tick function.
673 //
674
675 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
676 PEX_TIMER TickTimer;
677 LONGLONG CurrentNoWakeTolerance;
678 #else
679 KTIMER TickTimer;
680 KDPC TickTimerDpc;
681 #endif // (NTDDI_VERSION >= NTDDI_WINBLUE)
682
683 //
684 // Power related and release queue SRBs
685 //
686 union {
687 STORAGE_REQUEST_BLOCK SrbEx;
688 UCHAR PowerSrbBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE];
689 } PowerSrb;
690
691 union {
692 STORAGE_REQUEST_BLOCK SrbEx;
693 UCHAR ReleaseQueueSrbBuffer[CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE];
694 } ReleaseQueueSrb;
695
696 #endif
697
698 ULONG TrackingFlags;
699
700 /*
701 * Flag to detect recursion caused by devices
702 * reporting different capacity per each request
703 */
704 ULONG UpdateDiskPropertiesWorkItemActive;
705
706 //
707 // Local equivalents of MinWorkingSetTransferPackets and MaxWorkingSetTransferPackets.
708 // These values are initialized by the global equivalents but are then adjusted as
709 // requested by the class driver.
710 //
711 ULONG LocalMinWorkingSetTransferPackets;
712 ULONG LocalMaxWorkingSetTransferPackets;
713
714 #if DBG
715
716 ULONG MaxOutstandingIOPerLUN;
717
718 #endif
719
720 /*
721 * Entry in static list used by debug extension to quickly find all class FDOs.
722 */
723 LIST_ENTRY AllFdosListEntry;
724
725 //
726 // this private structure allows us to
727 // dynamically re-enable the perf benefits
728 // lost due to transient error conditions.
729 // in w2k, a reboot was required. :(
730 //
731 struct {
732 ULONG OriginalSrbFlags;
733 ULONG SuccessfulIO;
734 ULONG ReEnableThreshhold; // 0 means never
735 } Perf;
736
737 ULONG_PTR HackFlags;
738
739 STORAGE_HOTPLUG_INFO HotplugInfo;
740
741 // Legacy. Still used by obsolete legacy code.
742 struct {
743 LARGE_INTEGER Delta; // in ticks
744 LARGE_INTEGER Tick; // when it should fire
745 PCLASS_RETRY_INFO ListHead; // singly-linked list
746 ULONG Granularity; // static
747 KSPIN_LOCK Lock; // protective spin lock
748 KDPC Dpc; // DPC routine object
749 KTIMER Timer; // timer to fire DPC
750 } Retry;
751
752 BOOLEAN TimerInitialized;
753 BOOLEAN LoggedTURFailureSinceLastIO;
754 BOOLEAN LoggedSYNCFailure;
755
756 //
757 // privately allocated release queue irp
758 // protected by fdoExtension->ReleaseQueueSpinLock
759 //
760 BOOLEAN ReleaseQueueIrpAllocated;
761 PIRP ReleaseQueueIrp;
762
763 /*
764 * Queues for TRANSFER_PACKETs that contextualize the IRPs and SRBs
765 * that we send down to the port driver.
766 * (The free list is an slist so that we can use fast
767 * interlocked operations on it; but the relatively-static
768 * AllTransferPacketsList list has to be
769 * a doubly-linked list since we have to dequeue from the middle).
770 */
771 LIST_ENTRY AllTransferPacketsList;
772 PPNL_SLIST_HEADER FreeTransferPacketsLists;
773
774 /*
775 * Queue for deferred client irps
776 */
777 LIST_ENTRY DeferredClientIrpList;
778
779 /*
780 * Precomputed maximum transfer length for the hardware.
781 */
782 ULONG HwMaxXferLen;
783
784 /*
785 * SCSI_REQUEST_BLOCK template preconfigured with the constant values.
786 * This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
787 */
788
789 #if (NTDDI_VERSION >= NTDDI_WIN8)
790 PSTORAGE_REQUEST_BLOCK_HEADER SrbTemplate;
791 #else
792 SCSI_REQUEST_BLOCK SrbTemplate;
793 #endif
794
795 KSPIN_LOCK SpinLock;
796
797 /*
798 * For non-removable media, we read the drive capacity at start time and cache it.
799 * This is so that ReadDriveCapacity failures at runtime (e.g. due to memory stress)
800 * don't cause I/O on the paging disk to start failing.
801 */
802 READ_CAPACITY_DATA_EX LastKnownDriveCapacityData;
803 BOOLEAN IsCachedDriveCapDataValid;
804
805 //
806 // Idle priority support flag
807 //
808 BOOLEAN IdlePrioritySupported;
809
810 //
811 // Tick timer enabled
812 //
813 BOOLEAN TickTimerEnabled;
814
815 BOOLEAN ReservedBoolean;
816
817 /*
818 * Circular array of timestamped logs of errors that occurred on this device.
819 */
820 ULONG ErrorLogNextIndex;
821 CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
822
823 //
824 // Number of outstanding critical Io requests from Mm
825 //
826 ULONG NumHighPriorityPagingIo;
827
828 //
829 // Maximum number of normal Io requests that can be interleaved with the critical ones
830 //
831 ULONG MaxInterleavedNormalIo;
832
833 //
834 // The timestamp when entering throttle mode
835 //
836 LARGE_INTEGER ThrottleStartTime;
837
838 //
839 // The timestamp when exiting throttle mode
840 //
841 LARGE_INTEGER ThrottleStopTime;
842
843 //
844 // The longest time ever spent in throttle mode
845 //
846 LARGE_INTEGER LongestThrottlePeriod;
847
848 #if DBG
849 ULONG DbgMaxPktId;
850
851 /*
852 * Logging fields for ForceUnitAccess and Flush
853 */
854 BOOLEAN DbgInitFlushLogging; // must reset this to 1 for each logging session
855 ULONG DbgNumIORequests;
856 ULONG DbgNumFUAs; // num I/O requests with ForceUnitAccess bit set
857 ULONG DbgNumFlushes; // num SRB_FUNCTION_FLUSH_QUEUE
858 ULONG DbgIOsSinceFUA;
859 ULONG DbgIOsSinceFlush;
860 ULONG DbgAveIOsToFUA; // average number of I/O requests between FUAs
861 ULONG DbgAveIOsToFlush; // ...
862 ULONG DbgMaxIOsToFUA;
863 ULONG DbgMaxIOsToFlush;
864 ULONG DbgMinIOsToFUA;
865 ULONG DbgMinIOsToFlush;
866
867 /*
868 * Debug log of previously sent packets (including retries).
869 */
870 ULONG DbgPacketLogNextIndex;
871 TRANSFER_PACKET DbgPacketLogs[DBG_NUM_PACKET_LOG_ENTRIES];
872 #endif
873
874 //
875 // Spin lock for low priority I/O list
876 //
877 KSPIN_LOCK IdleListLock;
878
879 //
880 // Queue for low priority I/O
881 //
882 LIST_ENTRY IdleIrpList;
883
884 //
885 // Timer for low priority I/O
886 //
887 KTIMER IdleTimer;
888
889 //
890 // DPC for low priority I/O
891 //
892 KDPC IdleDpc;
893
894 #if (NTDDI_VERSION >= NTDDI_WIN8)
895
896 //
897 // Time (ms) since the completion of the last non-idle request before the
898 // first idle request should be issued. Due to the coarseness of the idle
899 // timer frequency, some variability in the idle interval will be tolerated
900 // such that it is the desired idle interval on average.
901 //
902 USHORT IdleInterval;
903
904 //
905 // Max number of active idle requests.
906 //
907 USHORT IdleActiveIoMax;
908
909 #endif
910
911 //
912 // Idle duration required to process idle request
913 // to avoid starvation
914 //
915 USHORT StarvationDuration;
916
917 //
918 // Idle I/O count
919 //
920 ULONG IdleIoCount;
921
922 //
923 // Flag to indicate timer status
924 //
925 LONG IdleTimerStarted;
926
927 //
928 // Time when the Idle timer was started
929 //
930 LARGE_INTEGER AntiStarvationStartTime;
931
932 //
933 // Normal priority I/O time
934 //
935 LARGE_INTEGER LastNonIdleIoTime;
936
937 //
938 // Time when the last IO of any priority completed.
939 //
940 LARGE_INTEGER LastIoCompletionTime;
941
942 //
943 // Count of active normal priority I/O
944 //
945 LONG ActiveIoCount;
946
947 //
948 // Count of active idle priority I/O
949 //
950 LONG ActiveIdleIoCount;
951
952 //
953 // Support for class drivers to extend
954 // the interpret sense information routine
955 // and retry history per-packet. Copy of
956 // values in driver extension.
957 //
958 PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo;
959
960 //
961 // power process parameters. they work closely with CLASS_POWER_CONTEXT structure.
962 //
963 ULONG MaxPowerOperationRetryCount;
964 PIRP PowerProcessIrp;
965
966 //
967 // Indicates legacy error handling should be used.
968 // This means:
969 // - Max number of retries for an IO request is 8 (instead of 4).
970 //
971 BOOLEAN LegacyErrorHandling;
972
973 //
974 // Maximum number of retries allowed for IO requests for this device.
975 //
976 UCHAR MaxNumberOfIoRetries;
977
978 //
979 // Disable All Throttling in case of Error
980 //
981 BOOLEAN DisableThrottling;
982
983 };
984
985 //
986 // !!! WARNING !!!
987 // DO NOT use the following structure in code outside of classpnp
988 // as structure will not be guaranteed between OS versions.
989 //
990 // EX_RUNDOWN_REF_CACHE_AWARE is variable size and follows
991 // RemoveLockFailAcquire. EX_RUNDOWN_REF_CACHE_AWARE must be part
992 // of the device extension allocation to avoid issues with a device
993 // that has been PNP remove but still has outstanding references.
994 // In this case, the removed object may still receive incoming requests.
995 //
996 // There are code dependencies on the structure layout. To minimize
997 // code changes, new fields to _CLASS_PRIVATE_COMMON_DATA should be
998 // added based on the following guidance.
999 // - Fixed size: beginning of _CLASS_PRIVATE_COMMON_DATA
1000 // - Variable size: at the end of _CLASS_PRIVATE_COMMON_DATA after the
1001 // last variable size field.
1002 //
1003
1004 struct _CLASS_PRIVATE_COMMON_DATA {
1005
1006 //
1007 // Cacheaware rundown lock reference
1008 //
1009
1010 LONG RemoveLockFailAcquire;
1011
1012 //
1013 // N.B. EX_RUNDOWN_REF_CACHE_AWARE begins with a pointer-sized item that is
1014 // accessed interlocked, and must be aligned on ARM platforms. In order
1015 // for this to work on ARM64, an additional 32-bit slot must be allocated.
1016 //
1017
1018 #if defined(_WIN64)
1019 LONG Align;
1020 #endif
1021
1022 // EX_RUNDOWN_REF_CACHE_AWARE (variable size) follows
1023
1024 };
1025
1026 //
1027 // Verify that the size of _CLASS_PRIVATE_COMMON_DATA is pointer size aligned
1028 // to ensure the EX_RUNDOWN_REF_CACHE_AWARE following it is properly aligned.
1029 //
1030
1031 C_ASSERT((sizeof(struct _CLASS_PRIVATE_COMMON_DATA) % sizeof(PVOID)) == 0);
1032
1033 typedef struct _IDLE_POWER_FDO_LIST_ENTRY {
1034 LIST_ENTRY ListEntry;
1035 PDEVICE_OBJECT Fdo;
1036 } IDLE_POWER_FDO_LIST_ENTRY, *PIDLE_POWER_FDO_LIST_ENTRY;
1037
1038 typedef struct _OFFLOAD_READ_CONTEXT {
1039
1040 PDEVICE_OBJECT Fdo;
1041
1042 //
1043 // Upper offload read DSM irp.
1044 //
1045
1046 PIRP OffloadReadDsmIrp;
1047
1048 //
1049 // A pseudo-irp is used despite the operation being async. This is in
1050 // contrast to normal read and write, which let TransferPktComplete()
1051 // complete the upper IRP directly. Offload requests are enough different
1052 // that it makes more sense to let them manage their own async steps with
1053 // minimal help from TransferPktComplete() (just a continuation function
1054 // call during TransferPktComplete()).
1055 //
1056
1057 IRP PseudoIrp;
1058
1059 //
1060 // The offload read context tracks one packet in flight at a time - it'll be
1061 // the POPULATE TOKEN packet first, then RECEIVE ROD TOKEN INFORMATION.
1062 //
1063 // This field exists only for debug purposes.
1064 //
1065
1066 PTRANSFER_PACKET Pkt;
1067
1068 PMDL PopulateTokenMdl;
1069
1070 ULONG BufferLength;
1071
1072 ULONG ListIdentifier;
1073
1074 ULONG ReceiveTokenInformationBufferLength;
1075
1076 //
1077 // Total sectors that the operation is attempting to process.
1078 //
1079
1080 ULONGLONG TotalSectorsToProcess;
1081
1082 //
1083 // Total sectors actually processed.
1084 //
1085
1086 ULONGLONG TotalSectorsProcessed;
1087
1088 //
1089 // Total upper request size in bytes.
1090 //
1091
1092 ULONGLONG EntireXferLen;
1093
1094 //
1095 // Just a cached copy of what was in the transfer packet.
1096 //
1097
1098 SCSI_REQUEST_BLOCK Srb;
1099
1100 //
1101 // Pointer into the token part of the SCSI buffer (the buffer immediately
1102 // after this struct), for easy reference.
1103 //
1104
1105 PUCHAR Token;
1106
1107 // The SCSI buffer (in/out buffer, not CDB) for the commands immediately
1108 // follows this struct, so no need to have a field redundantly pointing to
1109 // the buffer.
1110 } OFFLOAD_READ_CONTEXT, *POFFLOAD_READ_CONTEXT;
1111
1112
1113 typedef struct _OFFLOAD_WRITE_CONTEXT {
1114
1115 PDEVICE_OBJECT Fdo;
1116
1117 PIRP OffloadWriteDsmIrp;
1118
1119 ULONGLONG EntireXferLen;
1120 ULONGLONG TotalRequestSizeSectors;
1121
1122 ULONG DataSetRangesCount;
1123
1124 PDEVICE_MANAGE_DATA_SET_ATTRIBUTES DsmAttributes;
1125 PDEVICE_DATA_SET_RANGE DataSetRanges;
1126 PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS OffloadWriteParameters;
1127 ULONGLONG LogicalBlockOffset;
1128
1129 ULONG MaxBlockDescrCount;
1130 ULONGLONG MaxLbaCount;
1131
1132 ULONG BufferLength;
1133 ULONG ReceiveTokenInformationBufferLength;
1134
1135 IRP PseudoIrp;
1136
1137 PMDL WriteUsingTokenMdl;
1138
1139 ULONGLONG TotalSectorsProcessedSuccessfully;
1140 ULONG DataSetRangeIndex;
1141 ULONGLONG DataSetRangeByteOffset;
1142
1143 PTRANSFER_PACKET Pkt;
1144
1145 //
1146 // Per-WUT (WRITE USING TOKEN), not overall.
1147 //
1148
1149 ULONGLONG TotalSectorsToProcess;
1150 ULONGLONG TotalSectorsProcessed;
1151
1152 ULONG ListIdentifier;
1153
1154 BOOLEAN TokenInvalidated;
1155
1156 //
1157 // Just a cached copy of what was in the transfer packet.
1158 //
1159
1160 SCSI_REQUEST_BLOCK Srb;
1161
1162 ULONGLONG OperationStartTime;
1163
1164 } OFFLOAD_WRITE_CONTEXT, *POFFLOAD_WRITE_CONTEXT;
1165
1166
1167 typedef struct _OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER {
1168 PIO_WORKITEM WorkItem;
1169 PVOID SenseData;
1170 ULONG SenseDataSize;
1171 UCHAR SrbStatus;
1172 UCHAR ScsiStatus;
1173 UCHAR OpCode;
1174 UCHAR Reserved;
1175 ULONG ErrorCode;
1176 } OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER, *POPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER;
1177
1178 typedef struct _IO_RETRIED_LOG_MESSAGE_CONTEXT {
1179 OPCODE_SENSE_DATA_IO_LOG_MESSAGE_CONTEXT_HEADER ContextHeader;
1180 LARGE_INTEGER Lba;
1181 ULONG DeviceNumber;
1182 } IO_RETRIED_LOG_MESSAGE_CONTEXT, *PIO_RETRIED_LOG_MESSAGE_CONTEXT;
1183
1184
1185 #define QERR_SET_ZERO_ODX_OR_TP_ONLY 0
1186 #define QERR_SET_ZERO_ALWAYS 1
1187 #define QERR_SET_ZERO_NEVER 2
1188
1189
1190 #define MIN(a, b) ((a) < (b) ? (a) : (b))
1191 #define MAX(a, b) ((a) > (b) ? (a) : (b))
1192
1193
1194 #define NOT_READY_RETRY_INTERVAL 10
1195 #define MINIMUM_RETRY_UNITS ((LONGLONG)32)
1196 #define MODE_PAGE_DATA_SIZE 192
1197
1198 #define CLASS_IDLE_INTERVAL_MIN 12 // 12 milliseconds
1199 #define CLASS_IDLE_INTERVAL 12 // 12 milliseconds
1200 #define CLASS_STARVATION_INTERVAL 500 // 500 milliseconds
1201
1202 //
1203 // Value of 50 milliseconds in 100 nanoseconds units
1204 //
1205 #define FIFTY_MS_IN_100NS_UNITS 50 * 100
1206
1207
1208 /*
1209 * Simple singly-linked-list queuing macros, with no synchronization.
1210 */
SimpleInitSlistHdr(SINGLE_LIST_ENTRY * SListHdr)1211 FORCEINLINE VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
1212 {
1213 SListHdr->Next = NULL;
1214 }
SimplePushSlist(SINGLE_LIST_ENTRY * SListHdr,SINGLE_LIST_ENTRY * SListEntry)1215 FORCEINLINE VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
1216 {
1217 SListEntry->Next = SListHdr->Next;
1218 SListHdr->Next = SListEntry;
1219 }
SimplePopSlist(SINGLE_LIST_ENTRY * SListHdr)1220 FORCEINLINE SINGLE_LIST_ENTRY *SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
1221 {
1222 SINGLE_LIST_ENTRY *sListEntry = SListHdr->Next;
1223 if (sListEntry){
1224 SListHdr->Next = sListEntry->Next;
1225 sListEntry->Next = NULL;
1226 }
1227 return sListEntry;
1228 }
SimpleIsSlistEmpty(SINGLE_LIST_ENTRY * SListHdr)1229 FORCEINLINE BOOLEAN SimpleIsSlistEmpty(SINGLE_LIST_ENTRY *SListHdr)
1230 {
1231 return (SListHdr->Next == NULL);
1232 }
1233
1234 FORCEINLINE
1235 BOOLEAN
ClasspIsIdleRequestSupported(PCLASS_PRIVATE_FDO_DATA FdoData,PIRP Irp)1236 ClasspIsIdleRequestSupported(
1237 PCLASS_PRIVATE_FDO_DATA FdoData,
1238 PIRP Irp
1239 )
1240 {
1241 #ifndef __REACTOS__
1242 IO_PRIORITY_HINT ioPriority = IoGetIoPriorityHint(Irp);
1243 return ((ioPriority <= IoPriorityLow) && (FdoData->IdlePrioritySupported == TRUE));
1244 #else
1245 return (FdoData->IdlePrioritySupported == TRUE);
1246 #endif
1247 }
1248
1249 FORCEINLINE
1250 VOID
ClasspMarkIrpAsIdle(PIRP Irp,BOOLEAN Idle)1251 ClasspMarkIrpAsIdle(
1252 PIRP Irp,
1253 BOOLEAN Idle
1254 )
1255 {
1256 #ifndef __REACTOS__
1257 // truncation is not an issue for this use case
1258 // nonstandard extension used is not an issue for this use case
1259 #pragma warning(suppress:4305; suppress:4213)
1260 ((BOOLEAN)Irp->Tail.Overlay.DriverContext[1]) = Idle;
1261 #else
1262 ((PULONG_PTR)Irp->Tail.Overlay.DriverContext)[1] = Idle;
1263 #endif
1264 }
1265
1266 FORCEINLINE
1267 BOOLEAN
ClasspIsIdleRequest(PIRP Irp)1268 ClasspIsIdleRequest(
1269 PIRP Irp
1270 )
1271 {
1272 #ifdef _MSC_VER
1273 #pragma warning(suppress:4305) // truncation is not an issue for this use case
1274 #endif
1275 return ((BOOLEAN)Irp->Tail.Overlay.DriverContext[1]);
1276 }
1277
1278 FORCEINLINE
1279 LARGE_INTEGER
ClasspGetCurrentTime(VOID)1280 ClasspGetCurrentTime(
1281 VOID
1282 )
1283 {
1284 LARGE_INTEGER currentTime;
1285
1286 #ifndef __REACTOS__
1287 currentTime.QuadPart = KeQueryUnbiasedInterruptTimePrecise((ULONG64*)¤tTime.QuadPart);
1288 #else
1289 currentTime = KeQueryPerformanceCounter(NULL);
1290 #endif
1291
1292 return currentTime;
1293 }
1294
1295 FORCEINLINE
1296 ULONGLONG
ClasspTimeDiffToMs(ULONGLONG TimeDiff)1297 ClasspTimeDiffToMs(
1298 ULONGLONG TimeDiff
1299 )
1300 {
1301 TimeDiff /= (10 * 1000);
1302
1303 return TimeDiff;
1304 }
1305
1306 FORCEINLINE
1307 BOOLEAN
ClasspSupportsUnmap(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)1308 ClasspSupportsUnmap(
1309 _In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo
1310 )
1311 {
1312 return SupportInfo->LBProvisioningData.LBPU;
1313 }
1314
1315 FORCEINLINE
1316 BOOLEAN
ClasspIsThinProvisioned(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)1317 ClasspIsThinProvisioned(
1318 _In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo
1319 )
1320 {
1321 //
1322 // We only support thinly provisioned devices that also support UNMAP.
1323 //
1324 if (SupportInfo->LBProvisioningData.ProvisioningType == PROVISIONING_TYPE_THIN &&
1325 SupportInfo->LBProvisioningData.LBPU == TRUE)
1326 {
1327 return TRUE;
1328 }
1329
1330 return FALSE;
1331 }
1332
1333 FORCEINLINE
1334 BOOLEAN
ClasspIsObsoletePortDriver(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)1335 ClasspIsObsoletePortDriver(
1336 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1337 )
1338 {
1339 if ( (FdoExtension->MiniportDescriptor != NULL) &&
1340 (FdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSCSIport) ) {
1341 return TRUE;
1342 }
1343
1344 return FALSE;
1345 }
1346
1347
1348 ULONG
1349 ClasspCalculateLogicalSectorSize (
1350 _In_ PDEVICE_OBJECT Fdo,
1351 _In_ ULONG BytesPerBlockInBigEndian
1352 );
1353
1354 DRIVER_INITIALIZE DriverEntry;
1355
1356 DRIVER_UNLOAD ClassUnload;
1357
1358 _Dispatch_type_(IRP_MJ_CREATE)
1359 _Dispatch_type_(IRP_MJ_CLOSE)
1360 DRIVER_DISPATCH ClassCreateClose;
1361
1362 NTSTATUS
1363 ClasspCreateClose(
1364 IN PDEVICE_OBJECT DeviceObject,
1365 IN PIRP Irp
1366 );
1367
1368 VOID
1369 ClasspCleanupProtectedLocks(
1370 IN PFILE_OBJECT_EXTENSION FsContext
1371 );
1372
1373 NTSTATUS
1374 ClasspEjectionControl(
1375 IN PDEVICE_OBJECT Fdo,
1376 IN PIRP Irp,
1377 IN MEDIA_LOCK_TYPE LockType,
1378 IN BOOLEAN Lock
1379 );
1380
1381 _Dispatch_type_(IRP_MJ_READ)
1382 _Dispatch_type_(IRP_MJ_WRITE)
1383 DRIVER_DISPATCH ClassReadWrite;
1384
1385 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
1386 DRIVER_DISPATCH ClassDeviceControlDispatch;
1387
1388 _Dispatch_type_(IRP_MJ_PNP)
1389 DRIVER_DISPATCH ClassDispatchPnp;
1390
1391 NTSTATUS
1392 ClassPnpStartDevice(
1393 IN PDEVICE_OBJECT DeviceObject
1394 );
1395
1396 _Dispatch_type_(IRP_MJ_SHUTDOWN)
1397 _Dispatch_type_(IRP_MJ_FLUSH_BUFFERS)
1398 DRIVER_DISPATCH ClassShutdownFlush;
1399
1400 _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
1401 DRIVER_DISPATCH ClassSystemControl;
1402
1403
1404 //
1405 // Class internal routines
1406 //
1407
1408 DRIVER_ADD_DEVICE ClassAddDevice;
1409
1410 IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion;
1411
1412 VOID
1413 RetryRequest(
1414 PDEVICE_OBJECT DeviceObject,
1415 PIRP Irp,
1416 PSCSI_REQUEST_BLOCK Srb,
1417 BOOLEAN Associated,
1418 LONGLONG TimeDelta100ns
1419 );
1420
1421 NTSTATUS
1422 ClassIoCompletion(
1423 IN PDEVICE_OBJECT DeviceObject,
1424 IN PIRP Irp,
1425 IN PVOID Context
1426 );
1427
1428 NTSTATUS
1429 ClassPnpQueryFdoRelations(
1430 IN PDEVICE_OBJECT Fdo,
1431 IN PIRP Irp
1432 );
1433
1434 NTSTATUS
1435 ClassRetrieveDeviceRelations(
1436 IN PDEVICE_OBJECT Fdo,
1437 IN DEVICE_RELATION_TYPE RelationType,
1438 OUT PDEVICE_RELATIONS *DeviceRelations
1439 );
1440
1441 NTSTATUS
1442 ClassGetPdoId(
1443 IN PDEVICE_OBJECT Pdo,
1444 IN BUS_QUERY_ID_TYPE IdType,
1445 IN PUNICODE_STRING IdString
1446 );
1447
1448 NTSTATUS
1449 ClassQueryPnpCapabilities(
1450 IN PDEVICE_OBJECT PhysicalDeviceObject,
1451 IN PDEVICE_CAPABILITIES Capabilities
1452 );
1453
1454 DRIVER_STARTIO ClasspStartIo;
1455
1456 NTSTATUS
1457 ClasspPagingNotificationCompletion(
1458 IN PDEVICE_OBJECT DeviceObject,
1459 IN PIRP Irp,
1460 IN PDEVICE_OBJECT RealDeviceObject
1461 );
1462
1463 NTSTATUS
1464 ClasspMediaChangeCompletion(
1465 PDEVICE_OBJECT DeviceObject,
1466 PIRP Irp,
1467 PVOID Context
1468 );
1469
1470 NTSTATUS
1471 ClasspMcnControl(
1472 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1473 IN PIRP Irp,
1474 IN PSCSI_REQUEST_BLOCK Srb
1475 );
1476
1477 VOID
1478 ClasspRegisterMountedDeviceInterface(
1479 IN PDEVICE_OBJECT DeviceObject
1480 );
1481
1482 VOID
1483 ClasspDisableTimer(
1484 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1485 );
1486
1487 VOID
1488 ClasspEnableTimer(
1489 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1490 );
1491
1492 NTSTATUS
1493 ClasspInitializeTimer(
1494 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1495 );
1496
1497 VOID
1498 ClasspDeleteTimer(
1499 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1500 );
1501
1502 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
1503 BOOLEAN
1504 ClasspUpdateTimerNoWakeTolerance(
1505 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1506 );
1507 #endif
1508
1509 NTSTATUS
1510 ClasspDuidQueryProperty(
1511 PDEVICE_OBJECT DeviceObject,
1512 PIRP Irp
1513 );
1514
1515 _Dispatch_type_(IRP_MJ_CREATE)
1516 _Dispatch_type_(IRP_MJ_CLOSE)
1517 _Dispatch_type_(IRP_MJ_READ)
1518 _Dispatch_type_(IRP_MJ_WRITE)
1519 _Dispatch_type_(IRP_MJ_SCSI)
1520 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
1521 _Dispatch_type_(IRP_MJ_SHUTDOWN)
1522 _Dispatch_type_(IRP_MJ_FLUSH_BUFFERS)
1523 _Dispatch_type_(IRP_MJ_PNP)
1524 _Dispatch_type_(IRP_MJ_POWER)
1525 _Dispatch_type_(IRP_MJ_SYSTEM_CONTROL)
1526 DRIVER_DISPATCH ClassGlobalDispatch;
1527
1528 VOID
1529 ClassInitializeDispatchTables(
1530 PCLASS_DRIVER_EXTENSION DriverExtension
1531 );
1532
1533 NTSTATUS
1534 ClasspPersistentReserve(
1535 _In_ PDEVICE_OBJECT DeviceObject,
1536 _In_ PIRP Irp,
1537 _Inout_ PSCSI_REQUEST_BLOCK Srb
1538 );
1539
1540 //
1541 // routines for dictionary list support
1542 //
1543
1544 VOID
1545 InitializeDictionary(
1546 IN PDICTIONARY Dictionary
1547 );
1548
1549 BOOLEAN
1550 TestDictionarySignature(
1551 IN PDICTIONARY Dictionary
1552 );
1553
1554 NTSTATUS
1555 AllocateDictionaryEntry(
1556 IN PDICTIONARY Dictionary,
1557 IN ULONGLONG Key,
1558 IN ULONG Size,
1559 IN ULONG Tag,
1560 OUT PVOID *Entry
1561 );
1562
1563 PVOID
1564 GetDictionaryEntry(
1565 IN PDICTIONARY Dictionary,
1566 IN ULONGLONG Key
1567 );
1568
1569 VOID
1570 FreeDictionaryEntry(
1571 IN PDICTIONARY Dictionary,
1572 IN PVOID Entry
1573 );
1574
1575
1576 NTSTATUS
1577 ClasspAllocateReleaseRequest(
1578 IN PDEVICE_OBJECT Fdo
1579 );
1580
1581 VOID
1582 ClasspFreeReleaseRequest(
1583 IN PDEVICE_OBJECT Fdo
1584 );
1585
1586 IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion;
1587
1588 VOID
1589 ClasspReleaseQueue(
1590 IN PDEVICE_OBJECT DeviceObject,
1591 IN PIRP ReleaseQueueIrp
1592 );
1593
1594 VOID
1595 ClasspDisablePowerNotification(
1596 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1597 );
1598
1599 //
1600 // class power routines
1601 //
1602
1603 _Dispatch_type_(IRP_MJ_POWER)
1604 DRIVER_DISPATCH ClassDispatchPower;
1605
1606 NTSTATUS
1607 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1608 ClassMinimalPowerHandler(
1609 IN PDEVICE_OBJECT DeviceObject,
1610 IN PIRP Irp
1611 );
1612
1613 _IRQL_requires_same_
1614 NTSTATUS
1615 ClasspEnableIdlePower(
1616 _In_ PDEVICE_OBJECT DeviceObject
1617 );
1618
1619 POWER_SETTING_CALLBACK ClasspPowerSettingCallback;
1620
1621 //
1622 // Child list routines
1623 //
1624
1625 VOID
1626 ClassAddChild(
1627 _In_ PFUNCTIONAL_DEVICE_EXTENSION Parent,
1628 _In_ PPHYSICAL_DEVICE_EXTENSION Child,
1629 _In_ BOOLEAN AcquireLock
1630 );
1631
1632 PPHYSICAL_DEVICE_EXTENSION
1633 ClassRemoveChild(
1634 IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
1635 IN PPHYSICAL_DEVICE_EXTENSION Child,
1636 IN BOOLEAN AcquireLock
1637 );
1638
1639 VOID
1640 ClasspRetryDpcTimer(
1641 IN PCLASS_PRIVATE_FDO_DATA FdoData
1642 );
1643
1644 KDEFERRED_ROUTINE ClasspRetryRequestDpc;
1645
1646 VOID
1647 ClassFreeOrReuseSrb(
1648 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1649 IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb
1650 );
1651
1652 VOID
1653 ClassRetryRequest(
1654 IN PDEVICE_OBJECT SelfDeviceObject,
1655 IN PIRP Irp,
1656 _In_ _In_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) // this is 100 seconds; already an assert in classpnp based on this
1657 IN LONGLONG TimeDelta100ns // in 100ns units
1658 );
1659
1660 VOID
1661 ClasspBuildRequestEx(
1662 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1663 _In_ PIRP Irp,
1664 _In_ __drv_aliasesMem PSCSI_REQUEST_BLOCK Srb
1665 );
1666
1667 NTSTATUS
1668 ClasspAllocateReleaseQueueIrp(
1669 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1670 );
1671
1672 NTSTATUS
1673 ClasspAllocatePowerProcessIrp(
1674 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1675 );
1676
1677 NTSTATUS
1678 ClasspInitializeGesn(
1679 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1680 IN PMEDIA_CHANGE_DETECTION_INFO Info
1681 );
1682
1683 VOID
1684 ClassSendEjectionNotification(
1685 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1686 );
1687
1688 VOID
1689 ClasspScanForSpecialInRegistry(
1690 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1691 );
1692
1693 VOID
1694 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1695 ClasspScanForClassHacks(
1696 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1697 IN ULONG_PTR Data
1698 );
1699
1700 NTSTATUS
1701 ClasspInitializeHotplugInfo(
1702 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1703 );
1704
1705 VOID
1706 ClasspPerfIncrementErrorCount(
1707 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1708 );
1709 VOID
1710 ClasspPerfIncrementSuccessfulIo(
1711 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
1712 );
1713
1714 IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties;
1715
1716 __drv_allocatesMem(Mem)
1717 PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo);
1718 VOID DestroyTransferPacket(_In_ __drv_freesMem(mem) PTRANSFER_PACKET Pkt);
1719 VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt);
1720 PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded);
1721 PTRANSFER_PACKET DequeueFreeTransferPacketEx(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN AllocIfNeeded, _In_ ULONG Node);
1722 VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp);
1723 NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt);
1724 IO_COMPLETION_ROUTINE TransferPktComplete;
1725 NTSTATUS ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc);
1726 VOID TransferPacketQueueRetryDpc(PTRANSFER_PACKET Pkt);
1727 KDEFERRED_ROUTINE TransferPacketRetryTimerDpc;
1728 BOOLEAN InterpretTransferPacketError(PTRANSFER_PACKET Pkt);
1729 BOOLEAN RetryTransferPacket(PTRANSFER_PACKET Pkt);
1730 VOID EnqueueDeferredClientIrp(PDEVICE_OBJECT Fdo, PIRP Irp);
1731 PIRP DequeueDeferredClientIrp(PDEVICE_OBJECT Fdo);
1732 VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation);
1733 BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt);
1734 VOID SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp);
1735 VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, UCHAR SubPage, PIRP OriginalIrp, UCHAR PageControl);
1736 VOID SetupModeSelectTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSelectBuffer, UCHAR ModeSelectBufferLen, BOOLEAN SavePages, PIRP OriginalIrp);
1737 VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp, BOOLEAN Use16ByteCdb);
1738 PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen);
1739 PMDL ClasspBuildDeviceMdl(PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice);
1740 VOID FreeDeviceInputMdl(PMDL Mdl);
1741 VOID ClasspFreeDeviceMdl(PMDL Mdl);
1742 NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo);
1743 VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo);
1744 VOID InterpretCapacityData(PDEVICE_OBJECT Fdo, PREAD_CAPACITY_DATA_EX ReadCapacityData);
1745 IO_WORKITEM_ROUTINE_EX CleanupTransferPacketToWorkingSetSizeWorker;
1746 VOID CleanupTransferPacketToWorkingSetSize(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN LimitNumPktToDelete, _In_ ULONG Node);
1747
1748 _IRQL_requires_max_(APC_LEVEL)
1749 _IRQL_requires_min_(PASSIVE_LEVEL)
1750 _IRQL_requires_same_
1751 VOID
1752 ClasspSetupPopulateTokenTransferPacket(
1753 _In_ __drv_aliasesMem POFFLOAD_READ_CONTEXT OffloadReadContext,
1754 _In_ PTRANSFER_PACKET Pkt,
1755 _In_ ULONG Length,
1756 _In_reads_bytes_(Length) PUCHAR PopulateTokenBuffer,
1757 _In_ PIRP OriginalIrp,
1758 _In_ ULONG ListIdentifier
1759 );
1760
1761 _IRQL_requires_max_(APC_LEVEL)
1762 _IRQL_requires_min_(PASSIVE_LEVEL)
1763 _IRQL_requires_same_
1764 VOID
1765 ClasspSetupReceivePopulateTokenInformationTransferPacket(
1766 _In_ POFFLOAD_READ_CONTEXT OffloadReadContext,
1767 _In_ PTRANSFER_PACKET Pkt,
1768 _In_ ULONG Length,
1769 _In_reads_bytes_(Length) PUCHAR ReceivePopulateTokenInformationBuffer,
1770 _In_ PIRP OriginalIrp,
1771 _In_ ULONG ListIdentifier
1772 );
1773
1774 _IRQL_requires_max_(APC_LEVEL)
1775 _IRQL_requires_min_(PASSIVE_LEVEL)
1776 _IRQL_requires_same_
1777 VOID
1778 ClasspSetupWriteUsingTokenTransferPacket(
1779 _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
1780 _In_ PTRANSFER_PACKET Pkt,
1781 _In_ ULONG Length,
1782 _In_reads_bytes_(Length) PUCHAR WriteUsingTokenBuffer,
1783 _In_ PIRP OriginalIrp,
1784 _In_ ULONG ListIdentifier
1785 );
1786
1787 _IRQL_requires_max_(APC_LEVEL)
1788 _IRQL_requires_min_(PASSIVE_LEVEL)
1789 _IRQL_requires_same_
1790 VOID
1791 ClasspSetupReceiveWriteUsingTokenInformationTransferPacket(
1792 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
1793 _In_ PTRANSFER_PACKET Pkt,
1794 _In_ ULONG Length,
1795 _In_reads_bytes_(Length) PUCHAR ReceiveWriteUsingTokenInformationBuffer,
1796 _In_ PIRP OriginalIrp,
1797 _In_ ULONG ListIdentifier
1798 );
1799
1800 ULONG ClasspModeSense(
1801 _In_ PDEVICE_OBJECT Fdo,
1802 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
1803 _In_ ULONG Length,
1804 _In_ UCHAR PageMode,
1805 _In_ UCHAR PageControl
1806 );
1807
1808 NTSTATUS
1809 ClasspModeSelect(
1810 _In_ PDEVICE_OBJECT Fdo,
1811 _In_reads_bytes_(Length) PCHAR ModeSelectBuffer,
1812 _In_ ULONG Length,
1813 _In_ BOOLEAN SavePages
1814 );
1815
1816 NTSTATUS ClasspWriteCacheProperty(
1817 _In_ PDEVICE_OBJECT DeviceObject,
1818 _In_ PIRP Irp,
1819 _Inout_ PSCSI_REQUEST_BLOCK Srb
1820 );
1821
1822 NTSTATUS ClasspAccessAlignmentProperty(
1823 _In_ PDEVICE_OBJECT DeviceObject,
1824 _In_ PIRP Irp,
1825 _Inout_ PSCSI_REQUEST_BLOCK Srb
1826 );
1827
1828 NTSTATUS ClasspDeviceSeekPenaltyProperty(
1829 _In_ PDEVICE_OBJECT DeviceObject,
1830 _In_ PIRP Irp,
1831 _Inout_ PSCSI_REQUEST_BLOCK Srb
1832 );
1833
1834 NTSTATUS ClasspDeviceGetLBProvisioningVPDPage(
1835 _In_ PDEVICE_OBJECT DeviceObject,
1836 _Inout_opt_ PSCSI_REQUEST_BLOCK Srb
1837 );
1838
1839 NTSTATUS ClasspDeviceGetBlockDeviceCharacteristicsVPDPage(
1840 _In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension,
1841 _In_ PSCSI_REQUEST_BLOCK Srb
1842 );
1843
1844 NTSTATUS ClasspDeviceGetBlockLimitsVPDPage(
1845 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
1846 _Inout_bytecount_(SrbSize) PSCSI_REQUEST_BLOCK Srb,
1847 _In_ ULONG SrbSize,
1848 _Out_ PCLASS_VPD_B0_DATA BlockLimitsData
1849 );
1850
1851 NTSTATUS ClasspDeviceTrimProperty(
1852 _In_ PDEVICE_OBJECT DeviceObject,
1853 _In_ PIRP Irp,
1854 _Inout_ PSCSI_REQUEST_BLOCK Srb
1855 );
1856
1857 NTSTATUS ClasspDeviceLBProvisioningProperty(
1858 _In_ PDEVICE_OBJECT DeviceObject,
1859 _Inout_ PIRP Irp,
1860 _Inout_ PSCSI_REQUEST_BLOCK Srb
1861 );
1862
1863 NTSTATUS ClasspDeviceTrimProcess(
1864 _In_ PDEVICE_OBJECT DeviceObject,
1865 _In_ PIRP Irp,
1866 _In_ PGUID ActivityId,
1867 _Inout_ PSCSI_REQUEST_BLOCK Srb
1868 );
1869
1870 NTSTATUS ClasspDeviceGetLBAStatus(
1871 _In_ PDEVICE_OBJECT DeviceObject,
1872 _Inout_ PIRP Irp,
1873 _Inout_ PSCSI_REQUEST_BLOCK Srb
1874 );
1875
1876 NTSTATUS ClasspDeviceGetLBAStatusWorker(
1877 _In_ PDEVICE_OBJECT DeviceObject,
1878 _In_ PCLASS_VPD_B0_DATA BlockLimitsData,
1879 _In_ ULONGLONG StartingOffset,
1880 _In_ ULONGLONG LengthInBytes,
1881 _Out_ PDEVICE_MANAGE_DATA_SET_ATTRIBUTES_OUTPUT DsmOutput,
1882 _Inout_ PULONG DsmOutputLength,
1883 _Inout_ PSCSI_REQUEST_BLOCK Srb,
1884 _In_ BOOLEAN ConsolidateableBlocksOnly,
1885 _In_ ULONG OutputVersion,
1886 _Out_ PBOOLEAN BlockLimitsDataMayHaveChanged
1887 );
1888
1889 VOID ClassQueueThresholdEventWorker(
1890 _In_ PDEVICE_OBJECT DeviceObject
1891 );
1892
1893 VOID ClassQueueResourceExhaustionEventWorker(
1894 _In_ PDEVICE_OBJECT DeviceObject
1895 );
1896
1897 VOID ClassQueueCapacityChangedEventWorker(
1898 _In_ PDEVICE_OBJECT DeviceObject
1899 );
1900
1901 VOID ClassQueueProvisioningTypeChangedEventWorker(
1902 _In_ PDEVICE_OBJECT DeviceObject
1903 );
1904
1905 IO_WORKITEM_ROUTINE ClasspLogIOEventWithContext;
1906
1907 VOID
1908 ClasspQueueLogIOEventWithContextWorker(
1909 _In_ PDEVICE_OBJECT DeviceObject,
1910 _In_ ULONG SenseBufferSize,
1911 _In_ PVOID SenseData,
1912 _In_ UCHAR SrbStatus,
1913 _In_ UCHAR ScsiStatus,
1914 _In_ ULONG ErrorCode,
1915 _In_ ULONG CdbLength,
1916 _In_opt_ PCDB Cdb,
1917 _In_opt_ PTRANSFER_PACKET Pkt
1918 );
1919
1920 VOID
1921 ClasspZeroQERR(
1922 _In_ PDEVICE_OBJECT DeviceObject
1923 );
1924
1925
1926 _IRQL_requires_max_(PASSIVE_LEVEL)
1927 NTSTATUS
1928 ClasspGetMaximumTokenListIdentifier(
1929 _In_ PDEVICE_OBJECT DeviceObject,
1930 _In_z_ PWSTR RegistryPath,
1931 _Out_ PULONG MaximumListIdentifier
1932 );
1933
1934 _IRQL_requires_max_(PASSIVE_LEVEL)
1935 NTSTATUS
1936 ClasspGetCopyOffloadMaxDuration(
1937 _In_ PDEVICE_OBJECT DeviceObject,
1938 _In_z_ PWSTR RegistryPath,
1939 _Out_ PULONG MaxDuration
1940 );
1941
1942 _IRQL_requires_max_(APC_LEVEL)
1943 _IRQL_requires_min_(PASSIVE_LEVEL)
1944 _IRQL_requires_same_
1945 NTSTATUS
1946 ClasspDeviceCopyOffloadProperty(
1947 _In_ PDEVICE_OBJECT DeviceObject,
1948 _Inout_ PIRP Irp,
1949 _Inout_ PSCSI_REQUEST_BLOCK Srb
1950 );
1951
1952 _IRQL_requires_max_(APC_LEVEL)
1953 _IRQL_requires_min_(PASSIVE_LEVEL)
1954 _IRQL_requires_same_
1955 NTSTATUS
1956 ClasspValidateOffloadSupported(
1957 _In_ PDEVICE_OBJECT DeviceObject,
1958 _In_ PIRP Irp
1959 );
1960
1961 _IRQL_requires_max_(APC_LEVEL)
1962 _IRQL_requires_min_(PASSIVE_LEVEL)
1963 _IRQL_requires_same_
1964 NTSTATUS
1965 ClasspValidateOffloadInputParameters(
1966 _In_ PDEVICE_OBJECT DeviceObject,
1967 _In_ PIRP Irp
1968 );
1969
1970 _IRQL_requires_same_
1971 NTSTATUS
1972 ClasspGetTokenOperationCommandBufferLength(
1973 _In_ PDEVICE_OBJECT Fdo,
1974 _In_ ULONG ServiceAction,
1975 _Inout_ PULONG CommandBufferLength,
1976 _Out_opt_ PULONG TokenOperationBufferLength,
1977 _Out_opt_ PULONG ReceiveTokenInformationBufferLength
1978 );
1979
1980 _IRQL_requires_same_
1981 NTSTATUS
1982 ClasspGetTokenOperationDescriptorLimits(
1983 _In_ PDEVICE_OBJECT Fdo,
1984 _In_ ULONG ServiceAction,
1985 _In_ ULONG MaxParameterBufferLength,
1986 _Out_ PULONG MaxBlockDescriptorsCount,
1987 _Out_ PULONGLONG MaxBlockDescriptorsLength
1988 );
1989
1990 _IRQL_requires_max_(APC_LEVEL)
1991 _IRQL_requires_min_(PASSIVE_LEVEL)
1992 _IRQL_requires_same_
1993 VOID
1994 ClasspConvertDataSetRangeToBlockDescr(
1995 _In_ PDEVICE_OBJECT Fdo,
1996 _In_ PVOID BlockDescr,
1997 _Inout_ PULONG CurrentBlockDescrIndex,
1998 _In_ ULONG MaxBlockDescrCount,
1999 _Inout_ PULONG CurrentLbaCount,
2000 _In_ ULONGLONG MaxLbaCount,
2001 _Inout_ PDEVICE_DATA_SET_RANGE DataSetRange,
2002 _Inout_ PULONGLONG TotalSectorsProcessed
2003 );
2004
2005 NTSTATUS
2006 ClasspDeviceMediaTypeProperty(
2007 _In_ PDEVICE_OBJECT DeviceObject,
2008 _Inout_ PIRP Irp,
2009 _Inout_ PSCSI_REQUEST_BLOCK Srb
2010 );
2011
2012
2013 _IRQL_requires_same_
2014 PUCHAR
2015 ClasspBinaryToAscii(
2016 _In_reads_(Length) PUCHAR HexBuffer,
2017 _In_ ULONG Length,
2018 _Inout_ PULONG UpdateLength
2019 );
2020
2021 FORCEINLINE
2022 BOOLEAN
ClasspIsTokenOperationComplete(_In_ ULONG CurrentStatus)2023 ClasspIsTokenOperationComplete(
2024 _In_ ULONG CurrentStatus
2025 )
2026 {
2027 BOOLEAN operationCompleted = FALSE;
2028
2029 switch (CurrentStatus) {
2030 case OPERATION_COMPLETED_WITH_SUCCESS:
2031 case OPERATION_COMPLETED_WITH_ERROR:
2032 case OPERATION_COMPLETED_WITH_RESIDUAL_DATA:
2033 case OPERATION_TERMINATED: {
2034
2035 operationCompleted = TRUE;
2036 }
2037 }
2038
2039 return operationCompleted;
2040 }
2041
2042 FORCEINLINE
2043 BOOLEAN
ClasspIsTokenOperation(_In_ PCDB Cdb)2044 ClasspIsTokenOperation(
2045 _In_ PCDB Cdb
2046 )
2047 {
2048 BOOLEAN tokenOperation = FALSE;
2049
2050 if (Cdb) {
2051 ULONG opCode = Cdb->AsByte[0];
2052 ULONG serviceAction = Cdb->AsByte[1];
2053
2054 if ((opCode == SCSIOP_POPULATE_TOKEN && serviceAction == SERVICE_ACTION_POPULATE_TOKEN) ||
2055 (opCode == SCSIOP_WRITE_USING_TOKEN && serviceAction == SERVICE_ACTION_WRITE_USING_TOKEN)) {
2056
2057 tokenOperation = TRUE;
2058 }
2059 }
2060
2061 return tokenOperation;
2062 }
2063
2064 FORCEINLINE
2065 BOOLEAN
ClasspIsReceiveTokenInformation(_In_ PCDB Cdb)2066 ClasspIsReceiveTokenInformation(
2067 _In_ PCDB Cdb
2068 )
2069 {
2070 BOOLEAN receiveTokenInformation = FALSE;
2071
2072 if (Cdb) {
2073 ULONG opCode = Cdb->AsByte[0];
2074 ULONG serviceAction = Cdb->AsByte[1];
2075
2076 if (opCode == SCSIOP_RECEIVE_ROD_TOKEN_INFORMATION && serviceAction == SERVICE_ACTION_RECEIVE_TOKEN_INFORMATION) {
2077
2078 receiveTokenInformation = TRUE;
2079 }
2080 }
2081
2082 return receiveTokenInformation;
2083 }
2084
2085 FORCEINLINE
2086 BOOLEAN
ClasspIsOffloadDataTransferCommand(_In_ PCDB Cdb)2087 ClasspIsOffloadDataTransferCommand(
2088 _In_ PCDB Cdb
2089 )
2090 {
2091 BOOLEAN offloadCommand = (ClasspIsTokenOperation(Cdb) || ClasspIsReceiveTokenInformation(Cdb)) ? TRUE : FALSE;
2092
2093 return offloadCommand;
2094 }
2095
2096 extern LIST_ENTRY AllFdosList;
2097
2098
2099 VOID
2100 ClasspInitializeIdleTimer(
2101 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2102 );
2103
2104 NTSTATUS
2105 ClasspIsPortable(
2106 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2107 _Out_ PBOOLEAN IsPortable
2108 );
2109
2110 VOID
2111 ClasspGetInquiryVpdSupportInfo(
2112 _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2113 );
2114
2115 NTSTATUS
2116 ClasspGetLBProvisioningInfo(
2117 _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2118 );
2119
2120
2121 _IRQL_requires_(PASSIVE_LEVEL)
2122 _IRQL_requires_same_
2123 NTSTATUS
2124 ClassDetermineTokenOperationCommandSupport(
2125 _In_ PDEVICE_OBJECT DeviceObject
2126 );
2127
2128 _IRQL_requires_same_
2129 NTSTATUS
2130 ClasspGetBlockDeviceTokenLimitsInfo(
2131 _Inout_ PDEVICE_OBJECT DeviceObject
2132 );
2133
2134 _IRQL_requires_max_(APC_LEVEL)
2135 _IRQL_requires_min_(PASSIVE_LEVEL)
2136 _IRQL_requires_same_
2137 NTSTATUS
2138 ClassDeviceProcessOffloadRead(
2139 _In_ PDEVICE_OBJECT DeviceObject,
2140 _In_ PIRP Irp,
2141 _Inout_ PSCSI_REQUEST_BLOCK Srb
2142 );
2143
2144 _IRQL_requires_max_(APC_LEVEL)
2145 _IRQL_requires_min_(PASSIVE_LEVEL)
2146 _IRQL_requires_same_
2147 NTSTATUS
2148 ClassDeviceProcessOffloadWrite(
2149 _In_ PDEVICE_OBJECT DeviceObject,
2150 _In_ PIRP Irp,
2151 _Inout_ PSCSI_REQUEST_BLOCK Srb
2152 );
2153
2154 _IRQL_requires_max_(APC_LEVEL)
2155 _IRQL_requires_min_(PASSIVE_LEVEL)
2156 _IRQL_requires_same_
2157 NTSTATUS
2158 ClasspServicePopulateTokenTransferRequest(
2159 _In_ PDEVICE_OBJECT Fdo,
2160 _In_ PIRP Irp
2161 );
2162
2163 _IRQL_requires_same_
2164 VOID
2165 ClasspReceivePopulateTokenInformation(
2166 _In_ POFFLOAD_READ_CONTEXT OffloadReadContext
2167 );
2168
2169 _IRQL_requires_max_(APC_LEVEL)
2170 _IRQL_requires_min_(PASSIVE_LEVEL)
2171 _IRQL_requires_same_
2172 NTSTATUS
2173 ClasspServiceWriteUsingTokenTransferRequest(
2174 _In_ PDEVICE_OBJECT Fdo,
2175 _In_ PIRP Irp
2176 );
2177
2178 _IRQL_requires_same_
2179 VOID
2180 ClasspReceiveWriteUsingTokenInformation(
2181 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2182 );
2183
2184 VOID
2185 ClasspCompleteOffloadRequest(
2186 _In_ PDEVICE_OBJECT DeviceObject,
2187 _In_ PIRP Irp,
2188 _In_ NTSTATUS CompletionStatus
2189 );
2190
2191 VOID
2192 ClasspCleanupOffloadReadContext(
2193 _In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext
2194 );
2195
2196 VOID
2197 ClasspCompleteOffloadRead(
2198 _In_ POFFLOAD_READ_CONTEXT OffloadReadContext,
2199 _In_ NTSTATUS CompletionStatus
2200 );
2201
2202 // PCONTINUATION_ROUTINE
2203 VOID
2204 ClasspPopulateTokenTransferPacketDone(
2205 _In_ PVOID Context
2206 );
2207
2208 // PCONTINUATION_ROUTINE
2209 VOID
2210 ClasspReceivePopulateTokenInformationTransferPacketDone(
2211 _In_ PVOID Context
2212 );
2213
2214 VOID
2215 ClasspContinueOffloadWrite(
2216 _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2217 );
2218
2219 VOID
2220 ClasspCleanupOffloadWriteContext(
2221 _In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2222 );
2223
2224 VOID
2225 ClasspCompleteOffloadWrite(
2226 _In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
2227 _In_ NTSTATUS CompletionCausingStatus
2228 );
2229
2230 VOID
2231 ClasspReceiveWriteUsingTokenInformationDone(
2232 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
2233 _In_ NTSTATUS CompletionCausingStatus
2234 );
2235
2236 VOID
2237 ClasspWriteUsingTokenTransferPacketDone(
2238 _In_ PVOID Context
2239 );
2240
2241 VOID
2242 ClasspReceiveWriteUsingTokenInformationTransferPacketDone(
2243 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext
2244 );
2245
2246 NTSTATUS
2247 ClasspRefreshFunctionSupportInfo(
2248 _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2249 _In_ BOOLEAN ForceQuery
2250 );
2251
2252 NTSTATUS
2253 ClasspBlockLimitsDataSnapshot(
2254 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2255 _In_ BOOLEAN ForceQuery,
2256 _Out_ PCLASS_VPD_B0_DATA BlockLimitsData,
2257 _Out_ PULONG GenerationCount
2258 );
2259
2260 NTSTATUS
2261 InterpretReadCapacity16Data (
2262 _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2263 _In_ PREAD_CAPACITY16_DATA ReadCapacity16Data
2264 );
2265
2266 NTSTATUS
2267 ClassReadCapacity16 (
2268 _Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2269 _Inout_ PSCSI_REQUEST_BLOCK Srb
2270 );
2271
2272 NTSTATUS
2273 ClassDeviceGetLBProvisioningResources(
2274 _In_ PDEVICE_OBJECT DeviceObject,
2275 _Inout_ PIRP Irp,
2276 _Inout_ PSCSI_REQUEST_BLOCK Srb
2277 );
2278
2279 _IRQL_requires_same_
2280 NTSTATUS
2281 ClasspStorageEventNotification(
2282 _In_ PDEVICE_OBJECT DeviceObject,
2283 _In_ PIRP Irp
2284 );
2285
2286 _IRQL_requires_max_(PASSIVE_LEVEL)
2287 NTSTATUS
2288 ClasspPowerActivateDevice(
2289 _In_ PDEVICE_OBJECT DeviceObject
2290 );
2291
2292 _IRQL_requires_max_(PASSIVE_LEVEL)
2293 NTSTATUS
2294 ClasspPowerIdleDevice(
2295 _In_ PDEVICE_OBJECT DeviceObject
2296 );
2297
2298 IO_WORKITEM_ROUTINE ClassLogThresholdEvent;
2299
2300 NTSTATUS
2301 ClasspLogSystemEventWithDeviceNumber(
2302 _In_ PDEVICE_OBJECT DeviceObject,
2303 _In_ NTSTATUS IoErrorCode
2304 );
2305
2306 IO_WORKITEM_ROUTINE ClassLogResourceExhaustionEvent;
2307
2308 NTSTATUS
2309 ClasspEnqueueIdleRequest(
2310 PDEVICE_OBJECT DeviceObject,
2311 PIRP Irp
2312 );
2313
2314 VOID
2315 ClasspCompleteIdleRequest(
2316 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2317 );
2318
2319 NTSTATUS
2320 ClasspPriorityHint(
2321 PDEVICE_OBJECT DeviceObject,
2322 PIRP Irp
2323 );
2324
2325 VOID
2326 HistoryInitializeRetryLogs(
2327 _Out_ PSRB_HISTORY History,
2328 ULONG HistoryCount
2329 );
2330 #define HISTORYINITIALIZERETRYLOGS(_packet) \
2331 { \
2332 if (_packet->RetryHistory != NULL) \
2333 { \
2334 HistoryInitializeRetryLogs( \
2335 _packet->RetryHistory, \
2336 _packet->RetryHistory->TotalHistoryCount \
2337 ); \
2338 } \
2339 }
2340
2341 VOID
2342 HistoryLogSendPacket(
2343 TRANSFER_PACKET *Pkt
2344 );
2345 #define HISTORYLOGSENDPACKET(_packet) \
2346 { \
2347 if (_packet->RetryHistory != NULL) { \
2348 HistoryLogSendPacket(_packet); \
2349 } \
2350 }
2351
2352 VOID
2353 HistoryLogReturnedPacket(
2354 TRANSFER_PACKET *Pkt
2355 );
2356
2357 #define HISTORYLOGRETURNEDPACKET(_packet) \
2358 { \
2359 if (_packet->RetryHistory != NULL) { \
2360 HistoryLogReturnedPacket(_packet); \
2361 } \
2362 }
2363
2364 BOOLEAN
2365 InterpretSenseInfoWithoutHistory(
2366 _In_ PDEVICE_OBJECT Fdo,
2367 _In_opt_ PIRP OriginalRequest,
2368 _In_ PSCSI_REQUEST_BLOCK Srb,
2369 UCHAR MajorFunctionCode,
2370 ULONG IoDeviceCode,
2371 ULONG PreviousRetryCount,
2372 _Out_ NTSTATUS * Status,
2373 _Out_opt_ _Deref_out_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
2374 LONGLONG * RetryIn100nsUnits
2375 );
2376
2377 BOOLEAN
2378 ClasspMyStringMatches(
2379 _In_opt_z_ PCHAR StringToMatch,
2380 _In_z_ PCHAR TargetString
2381 );
2382
2383
2384
2385 #define TRACKING_FORWARD_PROGRESS_PATH1 (0x00000001)
2386 #define TRACKING_FORWARD_PROGRESS_PATH2 (0x00000002)
2387 #define TRACKING_FORWARD_PROGRESS_PATH3 (0x00000004)
2388
2389
2390 VOID
2391 ClasspInitializeRemoveTracking(
2392 _In_ PDEVICE_OBJECT DeviceObject
2393 );
2394
2395 VOID
2396 ClasspUninitializeRemoveTracking(
2397 _In_ PDEVICE_OBJECT DeviceObject
2398 );
2399
2400 RTL_GENERIC_COMPARE_ROUTINE RemoveTrackingCompareRoutine;
2401
2402 RTL_GENERIC_ALLOCATE_ROUTINE RemoveTrackingAllocateRoutine;
2403
2404 RTL_GENERIC_FREE_ROUTINE RemoveTrackingFreeRoutine;
2405
2406 #if (NTDDI_VERSION >= NTDDI_WIN8)
2407
2408 typedef PVOID
2409 (*PSRB_ALLOCATE_ROUTINE) (
2410 _In_ CLONG ByteSize
2411 );
2412
2413 PVOID
2414 DefaultStorageRequestBlockAllocateRoutine(
2415 _In_ CLONG ByteSize
2416 );
2417
2418
2419 NTSTATUS
2420 CreateStorageRequestBlock(
2421 _Inout_ PSTORAGE_REQUEST_BLOCK *Srb,
2422 _In_ USHORT AddressType,
2423 _In_opt_ PSRB_ALLOCATE_ROUTINE AllocateRoutine,
2424 _Inout_opt_ ULONG *ByteSize,
2425 _In_ ULONG NumSrbExData,
2426 ...
2427 );
2428
2429 NTSTATUS
2430 InitializeStorageRequestBlock(
2431 _Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb,
2432 _In_ USHORT AddressType,
2433 _In_ ULONG ByteSize,
2434 _In_ ULONG NumSrbExData,
2435 ...
2436 );
2437
2438 VOID
2439 ClasspConvertToScsiRequestBlock(
2440 _Out_ PSCSI_REQUEST_BLOCK Srb,
2441 _In_ PSTORAGE_REQUEST_BLOCK SrbEx
2442 );
2443
2444 FORCEINLINE PCDB
ClasspTransferPacketGetCdb(_In_ PTRANSFER_PACKET Pkt)2445 ClasspTransferPacketGetCdb(
2446 _In_ PTRANSFER_PACKET Pkt
2447 )
2448 {
2449 return SrbGetCdb(Pkt->Srb);
2450 }
2451
2452 //
2453 // This inline function calculates number of retries already happened till now for known operation codes
2454 // and set the out parameter - TimesAlreadyRetried with the value, returns True
2455 //
2456 // For unknown operation codes this function will return false and will set TimesAlreadyRetried with zero
2457 //
2458 FORCEINLINE BOOLEAN
ClasspTransferPacketGetNumberOfRetriesDone(_In_ PTRANSFER_PACKET Pkt,_In_ PCDB Cdb,_Out_ PULONG TimesAlreadyRetried)2459 ClasspTransferPacketGetNumberOfRetriesDone(
2460 _In_ PTRANSFER_PACKET Pkt,
2461 _In_ PCDB Cdb,
2462 _Out_ PULONG TimesAlreadyRetried
2463 )
2464 {
2465 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Pkt->Fdo->DeviceExtension;
2466 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
2467
2468 if (Cdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL)
2469 {
2470 *TimesAlreadyRetried = NUM_LOCKMEDIAREMOVAL_RETRIES - Pkt->NumRetries;
2471 }
2472 else if ((Cdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
2473 (Cdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10))
2474 {
2475 *TimesAlreadyRetried = NUM_MODESENSE_RETRIES - Pkt->NumRetries;
2476 }
2477 else if ((Cdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY) ||
2478 (Cdb->CDB16.OperationCode == SCSIOP_READ_CAPACITY16))
2479 {
2480 *TimesAlreadyRetried = NUM_DRIVECAPACITY_RETRIES - Pkt->NumRetries;
2481 }
2482 else if (IS_SCSIOP_READWRITE(Cdb->CDB10.OperationCode))
2483 {
2484 *TimesAlreadyRetried = fdoData->MaxNumberOfIoRetries - Pkt->NumRetries;
2485 }
2486 else if (Cdb->TOKEN_OPERATION.OperationCode == SCSIOP_POPULATE_TOKEN &&
2487 Cdb->TOKEN_OPERATION.ServiceAction == SERVICE_ACTION_POPULATE_TOKEN)
2488 {
2489 *TimesAlreadyRetried = NUM_POPULATE_TOKEN_RETRIES - Pkt->NumRetries;
2490 }
2491 else if (Cdb->TOKEN_OPERATION.OperationCode == SCSIOP_WRITE_USING_TOKEN &&
2492 Cdb->TOKEN_OPERATION.ServiceAction == SERVICE_ACTION_WRITE_USING_TOKEN)
2493 {
2494 *TimesAlreadyRetried = NUM_WRITE_USING_TOKEN_RETRIES - Pkt->NumRetries;
2495 }
2496 else if (ClasspIsReceiveTokenInformation(Cdb))
2497 {
2498 *TimesAlreadyRetried = NUM_RECEIVE_TOKEN_INFORMATION_RETRIES - Pkt->NumRetries;
2499 }
2500
2501 else
2502 {
2503 *TimesAlreadyRetried = 0;
2504 return FALSE;
2505 }
2506
2507
2508 return TRUE;
2509 }
2510
2511
2512 FORCEINLINE PVOID
ClasspTransferPacketGetSenseInfoBuffer(_In_ PTRANSFER_PACKET Pkt)2513 ClasspTransferPacketGetSenseInfoBuffer(
2514 _In_ PTRANSFER_PACKET Pkt
2515 )
2516 {
2517 return SrbGetSenseInfoBuffer(Pkt->Srb);
2518 }
2519
2520 FORCEINLINE UCHAR
ClasspTransferPacketGetSenseInfoBufferLength(_In_ PTRANSFER_PACKET Pkt)2521 ClasspTransferPacketGetSenseInfoBufferLength(
2522 _In_ PTRANSFER_PACKET Pkt
2523 )
2524 {
2525 return SrbGetSenseInfoBufferLength(Pkt->Srb);
2526 }
2527
2528
2529 FORCEINLINE VOID
ClasspSrbSetOriginalIrp(_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb,_In_ PIRP Irp)2530 ClasspSrbSetOriginalIrp(
2531 _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb,
2532 _In_ PIRP Irp
2533 )
2534 {
2535 if (Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK)
2536 {
2537 ((PSTORAGE_REQUEST_BLOCK)Srb)->MiniportContext = (PVOID)Irp;
2538 }
2539 else
2540 {
2541 ((PSCSI_REQUEST_BLOCK)Srb)->SrbExtension = (PVOID)Irp;
2542 }
2543 }
2544
2545 FORCEINLINE
2546 BOOLEAN
PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)2547 PORT_ALLOCATED_SENSE_EX(
2548 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2549 _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb
2550 )
2551 {
2552 return ((BOOLEAN)((TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) &&
2553 TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_FREE_SENSE_BUFFER)) &&
2554 (SrbGetSenseInfoBuffer(Srb) != FdoExtension->SenseData))
2555 );
2556 }
2557
2558 FORCEINLINE
2559 VOID
FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)2560 FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(
2561 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
2562 _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb
2563 )
2564 {
2565 NT_ASSERT(TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
2566 NT_ASSERT(TEST_FLAG(SrbGetSrbFlags(Srb), SRB_FLAGS_FREE_SENSE_BUFFER));
2567 NT_ASSERT(SrbGetSenseInfoBuffer(Srb) != FdoExtension->SenseData);
2568
2569 ExFreePool(SrbGetSenseInfoBuffer(Srb));
2570 SrbSetSenseInfoBuffer(Srb, FdoExtension->SenseData);
2571 SrbSetSenseInfoBufferLength(Srb, GET_FDO_EXTENSON_SENSE_DATA_LENGTH(FdoExtension));
2572 SrbClearSrbFlags(Srb, SRB_FLAGS_FREE_SENSE_BUFFER);
2573 return;
2574 }
2575
2576 #endif //NTDDI_WIN8
2577
2578 BOOLEAN
2579 ClasspFailurePredictionPeriodMissed(
2580 _In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
2581 );
2582
2583 FORCEINLINE
2584 ULONG
ClasspGetMaxUsableBufferLengthFromOffset(_In_ PVOID BaseAddress,_In_ ULONG OffsetInBytes,_In_ ULONG BaseStructureSizeInBytes)2585 ClasspGetMaxUsableBufferLengthFromOffset(
2586 _In_ PVOID BaseAddress,
2587 _In_ ULONG OffsetInBytes,
2588 _In_ ULONG BaseStructureSizeInBytes
2589 )
2590 /*++
2591
2592 Routine Description:
2593
2594 This routine returns the maximum size of a buffer that starts at a given offset,
2595 based on the size of the containing structure.
2596
2597 Arguments:
2598
2599 BaseAddress - The base address of the structure. The offset is computed relative to this.
2600
2601 OffsetInBytes - (BaseAddress + OffsetInBytes) points to the beginning of the buffer.
2602
2603 BaseStructureSizeInBytes - The size of the structure which contains the buffer.
2604
2605 Return Value:
2606
2607 max(BaseStructureSizeInBytes - OffsetInBytes, 0). If any operations wrap around,
2608 the return value is 0.
2609
2610 --*/
2611
2612 {
2613
2614 ULONG_PTR offsetAddress = ((ULONG_PTR)BaseAddress + OffsetInBytes);
2615
2616 if (offsetAddress < (ULONG_PTR)BaseAddress) {
2617 //
2618 // This means BaseAddress + OffsetInBytes > ULONG_PTR_MAX.
2619 //
2620 return 0;
2621 }
2622
2623 if (OffsetInBytes > BaseStructureSizeInBytes) {
2624 return 0;
2625 }
2626
2627 return BaseStructureSizeInBytes - OffsetInBytes;
2628 }
2629
2630
2631 BOOLEAN
2632 ClasspIsThinProvisioningError (
2633 _In_ PSCSI_REQUEST_BLOCK _Srb
2634 );
2635
2636 FORCEINLINE
2637 BOOLEAN
ClasspLowerLayerNotSupport(_In_ NTSTATUS Status)2638 ClasspLowerLayerNotSupport (
2639 _In_ NTSTATUS Status
2640 )
2641 {
2642 return ((Status == STATUS_NOT_SUPPORTED) ||
2643 (Status == STATUS_NOT_IMPLEMENTED) ||
2644 (Status == STATUS_INVALID_DEVICE_REQUEST) ||
2645 (Status == STATUS_INVALID_PARAMETER_1));
2646 }
2647
2648 #if defined(__REACTOS__) && (NTDDI_VERSION >= NTDDI_WINBLUE)
2649 FORCEINLINE
2650 BOOLEAN
ClasspSrbTimeOutStatus(_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)2651 ClasspSrbTimeOutStatus (
2652 _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb
2653 )
2654 {
2655 UCHAR srbStatus = SrbGetSrbStatus(Srb);
2656 return ((srbStatus == SRB_STATUS_BUS_RESET) ||
2657 (srbStatus == SRB_STATUS_TIMEOUT) ||
2658 (srbStatus == SRB_STATUS_COMMAND_TIMEOUT) ||
2659 (srbStatus == SRB_STATUS_ABORTED));
2660 }
2661 #endif
2662
2663 NTSTATUS
2664 ClassDeviceHwFirmwareGetInfoProcess(
2665 _In_ PDEVICE_OBJECT DeviceObject,
2666 _Inout_ PIRP Irp
2667 );
2668
2669 NTSTATUS
2670 ClassDeviceHwFirmwareDownloadProcess(
2671 _In_ PDEVICE_OBJECT DeviceObject,
2672 _Inout_ PIRP Irp,
2673 _Inout_ PSCSI_REQUEST_BLOCK Srb
2674 );
2675
2676 NTSTATUS
2677 ClassDeviceHwFirmwareActivateProcess(
2678 _In_ PDEVICE_OBJECT DeviceObject,
2679 _Inout_ PIRP Irp,
2680 _Inout_ PSCSI_REQUEST_BLOCK Srb
2681 );
2682
2683