1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 1999
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 #ifndef _CLASSPNP_PCH_
29 #define _CLASSPNP_PCH_
30 
31 #include <ntddk.h>
32 #include <classpnp.h>
33 #include <ioevent.h>
34 #include <pseh/pseh2.h>
35 
36 extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[];
37 
38 extern GUID ClassGuidQueryRegInfoEx;
39 
40 
41 #define CLASSP_REG_SUBKEY_NAME                  (L"Classpnp")
42 
43 #define CLASSP_REG_HACK_VALUE_NAME              (L"HackMask")
44 #define CLASSP_REG_MMC_DETECTION_VALUE_NAME     (L"MMCDetectionState")
45 #define CLASSP_REG_WRITE_CACHE_VALUE_NAME       (L"WriteCacheEnableOverride")
46 #define CLASSP_REG_PERF_RESTORE_VALUE_NAME      (L"RestorePerfAtCount")
47 #define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME    (L"UserRemovalPolicy")
48 
49 #define CLASS_PERF_RESTORE_MINIMUM (0x10)
50 #define CLASS_ERROR_LEVEL_1 (0x4)
51 #define CLASS_ERROR_LEVEL_2 (0x8)
52 
53 #define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
54 #define FDO_HACK_GESN_IS_BAD       (0x00000002)
55 #define FDO_HACK_NO_SYNC_CACHE     (0x00000004)
56 
57 #define FDO_HACK_VALID_FLAGS       (0x00000007)
58 #define FDO_HACK_INVALID_FLAGS     (~FDO_HACK_VALID_FLAGS)
59 
60 /*
61  *  Lots of retries of synchronized SCSI commands that devices may not
62  *  even support really slows down the system (especially while booting).
63  *  (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
64  *  If a disk cannot return a small initialization buffer at startup
65  *  in two attempts (with delay interval) then we cannot expect it to return
66  *  data consistently with four retries.
67  *  So don't set the retry counts as high here as for data SRBs.
68  *
69  *  If we find that these requests are failing consecutively,
70  *  despite the retry interval, on otherwise reliable media,
71  *  then we should either increase the retry interval for
72  *  that failure or (by all means) increase these retry counts as appropriate.
73  */
74 #define NUM_LOCKMEDIAREMOVAL_RETRIES    1
75 #define NUM_MODESENSE_RETRIES           1
76 #define NUM_DRIVECAPACITY_RETRIES       1
77 
78 
79 #define CLASS_FILE_OBJECT_EXTENSION_KEY     'eteP'
80 #define CLASSP_VOLUME_VERIFY_CHECKED        0x34
81 
82 #define CLASS_TAG_PRIVATE_DATA              'CPcS'
83 #define CLASS_TAG_PRIVATE_DATA_FDO          'FPcS'
84 #define CLASS_TAG_PRIVATE_DATA_PDO          'PPcS'
85 
86 struct _MEDIA_CHANGE_DETECTION_INFO {
87 
88     //
89     // Mutex to synchronize enable/disable requests and media state changes
90     //
91 
92     KMUTEX MediaChangeMutex;
93 
94     //
95     // The current state of the media (present, not present, unknown)
96     // protected by MediaChangeSynchronizationEvent
97     //
98 
99     MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState;
100 
101     //
102     // This is a count of how many time MCD has been disabled.  if it is
103     // set to zero, then we'll poll the device for MCN events with the
104     // then-current method (ie. TEST UNIT READY or GESN).  this is
105     // protected by MediaChangeMutex
106     //
107 
108     LONG MediaChangeDetectionDisableCount;
109 
110 
111     //
112     // The timer value to support media change events.  This is a countdown
113     // value used to determine when to poll the device for a media change.
114     // The max value for the timer is 255 seconds.  This is not protected
115     // by an event -- simply InterlockedExchanged() as needed.
116     //
117 
118     LONG MediaChangeCountDown;
119 
120     //
121     // recent changes allowed instant retries of the MCN irp.  Since this
122     // could cause an infinite loop, keep a count of how many times we've
123     // retried immediately so that we can catch if the count exceeds an
124     // arbitrary limit.
125     //
126 
127     LONG MediaChangeRetryCount;
128 
129     //
130     // use GESN if it's available
131     //
132 
133     struct {
134         BOOLEAN Supported;
135         BOOLEAN HackEventMask;
136         UCHAR   EventMask;
137         UCHAR   NoChangeEventMask;
138         PUCHAR  Buffer;
139         PMDL    Mdl;
140         ULONG   BufferSize;
141     } Gesn;
142 
143     //
144     // If this value is one, then the irp is currently in use.
145     // If this value is zero, then the irp is available.
146     // Use InterlockedCompareExchange() to set from "available" to "in use".
147     // ASSERT that InterlockedCompareExchange() showed previous value of
148     //    "in use" when changing back to "available" state.
149     // This also implicitly protects the MediaChangeSrb and SenseBuffer
150     //
151 
152     LONG MediaChangeIrpInUse;
153 
154     //
155     // Pointer to the irp to be used for media change detection.
156     // protected by Interlocked MediaChangeIrpInUse
157     //
158 
159     PIRP MediaChangeIrp;
160 
161     //
162     // The srb for the media change detection.
163     // protected by Interlocked MediaChangeIrpInUse
164     //
165 
166     SCSI_REQUEST_BLOCK MediaChangeSrb;
167     PUCHAR SenseBuffer;
168     ULONG SrbFlags;
169 
170     //
171     // Second timer to keep track of how long the media change IRP has been
172     // in use.  If this value exceeds the timeout (#defined) then we should
173     // print out a message to the user and set the MediaChangeIrpLost flag
174     // protected by using Interlocked() operations in ClasspSendMediaStateIrp,
175     // the only routine which should modify this value.
176     //
177 
178     LONG MediaChangeIrpTimeInUse;
179 
180     //
181     // Set by CdRomTickHandler when we determine that the media change irp has
182     // been lost
183     //
184 
185     BOOLEAN MediaChangeIrpLost;
186 
187 };
188 
189 typedef enum {
190     SimpleMediaLock,
191     SecureMediaLock,
192     InternalMediaLock
193 } MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
194 
195 typedef struct _FAILURE_PREDICTION_INFO {
196     FAILURE_PREDICTION_METHOD Method;
197     ULONG CountDown;                // Countdown timer
198     ULONG Period;                   // Countdown period
199 
200     PIO_WORKITEM WorkQueueItem;
201 
202     KEVENT Event;
203 } FAILURE_PREDICTION_INFO, *PFAILURE_PREDICTION_INFO;
204 
205 
206 
207 //
208 // This struct must always fit within four PVOIDs of info,
209 // as it uses the irp's "PVOID DriverContext[4]" to store
210 // this info
211 //
212 typedef struct _CLASS_RETRY_INFO {
213     struct _CLASS_RETRY_INFO *Next;
214 } CLASS_RETRY_INFO, *PCLASS_RETRY_INFO;
215 
216 
217 
218 typedef struct _CSCAN_LIST {
219 
220     //
221     // The current block which has an outstanding request.
222     //
223 
224     ULONGLONG BlockNumber;
225 
226     //
227     // The list of blocks past the CurrentBlock to which we're going to do
228     // i/o.  This list is maintained in sorted order.
229     //
230 
231     LIST_ENTRY CurrentSweep;
232 
233     //
234     // The list of blocks behind the current block for which we'll have to
235     // wait until the next scan across the disk.  This is kept as a stack,
236     // the cost of sorting it is taken when it's moved over to be the
237     // running list.
238     //
239 
240     LIST_ENTRY NextSweep;
241 
242 } CSCAN_LIST, *PCSCAN_LIST;
243 
244 //
245 // add to the front of this structure to help prevent illegal
246 // snooping by other utilities.
247 //
248 
249 
250 
251 typedef enum _CLASS_DETECTION_STATE {
252     ClassDetectionUnknown = 0,
253     ClassDetectionUnsupported = 1,
254     ClassDetectionSupported = 2
255 } CLASS_DETECTION_STATE, *PCLASS_DETECTION_STATE;
256 
257 
258 typedef struct _CLASS_ERROR_LOG_DATA {
259     LARGE_INTEGER TickCount;        // Offset 0x00
260     ULONG PortNumber;               // Offset 0x08
261 
262     UCHAR ErrorPaging    : 1;       // Offset 0x0c
263     UCHAR ErrorRetried   : 1;
264     UCHAR ErrorUnhandled : 1;
265     UCHAR ErrorReserved  : 5;
266 
267     UCHAR Reserved[3];
268 
269     SCSI_REQUEST_BLOCK Srb;     // Offset 0x10
270 
271     /*
272      *  We define the SenseData as the default length.
273      *  Since the sense data returned by the port driver may be longer,
274      *  SenseData must be at the end of this structure.
275      *  For our internal error log, we only log the default length.
276      */
277     SENSE_DATA SenseData;     // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
278 } CLASS_ERROR_LOG_DATA, *PCLASS_ERROR_LOG_DATA;
279 
280 #define NUM_ERROR_LOG_ENTRIES   16
281 
282 
283 
284 typedef struct _TRANSFER_PACKET {
285 
286         SLIST_ENTRY SlistEntry;   // for when in free list (use fast slist)
287         LIST_ENTRY AllPktsListEntry;    // entry in fdoData's static AllTransferPacketsList
288 
289         PIRP Irp;
290         PDEVICE_OBJECT Fdo;
291 
292         /*
293          *  This is the client IRP that this TRANSFER_PACKET is currently
294          *  servicing.
295          */
296         PIRP OriginalIrp;
297         BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes;
298 
299         /*
300          *  Stuff for retrying the transfer.
301          */
302         ULONG NumRetries;
303         KTIMER RetryTimer;
304         KDPC RetryTimerDPC;
305         ULONG RetryIntervalSec;
306 
307         /*
308          *  Event for synchronizing the transfer (optional).
309          *  (Note that we can't have the event in the packet itself because
310          *  by the time a thread waits on an event the packet may have
311          *  been completed and re-issued.
312          */
313         PKEVENT SyncEventPtr;
314 
315         /*
316          *  Stuff for retrying during extreme low-memory stress
317          *  (when we retry 1 page at a time).
318          */
319         BOOLEAN InLowMemRetry;
320         PUCHAR LowMemRetry_remainingBufPtr;
321         ULONG LowMemRetry_remainingBufLen;
322         LARGE_INTEGER LowMemRetry_nextChunkTargetLocation;
323 
324         /*
325          *  Fields used for cancelling the packet.
326          */
327         // BOOLEAN Cancelled;
328         // KEVENT CancelledEvent;
329 
330         /*
331          *  We keep the buffer and length values here as well
332          *  as in the SRB because some miniports return
333          *  the transferred length in SRB.DataTransferLength,
334          *  and if the SRB failed we need that value again for the retry.
335          *  We don't trust the lower stack to preserve any of these values in the SRB.
336          */
337         PUCHAR BufPtrCopy;
338         ULONG BufLenCopy;
339         LARGE_INTEGER TargetLocationCopy;
340 
341         /*
342          *  This is a standard SCSI structure that receives a detailed
343          *  report about a SCSI error on the hardware.
344          */
345         SENSE_DATA SrbErrorSenseData;
346 
347         /*
348          *  This is the SRB block for this TRANSFER_PACKET.
349          *  For IOCTLs, the SRB block includes two DWORDs for
350          *  device object and ioctl code; so these must
351          *  immediately follow the SRB block.
352          */
353         SCSI_REQUEST_BLOCK Srb;
354         // ULONG SrbIoctlDevObj;        // not handling ioctls yet
355         // ULONG SrbIoctlCode;
356 
357 } TRANSFER_PACKET, *PTRANSFER_PACKET;
358 
359 /*
360  *  MIN_INITIAL_TRANSFER_PACKETS is the minimum number of packets that
361  *  we preallocate at startup for each device (we need at least one packet
362  *  to guarantee forward progress during memory stress).
363  *  MIN_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
364  *  we allow to build up and remain for each device;
365  *  we _lazily_ work down to this number when they're not needed.
366  *  MAX_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
367  *  that we _immediately_ reduce to when they are not needed.
368  *
369  *  The absolute maximum number of packets that we will allocate is
370  *  whatever is required by the current activity, up to the memory limit;
371  *  as soon as stress ends, we snap down to MAX_WORKINGSET_TRANSFER_PACKETS;
372  *  we then lazily work down to MIN_WORKINGSET_TRANSFER_PACKETS.
373  */
374 #define MIN_INITIAL_TRANSFER_PACKETS                     1
375 #define MIN_WORKINGSET_TRANSFER_PACKETS_Consumer      4
376 #define MAX_WORKINGSET_TRANSFER_PACKETS_Consumer     64
377 #define MIN_WORKINGSET_TRANSFER_PACKETS_Server        64
378 #define MAX_WORKINGSET_TRANSFER_PACKETS_Server      1024
379 #define MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise    256
380 #define MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise   2048
381 
382 
383 //
384 // add to the front of this structure to help prevent illegal
385 // snooping by other utilities.
386 //
387 struct _CLASS_PRIVATE_FDO_DATA {
388 
389     //
390     // this private structure allows us to
391     // dynamically re-enable the perf benefits
392     // lost due to transient error conditions.
393     // in w2k, a reboot was required. :(
394     //
395     struct {
396         ULONG      OriginalSrbFlags;
397         ULONG      SuccessfulIO;
398         ULONG      ReEnableThreshold; // 0 means never
399     } Perf;
400 
401     ULONG_PTR HackFlags;
402 
403     STORAGE_HOTPLUG_INFO HotplugInfo;
404 
405     // Legacy.  Still used by obsolete legacy code.
406     struct {
407         LARGE_INTEGER     Delta;       // in ticks
408         LARGE_INTEGER     Tick;        // when it should fire
409         PCLASS_RETRY_INFO ListHead;    // singly-linked list
410         ULONG             Granularity; // static
411         KSPIN_LOCK        Lock;        // protective spin lock
412         KDPC              Dpc;         // DPC routine object
413         KTIMER            Timer;       // timer to fire DPC
414     } Retry;
415 
416     BOOLEAN TimerStarted;
417     BOOLEAN LoggedTURFailureSinceLastIO;
418 
419     //
420     // privately allocated release queue irp
421     // protected by fdoExtension->ReleaseQueueSpinLock
422     //
423     BOOLEAN ReleaseQueueIrpAllocated;
424     PIRP ReleaseQueueIrp;
425 
426     /*
427      *  Queues for TRANSFER_PACKETs that contextualize the IRPs and SRBs
428      *  that we send down to the port driver.
429      *  (The free list is an slist so that we can use fast
430      *   interlocked operations on it; but the relatively-static
431      *   AllTransferPacketsList list has to be
432      *   a doubly-linked list since we have to dequeue from the middle).
433      */
434     LIST_ENTRY AllTransferPacketsList;
435     SLIST_HEADER FreeTransferPacketsList;
436     ULONG NumFreeTransferPackets;
437     ULONG NumTotalTransferPackets;
438     ULONG DbgPeakNumTransferPackets;
439 
440     /*
441      *  Queue for deferred client irps
442      */
443     LIST_ENTRY DeferredClientIrpList;
444 
445     /*
446      *  Precomputed maximum transfer length for the hardware.
447      */
448     ULONG HwMaxXferLen;
449 
450     /*
451      *  SCSI_REQUEST_BLOCK template preconfigured with the constant values.
452      *  This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
453      */
454     SCSI_REQUEST_BLOCK SrbTemplate;
455 
456     KSPIN_LOCK SpinLock;
457 
458     /*
459      *  Circular array of timestamped logs of errors that occurred on this device.
460      */
461     ULONG ErrorLogNextIndex;
462     CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
463 
464 };
465 
466 
467 #define MIN(a, b)   ((a) < (b) ? (a) : (b))
468 #define MAX(a, b)   ((a) > (b) ? (a) : (b))
469 
470 
471 #define NOT_READY_RETRY_INTERVAL    10
472 #define MINIMUM_RETRY_UNITS ((LONGLONG)32)
473 
474 
475 /*
476  *  Simple singly-linked-list queuing macros, with no synchronization.
477  */
478 static inline VOID SimpleInitSlistHdr(SLIST_ENTRY *SListHdr)
479 {
480     SListHdr->Next = NULL;
481 }
482 static inline VOID SimplePushSlist(SLIST_ENTRY *SListHdr, SLIST_ENTRY *SListEntry)
483 {
484     SListEntry->Next = SListHdr->Next;
485     SListHdr->Next = SListEntry;
486 }
487 static inline SLIST_ENTRY *SimplePopSlist(SLIST_ENTRY *SListHdr)
488 {
489     SLIST_ENTRY *sListEntry = SListHdr->Next;
490     if (sListEntry){
491         SListHdr->Next = sListEntry->Next;
492         sListEntry->Next = NULL;
493     }
494     return sListEntry;
495 }
496 static inline BOOLEAN SimpleIsSlistEmpty(SLIST_ENTRY *SListHdr)
497 {
498     return (SListHdr->Next == NULL);
499 }
500 
501 DRIVER_INITIALIZE DriverEntry;
502 
503 DRIVER_UNLOAD ClassUnload;
504 
505 DRIVER_DISPATCH ClassCreateClose;
506 
507 NTSTATUS
508 NTAPI
509 ClasspCreateClose(
510     IN PDEVICE_OBJECT DeviceObject,
511     IN PIRP Irp
512     );
513 
514 VOID
515 NTAPI
516 ClasspCleanupProtectedLocks(
517     IN PFILE_OBJECT_EXTENSION FsContext
518     );
519 
520 NTSTATUS
521 NTAPI
522 ClasspEjectionControl(
523     IN PDEVICE_OBJECT Fdo,
524     IN PIRP Irp,
525     IN MEDIA_LOCK_TYPE LockType,
526     IN BOOLEAN Lock
527     );
528 
529 DRIVER_DISPATCH ClassReadWrite;
530 
531 DRIVER_DISPATCH ClassDeviceControlDispatch;
532 
533 DRIVER_DISPATCH ClassDispatchPnp;
534 
535 NTSTATUS
536 NTAPI
537 ClassPnpStartDevice(
538     IN PDEVICE_OBJECT DeviceObject
539     );
540 
541 NTSTATUS
542 NTAPI
543 ClassShutdownFlush(
544     IN PDEVICE_OBJECT DeviceObject,
545     IN PIRP Irp
546     );
547 
548 DRIVER_DISPATCH ClassSystemControl;
549 
550 //
551 // Class internal routines
552 //
553 
554 DRIVER_ADD_DEVICE ClassAddDevice;
555 
556 IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion;
557 
558 VOID
559 NTAPI
560 RetryRequest(
561     PDEVICE_OBJECT DeviceObject,
562     PIRP Irp,
563     PSCSI_REQUEST_BLOCK Srb,
564     BOOLEAN Associated,
565     ULONG RetryInterval
566     );
567 
568 NTSTATUS
569 NTAPI
570 ClassIoCompletion(
571     IN PDEVICE_OBJECT DeviceObject,
572     IN PIRP Irp,
573     IN PVOID Context
574     );
575 
576 NTSTATUS
577 NTAPI
578 ClassPnpQueryFdoRelations(
579     IN PDEVICE_OBJECT Fdo,
580     IN PIRP Irp
581     );
582 
583 NTSTATUS
584 NTAPI
585 ClassRetrieveDeviceRelations(
586     IN PDEVICE_OBJECT Fdo,
587     IN DEVICE_RELATION_TYPE RelationType,
588     OUT PDEVICE_RELATIONS *DeviceRelations
589     );
590 
591 NTSTATUS
592 NTAPI
593 ClassGetPdoId(
594     IN PDEVICE_OBJECT Pdo,
595     IN BUS_QUERY_ID_TYPE IdType,
596     IN PUNICODE_STRING IdString
597     );
598 
599 NTSTATUS
600 NTAPI
601 ClassQueryPnpCapabilities(
602     IN PDEVICE_OBJECT PhysicalDeviceObject,
603     IN PDEVICE_CAPABILITIES Capabilities
604     );
605 
606 DRIVER_STARTIO ClasspStartIo;
607 
608 NTSTATUS
609 NTAPI
610 ClasspPagingNotificationCompletion(
611     IN PDEVICE_OBJECT DeviceObject,
612     IN PIRP Irp,
613     IN PDEVICE_OBJECT RealDeviceObject
614     );
615 
616 NTSTATUS
617 NTAPI
618 ClasspMediaChangeCompletion(
619     PDEVICE_OBJECT DeviceObject,
620     PIRP Irp,
621     PVOID Context
622     );
623 
624 PFILE_OBJECT_EXTENSION
625 NTAPI
626 ClasspGetFsContext(
627     IN PCOMMON_DEVICE_EXTENSION CommonExtension,
628     IN PFILE_OBJECT FileObject
629     );
630 
631 NTSTATUS
632 NTAPI
633 ClasspMcnControl(
634     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
635     IN PIRP Irp,
636     IN PSCSI_REQUEST_BLOCK Srb
637     );
638 
639 VOID
640 NTAPI
641 ClasspRegisterMountedDeviceInterface(
642     IN PDEVICE_OBJECT DeviceObject
643     );
644 
645 NTSTATUS
646 NTAPI
647 ClasspDisableTimer(
648     PDEVICE_OBJECT DeviceObject
649     );
650 
651 NTSTATUS
652 NTAPI
653 ClasspEnableTimer(
654     PDEVICE_OBJECT DeviceObject
655     );
656 
657 //
658 // routines for dictionary list support
659 //
660 
661 VOID
662 NTAPI
663 InitializeDictionary(
664     IN PDICTIONARY Dictionary
665     );
666 
667 BOOLEAN
668 NTAPI
669 TestDictionarySignature(
670     IN PDICTIONARY Dictionary
671     );
672 
673 NTSTATUS
674 NTAPI
675 AllocateDictionaryEntry(
676     IN PDICTIONARY Dictionary,
677     IN ULONGLONG Key,
678     IN ULONG Size,
679     IN ULONG Tag,
680     OUT PVOID *Entry
681     );
682 
683 PVOID
684 NTAPI
685 GetDictionaryEntry(
686     IN PDICTIONARY Dictionary,
687     IN ULONGLONG Key
688     );
689 
690 VOID
691 NTAPI
692 FreeDictionaryEntry(
693     IN PDICTIONARY Dictionary,
694     IN PVOID Entry
695     );
696 
697 
698 NTSTATUS
699 NTAPI
700 ClasspAllocateReleaseRequest(
701     IN PDEVICE_OBJECT Fdo
702     );
703 
704 VOID
705 NTAPI
706 ClasspFreeReleaseRequest(
707     IN PDEVICE_OBJECT Fdo
708     );
709 
710 IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion;
711 
712 VOID
713 NTAPI
714 ClasspReleaseQueue(
715     IN PDEVICE_OBJECT DeviceObject,
716     IN PIRP ReleaseQueueIrp
717     );
718 
719 VOID
720 NTAPI
721 ClasspDisablePowerNotification(
722     PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
723 );
724 
725 //
726 // class power routines
727 //
728 
729 DRIVER_DISPATCH ClassDispatchPower;
730 
731 NTSTATUS
732 NTAPI
733 ClassMinimalPowerHandler(
734     IN PDEVICE_OBJECT DeviceObject,
735     IN PIRP Irp
736     );
737 
738 //
739 // Child list routines
740 //
741 
742 VOID
743 NTAPI
744 ClassAddChild(
745     IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
746     IN PPHYSICAL_DEVICE_EXTENSION Child,
747     IN BOOLEAN AcquireLock
748     );
749 
750 PPHYSICAL_DEVICE_EXTENSION
751 NTAPI
752 ClassRemoveChild(
753     IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
754     IN PPHYSICAL_DEVICE_EXTENSION Child,
755     IN BOOLEAN AcquireLock
756     );
757 
758 VOID
759 NTAPI
760 ClasspRetryDpcTimer(
761     IN PCLASS_PRIVATE_FDO_DATA FdoData
762     );
763 
764 KDEFERRED_ROUTINE ClasspRetryRequestDpc;
765 
766 VOID
767 NTAPI
768 ClassFreeOrReuseSrb(
769     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
770     IN PSCSI_REQUEST_BLOCK Srb
771     );
772 
773 VOID
774 NTAPI
775 ClassRetryRequest(
776     IN PDEVICE_OBJECT SelfDeviceObject,
777     IN PIRP           Irp,
778     IN LARGE_INTEGER  TimeDelta100ns // in 100ns units
779     );
780 
781 VOID
782 NTAPI
783 ClasspBuildRequestEx(
784     IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
785     IN PIRP Irp,
786     IN PSCSI_REQUEST_BLOCK Srb
787     );
788 
789 NTSTATUS
790 NTAPI
791 ClasspAllocateReleaseQueueIrp(
792     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
793     );
794 
795 NTSTATUS
796 NTAPI
797 ClasspInitializeGesn(
798     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
799     IN PMEDIA_CHANGE_DETECTION_INFO Info
800     );
801 
802 VOID
803 NTAPI
804 ClasspSendNotification(
805     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
806     IN const GUID * Guid,
807     IN ULONG  ExtraDataSize,
808     IN PVOID  ExtraData
809     );
810 
811 VOID
812 NTAPI
813 ClassSendEjectionNotification(
814     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
815     );
816 
817 VOID
818 NTAPI
819 ClasspScanForSpecialInRegistry(
820     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
821     );
822 
823 VOID
824 NTAPI
825 ClasspScanForClassHacks(
826     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
827     IN ULONG_PTR Data
828     );
829 
830 NTSTATUS
831 NTAPI
832 ClasspInitializeHotplugInfo(
833     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
834     );
835 
836 VOID
837 NTAPI
838 ClasspPerfIncrementErrorCount(
839     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
840     );
841 VOID
842 NTAPI
843 ClasspPerfIncrementSuccessfulIo(
844     IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
845     );
846 
847 PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo);
848 VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt);
849 VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt);
850 PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded);
851 VOID NTAPI SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp);
852 VOID NTAPI SubmitTransferPacket(PTRANSFER_PACKET Pkt);
853 NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context);
854 VOID NTAPI ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp);
855 VOID NTAPI TransferPacketRetryTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
856 BOOLEAN NTAPI InterpretTransferPacketError(PTRANSFER_PACKET Pkt);
857 BOOLEAN NTAPI RetryTransferPacket(PTRANSFER_PACKET Pkt);
858 VOID NTAPI EnqueueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp);
859 PIRP NTAPI DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData);
860 VOID NTAPI InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation);
861 BOOLEAN NTAPI StepLowMemRetry(PTRANSFER_PACKET Pkt);
862 VOID NTAPI SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp);
863 VOID NTAPI SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, PIRP OriginalIrp);
864 VOID NTAPI SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp);
865 PMDL NTAPI BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen);
866 VOID NTAPI FreeDeviceInputMdl(PMDL Mdl);
867 NTSTATUS NTAPI InitializeTransferPackets(PDEVICE_OBJECT Fdo);
868 VOID NTAPI DestroyAllTransferPackets(PDEVICE_OBJECT Fdo);
869 
870 #include "debug.h"
871 
872 #endif /* _CLASSPNP_PCH_ */
873