3 Copyright (C) Microsoft Corporation, 1991 - 1999
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.
28 #ifndef _CLASSPNP_PCH_
29 #define _CLASSPNP_PCH_
34 #include <pseh/pseh2.h>
36 extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems
[];
38 extern GUID ClassGuidQueryRegInfoEx
;
41 #define CLASSP_REG_SUBKEY_NAME (L"Classpnp")
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")
49 #define CLASS_PERF_RESTORE_MINIMUM (0x10)
50 #define CLASS_ERROR_LEVEL_1 (0x4)
51 #define CLASS_ERROR_LEVEL_2 (0x8)
53 #define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
54 #define FDO_HACK_GESN_IS_BAD (0x00000002)
55 #define FDO_HACK_NO_SYNC_CACHE (0x00000004)
57 #define FDO_HACK_VALID_FLAGS (0x00000007)
58 #define FDO_HACK_INVALID_FLAGS (~FDO_HACK_VALID_FLAGS)
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.
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.
74 #define NUM_LOCKMEDIAREMOVAL_RETRIES 1
75 #define NUM_MODESENSE_RETRIES 1
76 #define NUM_DRIVECAPACITY_RETRIES 1
79 #define CLASS_FILE_OBJECT_EXTENSION_KEY 'eteP'
80 #define CLASSP_VOLUME_VERIFY_CHECKED 0x34
82 #define CLASS_TAG_PRIVATE_DATA 'CPcS'
83 #define CLASS_TAG_PRIVATE_DATA_FDO 'FPcS'
84 #define CLASS_TAG_PRIVATE_DATA_PDO 'PPcS'
86 struct _MEDIA_CHANGE_DETECTION_INFO
{
89 // Mutex to synchronize enable/disable requests and media state changes
92 KMUTEX MediaChangeMutex
;
95 // The current state of the media (present, not present, unknown)
96 // protected by MediaChangeSynchronizationEvent
99 MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState
;
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
108 LONG MediaChangeDetectionDisableCount
;
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.
118 LONG MediaChangeCountDown
;
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
127 LONG MediaChangeRetryCount
;
130 // use GESN if it's available
135 BOOLEAN HackEventMask
;
137 UCHAR NoChangeEventMask
;
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
152 LONG MediaChangeIrpInUse
;
155 // Pointer to the irp to be used for media change detection.
156 // protected by Interlocked MediaChangeIrpInUse
162 // The srb for the media change detection.
163 // protected by Interlocked MediaChangeIrpInUse
166 SCSI_REQUEST_BLOCK MediaChangeSrb
;
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.
178 LONG MediaChangeIrpTimeInUse
;
181 // Set by CdRomTickHandler when we determine that the media change irp has
185 BOOLEAN MediaChangeIrpLost
;
193 } MEDIA_LOCK_TYPE
, *PMEDIA_LOCK_TYPE
;
195 typedef struct _FAILURE_PREDICTION_INFO
{
196 FAILURE_PREDICTION_METHOD Method
;
197 ULONG CountDown
; // Countdown timer
198 ULONG Period
; // Countdown period
200 PIO_WORKITEM WorkQueueItem
;
203 } FAILURE_PREDICTION_INFO
, *PFAILURE_PREDICTION_INFO
;
208 // This struct must always fit within four PVOIDs of info,
209 // as it uses the irp's "PVOID DriverContext[4]" to store
212 typedef struct _CLASS_RETRY_INFO
{
213 struct _CLASS_RETRY_INFO
*Next
;
214 } CLASS_RETRY_INFO
, *PCLASS_RETRY_INFO
;
218 typedef struct _CSCAN_LIST
{
221 // The current block which has an outstanding request.
224 ULONGLONG BlockNumber
;
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.
231 LIST_ENTRY CurrentSweep
;
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
240 LIST_ENTRY NextSweep
;
242 } CSCAN_LIST
, *PCSCAN_LIST
;
245 // add to the front of this structure to help prevent illegal
246 // snooping by other utilities.
251 typedef enum _CLASS_DETECTION_STATE
{
252 ClassDetectionUnknown
= 0,
253 ClassDetectionUnsupported
= 1,
254 ClassDetectionSupported
= 2
255 } CLASS_DETECTION_STATE
, *PCLASS_DETECTION_STATE
;
258 typedef struct _CLASS_ERROR_LOG_DATA
{
259 LARGE_INTEGER TickCount
; // Offset 0x00
260 ULONG PortNumber
; // Offset 0x08
262 UCHAR ErrorPaging
: 1; // Offset 0x0c
263 UCHAR ErrorRetried
: 1;
264 UCHAR ErrorUnhandled
: 1;
265 UCHAR ErrorReserved
: 5;
269 SCSI_REQUEST_BLOCK Srb
; // Offset 0x10
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.
277 SENSE_DATA SenseData
; // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
278 } CLASS_ERROR_LOG_DATA
, *PCLASS_ERROR_LOG_DATA
;
280 #define NUM_ERROR_LOG_ENTRIES 16
284 typedef struct _TRANSFER_PACKET
{
286 LIST_ENTRY AllPktsListEntry
; // entry in fdoData's static AllTransferPacketsList
287 SINGLE_LIST_ENTRY SlistEntry
; // for when in free list (use fast slist)
293 * This is the client IRP that this TRANSFER_PACKET is currently
297 BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
;
300 * Stuff for retrying the transfer.
305 ULONG RetryIntervalSec
;
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.
313 PKEVENT SyncEventPtr
;
316 * Stuff for retrying during extreme low-memory stress
317 * (when we retry 1 page at a time).
319 BOOLEAN InLowMemRetry
;
320 PUCHAR LowMemRetry_remainingBufPtr
;
321 ULONG LowMemRetry_remainingBufLen
;
322 LARGE_INTEGER LowMemRetry_nextChunkTargetLocation
;
325 * Fields used for cancelling the packet.
327 // BOOLEAN Cancelled;
328 // KEVENT CancelledEvent;
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.
339 LARGE_INTEGER TargetLocationCopy
;
342 * This is a standard SCSI structure that receives a detailed
343 * report about a SCSI error on the hardware.
345 SENSE_DATA SrbErrorSenseData
;
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.
353 SCSI_REQUEST_BLOCK Srb
;
354 // ULONG SrbIoctlDevObj; // not handling ioctls yet
355 // ULONG SrbIoctlCode;
357 } TRANSFER_PACKET
, *PTRANSFER_PACKET
;
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.
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.
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
384 // add to the front of this structure to help prevent illegal
385 // snooping by other utilities.
387 struct _CLASS_PRIVATE_FDO_DATA
{
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. :(
396 ULONG OriginalSrbFlags
;
398 ULONG ReEnableThreshhold
; // 0 means never
403 STORAGE_HOTPLUG_INFO HotplugInfo
;
405 // Legacy. Still used by obsolete legacy code.
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
416 BOOLEAN TimerStarted
;
417 BOOLEAN LoggedTURFailureSinceLastIO
;
420 // privately allocated release queue irp
421 // protected by fdoExtension->ReleaseQueueSpinLock
423 BOOLEAN ReleaseQueueIrpAllocated
;
424 PIRP ReleaseQueueIrp
;
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).
434 LIST_ENTRY AllTransferPacketsList
;
435 SLIST_HEADER FreeTransferPacketsList
;
436 ULONG NumFreeTransferPackets
;
437 ULONG NumTotalTransferPackets
;
438 ULONG DbgPeakNumTransferPackets
;
441 * Queue for deferred client irps
443 LIST_ENTRY DeferredClientIrpList
;
446 * Precomputed maximum transfer length for the hardware.
451 * SCSI_REQUEST_BLOCK template preconfigured with the constant values.
452 * This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
454 SCSI_REQUEST_BLOCK SrbTemplate
;
459 * Circular array of timestamped logs of errors that occurred on this device.
461 ULONG ErrorLogNextIndex
;
462 CLASS_ERROR_LOG_DATA ErrorLogs
[NUM_ERROR_LOG_ENTRIES
];
467 #define MIN(a, b) ((a) < (b) ? (a) : (b))
468 #define MAX(a, b) ((a) > (b) ? (a) : (b))
471 #define NOT_READY_RETRY_INTERVAL 10
472 #define MINIMUM_RETRY_UNITS ((LONGLONG)32)
476 * Simple singly-linked-list queuing macros, with no synchronization.
478 static inline VOID
SimpleInitSlistHdr(SINGLE_LIST_ENTRY
*SListHdr
)
480 SListHdr
->Next
= NULL
;
482 static inline VOID
SimplePushSlist(SINGLE_LIST_ENTRY
*SListHdr
, SINGLE_LIST_ENTRY
*SListEntry
)
484 SListEntry
->Next
= SListHdr
->Next
;
485 SListHdr
->Next
= SListEntry
;
487 static inline SINGLE_LIST_ENTRY
*SimplePopSlist(SINGLE_LIST_ENTRY
*SListHdr
)
489 SINGLE_LIST_ENTRY
*sListEntry
= SListHdr
->Next
;
491 SListHdr
->Next
= sListEntry
->Next
;
492 sListEntry
->Next
= NULL
;
496 static inline BOOLEAN
SimpleIsSlistEmpty(SINGLE_LIST_ENTRY
*SListHdr
)
498 return (SListHdr
->Next
== NULL
);
501 DRIVER_INITIALIZE DriverEntry
;
503 DRIVER_UNLOAD ClassUnload
;
505 DRIVER_DISPATCH ClassCreateClose
;
510 IN PDEVICE_OBJECT DeviceObject
,
516 ClasspCleanupProtectedLocks(
517 IN PFILE_OBJECT_EXTENSION FsContext
522 ClasspEjectionControl(
523 IN PDEVICE_OBJECT Fdo
,
525 IN MEDIA_LOCK_TYPE LockType
,
529 DRIVER_DISPATCH ClassReadWrite
;
531 DRIVER_DISPATCH ClassDeviceControlDispatch
;
533 DRIVER_DISPATCH ClassDispatchPnp
;
538 IN PDEVICE_OBJECT DeviceObject
544 IN PDEVICE_OBJECT DeviceObject
,
548 DRIVER_DISPATCH ClassSystemControl
;
551 // Class internal routines
554 DRIVER_ADD_DEVICE ClassAddDevice
;
556 IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion
;
561 PDEVICE_OBJECT DeviceObject
,
563 PSCSI_REQUEST_BLOCK Srb
,
571 IN PDEVICE_OBJECT DeviceObject
,
578 ClassPnpQueryFdoRelations(
579 IN PDEVICE_OBJECT Fdo
,
585 ClassRetrieveDeviceRelations(
586 IN PDEVICE_OBJECT Fdo
,
587 IN DEVICE_RELATION_TYPE RelationType
,
588 OUT PDEVICE_RELATIONS
*DeviceRelations
594 IN PDEVICE_OBJECT Pdo
,
595 IN BUS_QUERY_ID_TYPE IdType
,
596 IN PUNICODE_STRING IdString
601 ClassQueryPnpCapabilities(
602 IN PDEVICE_OBJECT PhysicalDeviceObject
,
603 IN PDEVICE_CAPABILITIES Capabilities
606 DRIVER_STARTIO ClasspStartIo
;
610 ClasspPagingNotificationCompletion(
611 IN PDEVICE_OBJECT DeviceObject
,
613 IN PDEVICE_OBJECT RealDeviceObject
618 ClasspMediaChangeCompletion(
619 PDEVICE_OBJECT DeviceObject
,
624 PFILE_OBJECT_EXTENSION
627 IN PCOMMON_DEVICE_EXTENSION CommonExtension
,
628 IN PFILE_OBJECT FileObject
634 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
636 IN PSCSI_REQUEST_BLOCK Srb
641 ClasspRegisterMountedDeviceInterface(
642 IN PDEVICE_OBJECT DeviceObject
648 PDEVICE_OBJECT DeviceObject
654 PDEVICE_OBJECT DeviceObject
658 // routines for dictionary list support
663 InitializeDictionary(
664 IN PDICTIONARY Dictionary
669 TestDictionarySignature(
670 IN PDICTIONARY Dictionary
675 AllocateDictionaryEntry(
676 IN PDICTIONARY Dictionary
,
686 IN PDICTIONARY Dictionary
,
693 IN PDICTIONARY Dictionary
,
700 ClasspAllocateReleaseRequest(
701 IN PDEVICE_OBJECT Fdo
706 ClasspFreeReleaseRequest(
707 IN PDEVICE_OBJECT Fdo
710 IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion
;
715 IN PDEVICE_OBJECT DeviceObject
,
716 IN PIRP ReleaseQueueIrp
721 ClasspDisablePowerNotification(
722 PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
726 // class power routines
729 DRIVER_DISPATCH ClassDispatchPower
;
733 ClassMinimalPowerHandler(
734 IN PDEVICE_OBJECT DeviceObject
,
739 // Child list routines
745 IN PFUNCTIONAL_DEVICE_EXTENSION Parent
,
746 IN PPHYSICAL_DEVICE_EXTENSION Child
,
747 IN BOOLEAN AcquireLock
750 PPHYSICAL_DEVICE_EXTENSION
753 IN PFUNCTIONAL_DEVICE_EXTENSION Parent
,
754 IN PPHYSICAL_DEVICE_EXTENSION Child
,
755 IN BOOLEAN AcquireLock
761 IN PCLASS_PRIVATE_FDO_DATA FdoData
764 KDEFERRED_ROUTINE ClasspRetryRequestDpc
;
769 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
770 IN PSCSI_REQUEST_BLOCK Srb
776 IN PDEVICE_OBJECT SelfDeviceObject
,
778 IN LARGE_INTEGER TimeDelta100ns
// in 100ns units
783 ClasspBuildRequestEx(
784 IN PFUNCTIONAL_DEVICE_EXTENSION Fdo
,
786 IN PSCSI_REQUEST_BLOCK Srb
791 ClasspAllocateReleaseQueueIrp(
792 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
797 ClasspInitializeGesn(
798 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
799 IN PMEDIA_CHANGE_DETECTION_INFO Info
804 ClasspSendNotification(
805 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
806 IN
const GUID
* Guid
,
807 IN ULONG ExtraDataSize
,
813 ClassSendEjectionNotification(
814 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
819 ClasspScanForSpecialInRegistry(
820 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
825 ClasspScanForClassHacks(
826 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
832 ClasspInitializeHotplugInfo(
833 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
838 ClasspPerfIncrementErrorCount(
839 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
843 ClasspPerfIncrementSuccessfulIo(
844 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
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
);
872 #endif /* _CLASSPNP_PCH_ */