1 /*++ 2 3 Copyright (C) Microsoft Corporation. All rights reserved. 4 5 Module Name: 6 7 cdromp.h 8 9 Abstract: 10 11 Private header file for cdrom.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 __CDROMP_H__ 29 #define __CDROMP_H__ 30 31 32 #include <scsi.h> 33 #include <storduid.h> 34 #include <mountdev.h> 35 #include <ioevent.h> 36 #include <ntintsafe.h> 37 38 /* 39 * IA64 requires 8-byte alignment for pointers, but the IA64 NT kernel expects 16-byte alignment 40 */ 41 #ifdef _WIN64 42 #define PTRALIGN DECLSPEC_ALIGN(16) 43 #else 44 #define PTRALIGN 45 #endif 46 47 // NOTE: Start with a smaller 100 second maximum, due to current assert in CLASSPNP 48 // 0x0000 00C9'2A69 C000 (864,000,000,000) is 24 hours in 100ns units 49 // 0x0000 0000'3B9A CA00 ( 1,000,000,000) is 100 seconds in 100ns units 50 #define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS (0x3B9ACA00) 51 52 // structures to simplify matching devices, ids, and hacks required for 53 // these ids. 54 typedef struct _CDROM_SCAN_FOR_SPECIAL_INFO { 55 // 56 // * NULL pointers indicates that no match is required. 57 // * empty string will only match an empty string. non-existant strings 58 // in the device descriptor are considered empty strings for this match. 59 // (ie. "" will only match "") 60 // * all other strings will do partial matches, based upon 61 // string provided (ie. "hi" will match "hitazen" and "higazui") 62 // * array must end with all three PCHARs being set to NULL. 63 // 64 65 PCHAR VendorId; 66 PCHAR ProductId; 67 PCHAR ProductRevision; 68 69 // 70 // marked as a ULONG_PTR to allow use as either a ptr to a data block 71 // or 32 bits worth of flags. (64 bits on 64 bit systems) no longer a 72 // const so that it may be dynamically built. 73 // 74 75 ULONG_PTR Data; 76 77 } CDROM_SCAN_FOR_SPECIAL_INFO, *PCDROM_SCAN_FOR_SPECIAL_INFO; 78 79 // Define the various states that media can be in for autorun. 80 typedef enum _MEDIA_CHANGE_DETECTION_STATE { 81 MediaUnknown, 82 MediaPresent, 83 MediaNotPresent, 84 MediaUnavailable // e.g. cd-r media undergoing burn 85 } MEDIA_CHANGE_DETECTION_STATE, *PMEDIA_CHANGE_DETECTION_STATE; 86 87 88 /*++//////////////////////////////////////////////////////////////////////////// 89 90 This structure defines the history kept for a given transfer packet. 91 It includes a srb status/sense data structure that is always either valid 92 or zero-filled for the full 18 bytes, time sent/completed, and how long 93 the retry delay was requested to be. 94 95 --*/ 96 typedef struct _SRB_HISTORY_ITEM { 97 LARGE_INTEGER TickCountSent; // 0x00..0x07 98 LARGE_INTEGER TickCountCompleted; // 0x08..0x0F 99 ULONG MillisecondsDelayOnRetry; // 0x10..0x13 100 SENSE_DATA NormalizedSenseData; // 0x14..0x25 (0x12 bytes) 101 UCHAR SrbStatus; // 0x26 102 UCHAR ClassDriverUse; // 0x27 -- one byte free (alignment) 103 } SRB_HISTORY_ITEM, *PSRB_HISTORY_ITEM; 104 105 typedef struct _SRB_HISTORY { 106 ULONG_PTR ClassDriverUse[4]; // for the class driver to use as they please 107 _Field_range_(1,30000) 108 ULONG TotalHistoryCount; 109 _Field_range_(0,TotalHistoryCount) 110 ULONG UsedHistoryCount; 111 _Field_size_part_(TotalHistoryCount, UsedHistoryCount) 112 SRB_HISTORY_ITEM History[1]; 113 } SRB_HISTORY, *PSRB_HISTORY; 114 115 extern CDROM_SCAN_FOR_SPECIAL_INFO CdRomBadItems[]; 116 117 /*++////////////////////////////////////////////////////////////////////////////*/ 118 119 // legacy registry key and values. 120 #define CLASSP_REG_SUBKEY_NAME (L"Classpnp") 121 122 #define CLASSP_REG_HACK_VALUE_NAME (L"HackMask") 123 #define CLASSP_REG_MMC_DETECTION_VALUE_NAME (L"MMCDetectionState") 124 #define CLASSP_REG_WRITE_CACHE_VALUE_NAME (L"WriteCacheEnableOverride") 125 #define CLASSP_REG_PERF_RESTORE_VALUE_NAME (L"RestorePerfAtCount") 126 #define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME (L"UserRemovalPolicy") 127 #define WINPE_REG_KEY_NAME (L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\MiniNT") 128 129 #define CLASS_PERF_RESTORE_MINIMUM (0x10) 130 #define CLASS_ERROR_LEVEL_1 (0x4) 131 #define CLASS_ERROR_LEVEL_2 (0x8) 132 133 #define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001) 134 #define FDO_HACK_GESN_IS_BAD (0x00000002) 135 #define FDO_HACK_NO_RESERVE6 (0x00000008) 136 #define FDO_HACK_GESN_IGNORE_OPCHANGE (0x00000010) 137 #define FDO_HACK_NO_STREAMING (0x00000020) 138 #define FDO_HACK_NO_ASYNCHRONOUS_NOTIFICATION (0x00000040) 139 140 #define FDO_HACK_VALID_FLAGS (0x0000007F) 141 #define FDO_HACK_INVALID_FLAGS (~FDO_HACK_VALID_FLAGS) 142 143 /* 144 * Lots of retries of synchronized SCSI commands that devices may not 145 * even support really slows down the system (especially while booting). 146 * (Even GetDriveCapacity may be failed on purpose if an external disk is powered off). 147 * If a disk cannot return a small initialization buffer at startup 148 * in two attempts (with delay interval) then we cannot expect it to return 149 * data consistently with four retries. 150 * So don't set the retry counts as high here as for data SRBs. 151 * 152 * If we find that these requests are failing consecutively, 153 * despite the retry interval, on otherwise reliable media, 154 * then we should either increase the retry interval for 155 * that failure or (by all means) increase these retry counts as appropriate. 156 */ 157 //#define NUM_LOCKMEDIAREMOVAL_RETRIES 1 158 //#define NUM_MODESENSE_RETRIES 1 159 //#define NUM_DRIVECAPACITY_RETRIES 1 160 161 /* 162 * We retry failed I/O requests at 1-second intervals. 163 * In the case of a failure due to bus reset, we want to make sure that we retry after the allowable 164 * reset time. For SCSI, the allowable reset time is 5 seconds. ScsiPort queues requests during 165 * a bus reset, which should cause us to retry after the reset is over; but the requests queued in 166 * the miniport are failed all the way back to us immediately. In any event, in order to make 167 * extra sure that our retries span the allowable reset time, we should retry more than 5 times. 168 */ 169 //#define NUM_IO_RETRIES 8 170 171 #define CDROM_VOLUME_VERIFY_CHECKED 0x34 172 173 #define CDROM_TAG_PRIVATE_DATA 'CPcS' 174 175 typedef struct _MEDIA_CHANGE_DETECTION_INFO { 176 177 // Use AN if supported so that we don't need to poll for media change notifications. 178 BOOLEAN AsynchronousNotificationSupported; 179 180 // If AN is turned on and we received an AN signal when the device is exclusively locked, 181 // we should take a note and send down a GESN when the lock is lifted, since otherwise 182 // we will lose the signal. Even worse, some ODD models will signal the event again next 183 // time a SYNC CACHE is sent down, and processing the event in that arbitrary timing may 184 // cause unexpected behaviors. 185 BOOLEAN ANSignalPendingDueToExclusiveLock; 186 187 // Mutex to synchronize enable/disable requests and media state changes 188 KMUTEX MediaChangeMutex; 189 190 // For request erialization use. 191 // This irp is used in timer callback routine, will be sent to the device itself. 192 // so that the sequentail queue will get request wrapped on this irp. After doing 193 // the real work, this irp will be completed to indicate it's ok to send the next 194 // MCN request. 195 PIRP MediaChangeSyncIrp; 196 197 // The last known state of the media (present, not present, unknown). 198 // Protected by MediaChangeMutex. 199 MEDIA_CHANGE_DETECTION_STATE LastKnownMediaDetectionState; 200 201 // The last state of the media (present, not present, unknown) reported to apps 202 // via notifications. Protected by MediaChangeMutex 203 MEDIA_CHANGE_DETECTION_STATE LastReportedMediaDetectionState; 204 205 // This is a count of how many time MCD has been disabled. if it is 206 // set to zero, then we'll poll the device for MCN events with the 207 // then-current method (ie. TEST UNIT READY or GESN). this is 208 // protected by MediaChangeMutex 209 LONG MediaChangeDetectionDisableCount; 210 211 // recent changes allowed instant retries of the MCN REQUEST. Since this 212 // could cause an infinite loop, keep a count of how many times we've 213 // retried immediately so that we can catch if the count exceeds an 214 // arbitrary limit. 215 LONG MediaChangeRetryCount; 216 217 // use GESN if it's available 218 struct { 219 BOOLEAN Supported; 220 BOOLEAN HackEventMask; 221 UCHAR EventMask; 222 UCHAR NoChangeEventMask; 223 PUCHAR Buffer; 224 PMDL Mdl; 225 ULONG BufferSize; 226 } Gesn; 227 228 // If this value is one, then the REQUEST is currently in use. 229 // If this value is zero, then the REQUEST is available. 230 // Use InterlockedCompareExchange() to set from "available" to "in use". 231 // ASSERT that InterlockedCompareExchange() showed previous value of 232 // "in use" when changing back to "available" state. 233 // This also implicitly protects the MediaChangeSrb and SenseBuffer 234 // 235 // This protect is needed in the polling case since the timer is fired asynchronous 236 // to our sequential I/O queues, and when the timer is fired, our Sync Irp could be 237 // still using the MediaChangeRequest. However, if AN is used, then each interrupt 238 // will cause us to queue a request, so interrupts are serialized, and within the 239 // handling of each request, we already sequentially use the MediaChangeRequest if 240 // we need retries. We still use it in case of AN to be consistent with polling, but 241 // if in the future we remove polling altogether, then we don't need this field anymore. 242 LONG MediaChangeRequestInUse; 243 244 // Pointer to the REQUEST to be used for media change detection. 245 // protected by Interlocked MediaChangeRequestInUse 246 WDFREQUEST MediaChangeRequest; 247 248 // The srb for the media change detection. 249 // protected by Interlocked MediaChangeIrpInUse 250 SCSI_REQUEST_BLOCK MediaChangeSrb; 251 PUCHAR SenseBuffer; 252 ULONG SrbFlags; 253 254 // Handle to the display state notification registration. 255 PVOID DisplayStateCallbackHandle; 256 257 } MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO; 258 259 #define DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS (60 * 1000) 260 #define DELAY_TIME_TO_ENTER_AOAC_IDLE_POWER_IN_MS (10 * 1000) 261 #define BECOMING_READY_RETRY_COUNT (15) 262 #define BECOMING_READY_RETRY_INTERNVAL_IN_100NS (2 * 1000 * 1000) 263 264 typedef struct _ZERO_POWER_ODD_INFO { 265 266 UCHAR LoadingMechanism; // From Removable Medium Feature Descriptor 267 UCHAR Load; // From Removable Medium Feature Descriptor 268 269 D3COLD_SUPPORT_INTERFACE D3ColdInterface; // D3Cold interface from ACPI 270 271 BOOLEAN Reserved; // Reserved 272 BOOLEAN InZeroPowerState; // Is device currently in Zero Power State 273 BOOLEAN RetryFirstCommand; // First command after power resume should be retried 274 BOOLEAN MonitorStartStopUnit; // If 1. drawer 2. soft eject 3. no media 4. Immed=0, 275 // we will not receive any GESN events, and so we should 276 // monitor the command to get notified 277 ULONG BecomingReadyRetryCount; // How many times we should retry for becoming ready 278 279 UCHAR SenseKey; // sense code from TUR to check media & tray status 280 UCHAR AdditionalSenseCode; // sense code from TUR to check media & tray status 281 UCHAR AdditionalSenseCodeQualifier; // sense code from TUR to check media & tray status 282 283 PGET_CONFIGURATION_HEADER GetConfigurationBuffer; // Cached Get Configuration response from device 284 ULONG GetConfigurationBufferSize; // Size of the above buffer 285 286 } ZERO_POWER_ODD_INFO, *PZERO_POWER_ODD_INFO; 287 288 typedef enum { 289 SimpleMediaLock, 290 SecureMediaLock, 291 InternalMediaLock 292 } MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE; 293 294 295 typedef enum _CDROM_DETECTION_STATE { 296 CdromDetectionUnknown = 0, 297 CdromDetectionUnsupported = 1, 298 CdromDetectionSupported = 2 299 } CDROM_DETECTION_STATE, *PCDROM_DETECTION_STATE; 300 301 302 typedef struct _CDROM_ERROR_LOG_DATA { 303 LARGE_INTEGER TickCount; // Offset 0x00 304 ULONG PortNumber; // Offset 0x08 305 306 UCHAR ErrorPaging : 1; // Offset 0x0c 307 UCHAR ErrorRetried : 1; 308 UCHAR ErrorUnhandled : 1; 309 UCHAR ErrorReserved : 5; 310 311 UCHAR Reserved[3]; 312 313 SCSI_REQUEST_BLOCK Srb; // Offset 0x10 314 315 // We define the SenseData as the default length. 316 // Since the sense data returned by the port driver may be longer, 317 // SenseData must be at the end of this structure. 318 // For our internal error log, we only log the default length. 319 SENSE_DATA SenseData; // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!) 320 } CDROM_ERROR_LOG_DATA, *PCDROM_ERROR_LOG_DATA; 321 322 323 #define NUM_ERROR_LOG_ENTRIES 16 324 325 // 326 // add to the front of this structure to help prevent illegal 327 // snooping by other utilities. 328 // 329 typedef struct _CDROM_PRIVATE_FDO_DATA { 330 331 // this private structure allows us to 332 // dynamically re-enable the perf benefits 333 // lost due to transient error conditions. 334 // in w2k, a reboot was required. :( 335 struct { 336 ULONG OriginalSrbFlags; 337 ULONG SuccessfulIO; 338 ULONG ReEnableThreshhold; // 0 means never 339 } Perf; 340 341 ULONG_PTR HackFlags; 342 343 STORAGE_HOTPLUG_INFO HotplugInfo; 344 345 BOOLEAN TimerStarted; 346 BOOLEAN LoggedTURFailureSinceLastIO; 347 BOOLEAN LoggedSYNCFailure; 348 349 // not use WDFSPINLOCK to avoid exposing private object creation 350 // in initialization code. (cdrom.sys was in WDK example) 351 KSPIN_LOCK SpinLock; 352 353 // Circular array of timestamped logs of errors that occurred on this device. 354 ULONG ErrorLogNextIndex; 355 CDROM_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES]; 356 357 }CDROM_PRIVATE_FDO_DATA, *PCDROM_PRIVATE_FDO_DATA; 358 359 // 360 // this is a private structure, but must be kept here 361 // to properly compile size of FUNCTIONAL_DEVICE_EXTENSION 362 // 363 typedef struct _FILE_OBJECT_CONTEXT { 364 WDFFILEOBJECT FileObject; 365 WDFDEVICE DeviceObject; 366 ULONG LockCount; 367 ULONG McnDisableCount; 368 BOOLEAN EnforceStreamingRead; 369 BOOLEAN EnforceStreamingWrite; 370 } FILE_OBJECT_CONTEXT, *PFILE_OBJECT_CONTEXT; 371 372 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FILE_OBJECT_CONTEXT, FileObjectGetContext) 373 374 375 #define NOT_READY_RETRY_INTERVAL 10 376 #define MODE_PAGE_DATA_SIZE 192 377 378 // 379 // per session device 380 // 381 #define INVALID_SESSION ((ULONG)-1) 382 383 #endif // __CDROMP_H__ 384