xref: /reactos/drivers/storage/class/cdrom/cdromp.h (revision 3088717b)
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