windows-nt/Source/XPSP1/NT/drivers/storage/classpnp/classp.h
2020-09-26 16:20:57 +08:00

906 lines
22 KiB
C

/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
classp.h
Abstract:
Private header file for classpnp.sys modules. This contains private
structure and function declarations as well as constant values which do
not need to be exported.
Author:
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include <stddef.h>
#include <stdarg.h>
#include <ntddk.h>
#include <scsi.h>
#include <wmidata.h>
#include <classpnp.h>
#if CLASS_INIT_GUID
#include <initguid.h>
#endif
#include <mountdev.h>
#include <ioevent.h>
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[];
extern GUID ClassGuidQueryRegInfoEx;
#define CLASSP_REG_SUBKEY_NAME (L"Classpnp")
#define CLASSP_REG_HACK_VALUE_NAME (L"HackMask")
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME (L"MMCDetectionState")
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME (L"WriteCacheEnableOverride")
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME (L"RestorePerfAtCount")
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME (L"UserRemovalPolicy")
#define CLASS_PERF_RESTORE_MINIMUM (0x10)
#define CLASS_ERROR_LEVEL_1 (0x4)
#define CLASS_ERROR_LEVEL_2 (0x8)
#define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
#define FDO_HACK_GESN_IS_BAD (0x00000002)
#define FDO_HACK_NO_SYNC_CACHE (0x00000004)
#define FDO_HACK_VALID_FLAGS (0x00000007)
#define FDO_HACK_INVALID_FLAGS (~FDO_HACK_VALID_FLAGS)
/*
* Lots of retries of synchronized SCSI commands that devices may not
* even support really slows down the system (especially while booting).
* (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
* If a disk cannot return a small initialization buffer at startup
* in two attempts (with delay interval) then we cannot expect it to return
* data consistently with four retries.
* So don't set the retry counts as high here as for data SRBs.
*
* If we find that these requests are failing consecutively,
* despite the retry interval, on otherwise reliable media,
* then we should either increase the retry interval for
* that failure or (by all means) increase these retry counts as appropriate.
*/
#define NUM_LOCKMEDIAREMOVAL_RETRIES 1
#define NUM_MODESENSE_RETRIES 1
#define NUM_DRIVECAPACITY_RETRIES 1
#define CLASS_FILE_OBJECT_EXTENSION_KEY 'eteP'
#define CLASSP_VOLUME_VERIFY_CHECKED 0x34
#define CLASS_TAG_PRIVATE_DATA 'CPcS'
#define CLASS_TAG_PRIVATE_DATA_FDO 'FPcS'
#define CLASS_TAG_PRIVATE_DATA_PDO 'PPcS'
typedef struct _MEDIA_CHANGE_DETECTION_INFO {
//
// Mutex to synchronize enable/disable requests and media state changes
//
KMUTEX MediaChangeMutex;
//
// The current state of the media (present, not present, unknown)
// protected by MediaChangeSynchronizationEvent
//
MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState;
//
// This is a count of how many time MCD has been disabled. if it is
// set to zero, then we'll poll the device for MCN events with the
// then-current method (ie. TEST UNIT READY or GESN). this is
// protected by MediaChangeMutex
//
LONG MediaChangeDetectionDisableCount;
//
// The timer value to support media change events. This is a countdown
// value used to determine when to poll the device for a media change.
// The max value for the timer is 255 seconds. This is not protected
// by an event -- simply InterlockedExchanged() as needed.
//
LONG MediaChangeCountDown;
//
// recent changes allowed instant retries of the MCN irp. Since this
// could cause an infinite loop, keep a count of how many times we've
// retried immediately so that we can catch if the count exceeds an
// arbitrary limit.
//
LONG MediaChangeRetryCount;
//
// use GESN if it's available
//
struct {
BOOLEAN Supported;
BOOLEAN HackEventMask;
UCHAR EventMask;
UCHAR NoChangeEventMask;
PUCHAR Buffer;
PMDL Mdl;
ULONG BufferSize;
} Gesn;
//
// If this value is one, then the irp is currently in use.
// If this value is zero, then the irp is available.
// Use InterlockedCompareExchange() to set from "available" to "in use".
// ASSERT that InterlockedCompareExchange() showed previous value of
// "in use" when changing back to "available" state.
// This also implicitly protects the MediaChangeSrb and SenseBuffer
//
LONG MediaChangeIrpInUse;
//
// Pointer to the irp to be used for media change detection.
// protected by Interlocked MediaChangeIrpInUse
//
PIRP MediaChangeIrp;
//
// The srb for the media change detection.
// protected by Interlocked MediaChangeIrpInUse
//
SCSI_REQUEST_BLOCK MediaChangeSrb;
PUCHAR SenseBuffer;
ULONG SrbFlags;
//
// Second timer to keep track of how long the media change IRP has been
// in use. If this value exceeds the timeout (#defined) then we should
// print out a message to the user and set the MediaChangeIrpLost flag
// protected by using Interlocked() operations in ClasspSendMediaStateIrp,
// the only routine which should modify this value.
//
LONG MediaChangeIrpTimeInUse;
//
// Set by CdRomTickHandler when we determine that the media change irp has
// been lost
//
BOOLEAN MediaChangeIrpLost;
};
typedef enum {
SimpleMediaLock,
SecureMediaLock,
InternalMediaLock
} MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
typedef struct _FAILURE_PREDICTION_INFO {
FAILURE_PREDICTION_METHOD Method;
ULONG CountDown; // Countdown timer
ULONG Period; // Countdown period
PIO_WORKITEM WorkQueueItem;
KEVENT Event;
} FAILURE_PREDICTION_INFO, *PFAILURE_PREDICTION_INFO;
//
// This struct must always fit within four PVOIDs of info,
// as it uses the irp's "PVOID DriverContext[4]" to store
// this info
//
typedef struct _CLASS_RETRY_INFO {
struct _CLASS_RETRY_INFO *Next;
} CLASS_RETRY_INFO, *PCLASS_RETRY_INFO;
typedef struct _CSCAN_LIST {
//
// The current block which has an outstanding request.
//
ULONGLONG BlockNumber;
//
// The list of blocks past the CurrentBlock to which we're going to do
// i/o. This list is maintained in sorted order.
//
LIST_ENTRY CurrentSweep;
//
// The list of blocks behind the current block for which we'll have to
// wait until the next scan across the disk. This is kept as a stack,
// the cost of sorting it is taken when it's moved over to be the
// running list.
//
LIST_ENTRY NextSweep;
} CSCAN_LIST, *PCSCAN_LIST;
//
// add to the front of this structure to help prevent illegal
// snooping by other utilities.
//
typedef enum _CLASS_DETECTION_STATE {
ClassDetectionUnknown = 0,
ClassDetectionUnsupported = 1,
ClassDetectionSupported = 2
} CLASS_DETECTION_STATE, *PCLASS_DETECTION_STATE;
typedef struct _CLASS_ERROR_LOG_DATA {
LARGE_INTEGER TickCount; // Offset 0x00
ULONG PortNumber; // Offset 0x08
UCHAR ErrorPaging : 1; // Offset 0x0c
UCHAR ErrorRetried : 1;
UCHAR ErrorUnhandled : 1;
UCHAR ErrorReserved : 5;
UCHAR Reserved[3];
SCSI_REQUEST_BLOCK Srb; // Offset 0x10
/*
* We define the SenseData as the default length.
* Since the sense data returned by the port driver may be longer,
* SenseData must be at the end of this structure.
* For our internal error log, we only log the default length.
*/
SENSE_DATA SenseData; // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
} CLASS_ERROR_LOG_DATA, *PCLASS_ERROR_LOG_DATA;
#define NUM_ERROR_LOG_ENTRIES 16
typedef struct _TRANSFER_PACKET {
LIST_ENTRY AllPktsListEntry; // entry in fdoData's static AllTransferPacketsList
SINGLE_LIST_ENTRY SlistEntry; // for when in free list (use fast slist)
PIRP Irp;
PDEVICE_OBJECT Fdo;
/*
* This is the client IRP that this TRANSFER_PACKET is currently
* servicing.
*/
PIRP OriginalIrp;
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes;
/*
* Stuff for retrying the transfer.
*/
ULONG NumRetries;
KTIMER RetryTimer;
KDPC RetryTimerDPC;
ULONG RetryIntervalSec;
/*
* Event for synchronizing the transfer (optional).
* (Note that we can't have the event in the packet itself because
* by the time a thread waits on an event the packet may have
* been completed and re-issued.
*/
PKEVENT SyncEventPtr;
/*
* Stuff for retrying during extreme low-memory stress
* (when we retry 1 page at a time).
*/
BOOLEAN InLowMemRetry;
PUCHAR LowMemRetry_remainingBufPtr;
ULONG LowMemRetry_remainingBufLen;
LARGE_INTEGER LowMemRetry_nextChunkTargetLocation;
/*
* Fields used for cancelling the packet.
*/
// BOOLEAN Cancelled;
// KEVENT CancelledEvent;
/*
* We keep the buffer and length values here as well
* as in the SRB because some miniports return
* the transferred length in SRB.DataTransferLength,
* and if the SRB failed we need that value again for the retry.
* We don't trust the lower stack to preserve any of these values in the SRB.
*/
PUCHAR BufPtrCopy;
ULONG BufLenCopy;
LARGE_INTEGER TargetLocationCopy;
/*
* This is a standard SCSI structure that receives a detailed
* report about a SCSI error on the hardware.
*/
SENSE_DATA SrbErrorSenseData;
/*
* This is the SRB block for this TRANSFER_PACKET.
* For IOCTLs, the SRB block includes two DWORDs for
* device object and ioctl code; so these must
* immediately follow the SRB block.
*/
SCSI_REQUEST_BLOCK Srb;
// ULONG SrbIoctlDevObj; // not handling ioctls yet
// ULONG SrbIoctlCode;
} TRANSFER_PACKET, *PTRANSFER_PACKET;
/*
* MIN_INITIAL_TRANSFER_PACKETS is the minimum number of packets that
* we preallocate at startup for each device (we need at least one packet
* to guarantee forward progress during memory stress).
* MIN_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
* we allow to build up and remain for each device;
* we _lazily_ work down to this number when they're not needed.
* MAX_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
* that we _immediately_ reduce to when they are not needed.
*
* The absolute maximum number of packets that we will allocate is
* whatever is required by the current activity, up to the memory limit;
* as soon as stress ends, we snap down to MAX_WORKINGSET_TRANSFER_PACKETS;
* we then lazily work down to MIN_WORKINGSET_TRANSFER_PACKETS.
*/
#define MIN_INITIAL_TRANSFER_PACKETS 1
#define MIN_WORKINGSET_TRANSFER_PACKETS_Consumer 4
#define MAX_WORKINGSET_TRANSFER_PACKETS_Consumer 64
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server 64
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server 1024
#define MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise 256
#define MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise 2048
//
// add to the front of this structure to help prevent illegal
// snooping by other utilities.
//
struct _CLASS_PRIVATE_FDO_DATA {
//
// this private structure allows us to
// dynamically re-enable the perf benefits
// lost due to transient error conditions.
// in w2k, a reboot was required. :(
//
struct {
ULONG OriginalSrbFlags;
ULONG SuccessfulIO;
ULONG ReEnableThreshhold; // 0 means never
} Perf;
ULONG_PTR HackFlags;
STORAGE_HOTPLUG_INFO HotplugInfo;
// Legacy. Still used by obsolete legacy code.
struct {
LARGE_INTEGER Delta; // in ticks
LARGE_INTEGER Tick; // when it should fire
PCLASS_RETRY_INFO ListHead; // singly-linked list
ULONG Granularity; // static
KSPIN_LOCK Lock; // protective spin lock
KDPC Dpc; // DPC routine object
KTIMER Timer; // timer to fire DPC
} Retry;
BOOLEAN TimerStarted;
BOOLEAN LoggedTURFailureSinceLastIO;
//
// privately allocated release queue irp
// protected by fdoExtension->ReleaseQueueSpinLock
//
BOOLEAN ReleaseQueueIrpAllocated;
PIRP ReleaseQueueIrp;
/*
* Queues for TRANSFER_PACKETs that contextualize the IRPs and SRBs
* that we send down to the port driver.
* (The free list is an slist so that we can use fast
* interlocked operations on it; but the relatively-static
* AllTransferPacketsList list has to be
* a doubly-linked list since we have to dequeue from the middle).
*/
LIST_ENTRY AllTransferPacketsList;
SLIST_HEADER FreeTransferPacketsList;
ULONG NumFreeTransferPackets;
ULONG NumTotalTransferPackets;
ULONG DbgPeakNumTransferPackets;
/*
* Queue for deferred client irps
*/
LIST_ENTRY DeferredClientIrpList;
/*
* Precomputed maximum transfer length for the hardware.
*/
ULONG HwMaxXferLen;
/*
* SCSI_REQUEST_BLOCK template preconfigured with the constant values.
* This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
*/
SCSI_REQUEST_BLOCK SrbTemplate;
KSPIN_LOCK SpinLock;
/*
* Circular array of timestamped logs of errors that occurred on this device.
*/
ULONG ErrorLogNextIndex;
CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
};
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define NOT_READY_RETRY_INTERVAL 10
#define MINIMUM_RETRY_UNITS ((LONGLONG)32)
/*
* Simple singly-linked-list queuing macros, with no synchronization.
*/
__inline VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
{
SListHdr->Next = NULL;
}
__inline VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
{
SListEntry->Next = SListHdr->Next;
SListHdr->Next = SListEntry;
}
__inline SINGLE_LIST_ENTRY *SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
{
SINGLE_LIST_ENTRY *sListEntry = SListHdr->Next;
if (sListEntry){
SListHdr->Next = sListEntry->Next;
sListEntry->Next = NULL;
}
return sListEntry;
}
__inline BOOLEAN SimpleIsSlistEmpty(SINGLE_LIST_ENTRY *SListHdr)
{
return (SListHdr->Next == NULL);
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
VOID
ClassUnload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
ClassCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ClasspCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
ClasspCleanupProtectedLocks(
IN PFILE_OBJECT_EXTENSION FsContext
);
NTSTATUS
ClasspEjectionControl(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp,
IN MEDIA_LOCK_TYPE LockType,
IN BOOLEAN Lock
);
NTSTATUS
ClassReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ClassDeviceControlDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
);
NTSTATUS
ClassDeviceControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
);
NTSTATUS
ClassDispatchPnp(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
);
NTSTATUS
ClassPnpStartDevice(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
ClassInternalIoControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ClassShutdownFlush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ClassSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
//
// Class internal routines
//
NTSTATUS
ClassAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN OUT PDEVICE_OBJECT PhysicalDeviceObject
);
NTSTATUS
ClasspSendSynchronousCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
RetryRequest(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PSCSI_REQUEST_BLOCK Srb,
BOOLEAN Associated,
ULONG RetryInterval
);
NTSTATUS
ClassIoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
ClassPnpQueryFdoRelations(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp
);
NTSTATUS
ClassRetrieveDeviceRelations(
IN PDEVICE_OBJECT Fdo,
IN DEVICE_RELATION_TYPE RelationType,
OUT PDEVICE_RELATIONS *DeviceRelations
);
NTSTATUS
ClassGetPdoId(
IN PDEVICE_OBJECT Pdo,
IN BUS_QUERY_ID_TYPE IdType,
IN PUNICODE_STRING IdString
);
NTSTATUS
ClassQueryPnpCapabilities(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN PDEVICE_CAPABILITIES Capabilities
);
VOID
ClasspStartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ClasspPagingNotificationCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_OBJECT RealDeviceObject
);
NTSTATUS
ClasspMediaChangeCompletion(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
PFILE_OBJECT_EXTENSION
ClasspGetFsContext(
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
IN PFILE_OBJECT FileObject
);
NTSTATUS
ClasspMcnControl(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN PIRP Irp,
IN PSCSI_REQUEST_BLOCK Srb
);
VOID
ClasspRegisterMountedDeviceInterface(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
ClasspDisableTimer(
PDEVICE_OBJECT DeviceObject
);
NTSTATUS
ClasspEnableTimer(
PDEVICE_OBJECT DeviceObject
);
//
// routines for dictionary list support
//
VOID
InitializeDictionary(
IN PDICTIONARY Dictionary
);
BOOLEAN
TestDictionarySignature(
IN PDICTIONARY Dictionary
);
NTSTATUS
AllocateDictionaryEntry(
IN PDICTIONARY Dictionary,
IN ULONGLONG Key,
IN ULONG Size,
IN ULONG Tag,
OUT PVOID *Entry
);
PVOID
GetDictionaryEntry(
IN PDICTIONARY Dictionary,
IN ULONGLONG Key
);
VOID
FreeDictionaryEntry(
IN PDICTIONARY Dictionary,
IN PVOID Entry
);
NTSTATUS
ClasspAllocateReleaseRequest(
IN PDEVICE_OBJECT Fdo
);
VOID
ClasspFreeReleaseRequest(
IN PDEVICE_OBJECT Fdo
);
NTSTATUS
ClassReleaseQueueCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
ClasspReleaseQueue(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP ReleaseQueueIrp
);
VOID
ClasspDisablePowerNotification(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
//
// class power routines
//
NTSTATUS
ClassDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ClassMinimalPowerHandler(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
//
// Child list routines
//
VOID
ClassAddChild(
IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
IN PPHYSICAL_DEVICE_EXTENSION Child,
IN BOOLEAN AcquireLock
);
PPHYSICAL_DEVICE_EXTENSION
ClassRemoveChild(
IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
IN PPHYSICAL_DEVICE_EXTENSION Child,
IN BOOLEAN AcquireLock
);
VOID
ClasspRetryDpcTimer(
IN PCLASS_PRIVATE_FDO_DATA FdoData
);
VOID
ClasspRetryRequestDpc(
IN PKDPC Dpc,
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Arg1,
IN PVOID Arg2
);
VOID
ClassFreeOrReuseSrb(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN PSCSI_REQUEST_BLOCK Srb
);
VOID
ClassRetryRequest(
IN PDEVICE_OBJECT SelfDeviceObject,
IN PIRP Irp,
IN LARGE_INTEGER TimeDelta100ns // in 100ns units
);
VOID
ClasspBuildRequestEx(
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
IN PIRP Irp,
IN PSCSI_REQUEST_BLOCK Srb
);
NTSTATUS
ClasspAllocateReleaseQueueIrp(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
NTSTATUS
ClasspInitializeGesn(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN PMEDIA_CHANGE_DETECTION_INFO Info
);
VOID
ClasspSendNotification(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN const GUID * Guid,
IN ULONG ExtraDataSize,
IN PVOID ExtraData
);
VOID
ClassSendEjectionNotification(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
VOID
ClasspScanForSpecialInRegistry(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
VOID
ClasspScanForClassHacks(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
IN ULONG_PTR Data
);
NTSTATUS
ClasspInitializeHotplugInfo(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
VOID
ClasspPerfIncrementErrorCount(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
VOID
ClasspPerfIncrementSuccessfulIo(
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
);
PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo);
VOID DestroyTransferPacket(PTRANSFER_PACKET Pkt);
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt);
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded);
VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp);
VOID SubmitTransferPacket(PTRANSFER_PACKET Pkt);
NTSTATUS TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context);
VOID ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp);
VOID TransferPacketRetryTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
BOOLEAN InterpretTransferPacketError(PTRANSFER_PACKET Pkt);
BOOLEAN RetryTransferPacket(PTRANSFER_PACKET Pkt);
VOID EnqueueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp);
PIRP DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData);
VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation);
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt);
VOID SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp);
VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, PIRP OriginalIrp);
VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp);
PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen);
VOID FreeDeviceInputMdl(PMDL Mdl);
NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo);
VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo);