reactos/drivers/storage/class/cdrom/cdromp.h

383 lines
15 KiB
C

/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
cdromp.h
Abstract:
Private header file for cdrom.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:
--*/
#ifndef __CDROMP_H__
#define __CDROMP_H__
#include <scsi.h>
#include <storduid.h>
#include <mountdev.h>
#include <ioevent.h>
#include <ntintsafe.h>
/*
* IA64 requires 8-byte alignment for pointers, but the IA64 NT kernel expects 16-byte alignment
*/
#ifdef _WIN64
#define PTRALIGN DECLSPEC_ALIGN(16)
#else
#define PTRALIGN
#endif
// NOTE: Start with a smaller 100 second maximum, due to current assert in CLASSPNP
// 0x0000 00C9'2A69 C000 (864,000,000,000) is 24 hours in 100ns units
// 0x0000 0000'3B9A CA00 ( 1,000,000,000) is 100 seconds in 100ns units
#define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS (0x3B9ACA00)
// structures to simplify matching devices, ids, and hacks required for
// these ids.
typedef struct _CDROM_SCAN_FOR_SPECIAL_INFO {
//
// * NULL pointers indicates that no match is required.
// * empty string will only match an empty string. non-existant strings
// in the device descriptor are considered empty strings for this match.
// (ie. "" will only match "")
// * all other strings will do partial matches, based upon
// string provided (ie. "hi" will match "hitazen" and "higazui")
// * array must end with all three PCHARs being set to NULL.
//
PCHAR VendorId;
PCHAR ProductId;
PCHAR ProductRevision;
//
// marked as a ULONG_PTR to allow use as either a ptr to a data block
// or 32 bits worth of flags. (64 bits on 64 bit systems) no longer a
// const so that it may be dynamically built.
//
ULONG_PTR Data;
} CDROM_SCAN_FOR_SPECIAL_INFO, *PCDROM_SCAN_FOR_SPECIAL_INFO;
// Define the various states that media can be in for autorun.
typedef enum _MEDIA_CHANGE_DETECTION_STATE {
MediaUnknown,
MediaPresent,
MediaNotPresent,
MediaUnavailable // e.g. cd-r media undergoing burn
} MEDIA_CHANGE_DETECTION_STATE, *PMEDIA_CHANGE_DETECTION_STATE;
/*++////////////////////////////////////////////////////////////////////////////
This structure defines the history kept for a given transfer packet.
It includes a srb status/sense data structure that is always either valid
or zero-filled for the full 18 bytes, time sent/completed, and how long
the retry delay was requested to be.
--*/
typedef struct _SRB_HISTORY_ITEM {
LARGE_INTEGER TickCountSent; // 0x00..0x07
LARGE_INTEGER TickCountCompleted; // 0x08..0x0F
ULONG MillisecondsDelayOnRetry; // 0x10..0x13
SENSE_DATA NormalizedSenseData; // 0x14..0x25 (0x12 bytes)
UCHAR SrbStatus; // 0x26
UCHAR ClassDriverUse; // 0x27 -- one byte free (alignment)
} SRB_HISTORY_ITEM, *PSRB_HISTORY_ITEM;
typedef struct _SRB_HISTORY {
ULONG_PTR ClassDriverUse[4]; // for the class driver to use as they please
_Field_range_(1,30000)
ULONG TotalHistoryCount;
_Field_range_(0,TotalHistoryCount)
ULONG UsedHistoryCount;
_Field_size_part_(TotalHistoryCount, UsedHistoryCount)
SRB_HISTORY_ITEM History[1];
} SRB_HISTORY, *PSRB_HISTORY;
extern CDROM_SCAN_FOR_SPECIAL_INFO CdRomBadItems[];
/*++////////////////////////////////////////////////////////////////////////////*/
// legacy registry key and values.
#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 WINPE_REG_KEY_NAME (L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\MiniNT")
#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_RESERVE6 (0x00000008)
#define FDO_HACK_GESN_IGNORE_OPCHANGE (0x00000010)
#define FDO_HACK_NO_STREAMING (0x00000020)
#define FDO_HACK_NO_ASYNCHRONOUS_NOTIFICATION (0x00000040)
#define FDO_HACK_VALID_FLAGS (0x0000007F)
#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
/*
* We retry failed I/O requests at 1-second intervals.
* In the case of a failure due to bus reset, we want to make sure that we retry after the allowable
* reset time. For SCSI, the allowable reset time is 5 seconds. ScsiPort queues requests during
* a bus reset, which should cause us to retry after the reset is over; but the requests queued in
* the miniport are failed all the way back to us immediately. In any event, in order to make
* extra sure that our retries span the allowable reset time, we should retry more than 5 times.
*/
//#define NUM_IO_RETRIES 8
#define CDROM_VOLUME_VERIFY_CHECKED 0x34
#define CDROM_TAG_PRIVATE_DATA 'CPcS'
typedef struct _MEDIA_CHANGE_DETECTION_INFO {
// Use AN if supported so that we don't need to poll for media change notifications.
BOOLEAN AsynchronousNotificationSupported;
// If AN is turned on and we received an AN signal when the device is exclusively locked,
// we should take a note and send down a GESN when the lock is lifted, since otherwise
// we will lose the signal. Even worse, some ODD models will signal the event again next
// time a SYNC CACHE is sent down, and processing the event in that arbitrary timing may
// cause unexpected behaviors.
BOOLEAN ANSignalPendingDueToExclusiveLock;
// Mutex to synchronize enable/disable requests and media state changes
KMUTEX MediaChangeMutex;
// For request erialization use.
// This irp is used in timer callback routine, will be sent to the device itself.
// so that the sequentail queue will get request wrapped on this irp. After doing
// the real work, this irp will be completed to indicate it's ok to send the next
// MCN request.
PIRP MediaChangeSyncIrp;
// The last known state of the media (present, not present, unknown).
// Protected by MediaChangeMutex.
MEDIA_CHANGE_DETECTION_STATE LastKnownMediaDetectionState;
// The last state of the media (present, not present, unknown) reported to apps
// via notifications. Protected by MediaChangeMutex
MEDIA_CHANGE_DETECTION_STATE LastReportedMediaDetectionState;
// 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;
// recent changes allowed instant retries of the MCN REQUEST. 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 REQUEST is currently in use.
// If this value is zero, then the REQUEST 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
//
// This protect is needed in the polling case since the timer is fired asynchronous
// to our sequential I/O queues, and when the timer is fired, our Sync Irp could be
// still using the MediaChangeRequest. However, if AN is used, then each interrupt
// will cause us to queue a request, so interrupts are serialized, and within the
// handling of each request, we already sequentially use the MediaChangeRequest if
// we need retries. We still use it in case of AN to be consistent with polling, but
// if in the future we remove polling altogether, then we don't need this field anymore.
LONG MediaChangeRequestInUse;
// Pointer to the REQUEST to be used for media change detection.
// protected by Interlocked MediaChangeRequestInUse
WDFREQUEST MediaChangeRequest;
// The srb for the media change detection.
// protected by Interlocked MediaChangeIrpInUse
SCSI_REQUEST_BLOCK MediaChangeSrb;
PUCHAR SenseBuffer;
ULONG SrbFlags;
// Handle to the display state notification registration.
PVOID DisplayStateCallbackHandle;
} MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO;
#define DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS (60 * 1000)
#define DELAY_TIME_TO_ENTER_AOAC_IDLE_POWER_IN_MS (10 * 1000)
#define BECOMING_READY_RETRY_COUNT (15)
#define BECOMING_READY_RETRY_INTERNVAL_IN_100NS (2 * 1000 * 1000)
typedef struct _ZERO_POWER_ODD_INFO {
UCHAR LoadingMechanism; // From Removable Medium Feature Descriptor
UCHAR Load; // From Removable Medium Feature Descriptor
D3COLD_SUPPORT_INTERFACE D3ColdInterface; // D3Cold interface from ACPI
BOOLEAN Reserved; // Reserved
BOOLEAN InZeroPowerState; // Is device currently in Zero Power State
BOOLEAN RetryFirstCommand; // First command after power resume should be retried
BOOLEAN MonitorStartStopUnit; // If 1. drawer 2. soft eject 3. no media 4. Immed=0,
// we will not receive any GESN events, and so we should
// monitor the command to get notified
ULONG BecomingReadyRetryCount; // How many times we should retry for becoming ready
UCHAR SenseKey; // sense code from TUR to check media & tray status
UCHAR AdditionalSenseCode; // sense code from TUR to check media & tray status
UCHAR AdditionalSenseCodeQualifier; // sense code from TUR to check media & tray status
PGET_CONFIGURATION_HEADER GetConfigurationBuffer; // Cached Get Configuration response from device
ULONG GetConfigurationBufferSize; // Size of the above buffer
} ZERO_POWER_ODD_INFO, *PZERO_POWER_ODD_INFO;
typedef enum {
SimpleMediaLock,
SecureMediaLock,
InternalMediaLock
} MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
typedef enum _CDROM_DETECTION_STATE {
CdromDetectionUnknown = 0,
CdromDetectionUnsupported = 1,
CdromDetectionSupported = 2
} CDROM_DETECTION_STATE, *PCDROM_DETECTION_STATE;
typedef struct _CDROM_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!)
} CDROM_ERROR_LOG_DATA, *PCDROM_ERROR_LOG_DATA;
#define NUM_ERROR_LOG_ENTRIES 16
//
// add to the front of this structure to help prevent illegal
// snooping by other utilities.
//
typedef struct _CDROM_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;
BOOLEAN TimerStarted;
BOOLEAN LoggedTURFailureSinceLastIO;
BOOLEAN LoggedSYNCFailure;
// not use WDFSPINLOCK to avoid exposing private object creation
// in initialization code. (cdrom.sys was in WDK example)
KSPIN_LOCK SpinLock;
// Circular array of timestamped logs of errors that occurred on this device.
ULONG ErrorLogNextIndex;
CDROM_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
}CDROM_PRIVATE_FDO_DATA, *PCDROM_PRIVATE_FDO_DATA;
//
// this is a private structure, but must be kept here
// to properly compile size of FUNCTIONAL_DEVICE_EXTENSION
//
typedef struct _FILE_OBJECT_CONTEXT {
WDFFILEOBJECT FileObject;
WDFDEVICE DeviceObject;
ULONG LockCount;
ULONG McnDisableCount;
BOOLEAN EnforceStreamingRead;
BOOLEAN EnforceStreamingWrite;
} FILE_OBJECT_CONTEXT, *PFILE_OBJECT_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FILE_OBJECT_CONTEXT, FileObjectGetContext)
#define NOT_READY_RETRY_INTERVAL 10
#define MODE_PAGE_DATA_SIZE 192
//
// per session device
//
#define INVALID_SESSION ((ULONG)-1)
#endif // __CDROMP_H__