1 /*++
2
3 Copyright (C) Microsoft Corporation. All rights reserved.
4
5 Module Name:
6
7 mmc.h
8
9 Abstract:
10
11 Functions/macros for using the scratch buffer and scratch request/SRB
12 in the serial I/O queue context
13
14 Author:
15
16 Environment:
17
18 kernel mode only
19
20 Notes:
21
22
23 Revision History:
24
25 --*/
26
27 #ifndef __SCRATCH_H__
28 #define __SCRATCH_H__
29
30
31 _IRQL_requires_max_(APC_LEVEL)
32 VOID
33 ScratchBuffer_Deallocate(
34 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
35 );
36
37 _IRQL_requires_max_(APC_LEVEL)
38 BOOLEAN
39 ScratchBuffer_Allocate(
40 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
41 );
42
43 VOID
44 ScratchBuffer_ResetItems(
45 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
46 _In_ BOOLEAN ResetRequestHistory
47 );
48
49 _IRQL_requires_max_(APC_LEVEL)
50 VOID
51 ScratchBuffer_SetupSrb(
52 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
53 _In_opt_ WDFREQUEST OriginalRequest,
54 _In_ ULONG MaximumTransferLength,
55 _In_ BOOLEAN GetDataFromDevice
56 );
57
58 VOID
59 ScratchBuffer_SetupReadWriteSrb(
60 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
61 _In_ WDFREQUEST OriginalRequest,
62 _In_ LARGE_INTEGER StartingOffset,
63 _In_ ULONG RequiredLength,
64 _Inout_updates_bytes_(RequiredLength) UCHAR* DataBuffer,
65 _In_ BOOLEAN IsReadRequest,
66 _In_ BOOLEAN UsePartialMdl
67 );
68
69 NTSTATUS
70 ScratchBuffer_SendSrb(
71 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
72 _In_ BOOLEAN SynchronousSrb,
73 _When_(SynchronousSrb, _Pre_null_)
74 _When_(!SynchronousSrb, _In_opt_)
75 PSRB_HISTORY_ITEM *SrbHistoryItem
76 );
77
78 NTSTATUS
79 ScratchBuffer_PerformNextReadWrite(
80 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
81 _In_ BOOLEAN FirstTry
82 );
83
84 #if DBG
85 #define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), __FILE__, __LINE__)
86 #else
87 #define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), NULL, (ULONG)-1)
88 #endif
89
ScratchBuffer_BeginUseX(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_opt_ LPCSTR File,ULONG Line)90 FORCEINLINE VOID ScratchBuffer_BeginUseX(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_opt_ LPCSTR File, ULONG Line)
91 {
92 // NOTE: these are not "real" locks. They are simply to help
93 // avoid multiple uses of the scratch buffer. Thus, it
94 // is not critical to have atomic operations here.
95 PVOID tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), (PVOID)-1, NULL);
96 NT_ASSERT(tmp == NULL);
97 UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning.
98 DeviceExtension->ScratchContext.ScratchInUseFileName = File;
99 DeviceExtension->ScratchContext.ScratchInUseLineNumber = Line;
100 ScratchBuffer_ResetItems(DeviceExtension, TRUE);
101 RequestClearSendTime(DeviceExtension->ScratchContext.ScratchRequest);
102 return;
103 }
ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)104 FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
105 {
106 // NOTE: these are not "real" locks. They are simply to help
107 // avoid multiple uses of the scratch buffer. Thus, it
108 // is not critical to have atomic operations here.
109
110 // On lock release, we erase ScratchInUseFileName and ScratchInUseLineNumber _before_ releasing ScratchInUse,
111 // because otherwise we may erase these after the lock has been acquired again by another thread. We store the
112 // old values of ScratchInUseFileName and ScratchInUseLineNumber in local variables to facilitate debugging,
113 // if the ASSERT at the end of the function is hit.
114 PCSTR scratchInUseFileName;
115 ULONG scratchInUseLineNumber;
116 PVOID tmp;
117
118 scratchInUseFileName = DeviceExtension->ScratchContext.ScratchInUseFileName;
119 scratchInUseLineNumber = DeviceExtension->ScratchContext.ScratchInUseLineNumber;
120 UNREFERENCED_PARAMETER(scratchInUseFileName);
121 UNREFERENCED_PARAMETER(scratchInUseLineNumber);
122 DeviceExtension->ScratchContext.ScratchInUseFileName = NULL;
123 DeviceExtension->ScratchContext.ScratchInUseLineNumber = 0;
124
125 //
126 // If we have used the PartialMdl in the scratch context we should notify MM that we will be reusing it
127 // otherwise it may leak System VA if some one below us has mapped the same.
128 //
129
130 if (DeviceExtension->ScratchContext.PartialMdlIsBuilt != FALSE)
131 {
132 MmPrepareMdlForReuse(DeviceExtension->ScratchContext.PartialMdl);
133 DeviceExtension->ScratchContext.PartialMdlIsBuilt = FALSE;
134 }
135
136 tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), NULL, (PVOID)-1);
137 NT_ASSERT(tmp == ((PVOID)-1));
138 UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning.
139 return;
140 }
141
142 VOID
143 CompressSrbHistoryData(
144 _Inout_ PSRB_HISTORY RequestHistory
145 );
146
147 VOID
148 ValidateSrbHistoryDataPresumptions(
149 _In_ SRB_HISTORY const* RequestHistory
150 );
151
152 _IRQL_requires_max_(APC_LEVEL)
153 NTSTATUS
154 ScratchBuffer_ExecuteCdbEx(
155 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
156 _In_opt_ WDFREQUEST OriginalRequest,
157 _In_ ULONG TransferSize,
158 _In_ BOOLEAN GetDataFromDevice,
159 _In_ PCDB Cdb,
160 _In_ UCHAR OprationLength,
161 _In_ ULONG TimeoutValue
162 );
163
_IRQL_requires_max_(APC_LEVEL)164 _IRQL_requires_max_(APC_LEVEL)
165 FORCEINLINE // __REACTOS__
166 NTSTATUS
167 ScratchBuffer_ExecuteCdb(
168 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
169 _In_opt_ WDFREQUEST OriginalRequest,
170 _In_ ULONG TransferSize,
171 _In_ BOOLEAN GetDataFromDevice,
172 _In_ PCDB Cdb,
173 _In_ UCHAR OprationLength
174 )
175 {
176 return ScratchBuffer_ExecuteCdbEx(DeviceExtension,
177 OriginalRequest,
178 TransferSize,
179 GetDataFromDevice,
180 Cdb,
181 OprationLength,
182 0);
183 }
184
185 KDEFERRED_ROUTINE ScratchBuffer_ReadWriteTimerRoutine;
186
187 #endif //__SCRATCH_H__
188