1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxCommonBufferAPI.cpp
8 
9 Abstract:
10 
11     Base for WDF CommonBuffer APIs
12 
13 Environment:
14 
15     Kernel mode only.
16 
17 Notes:
18 
19 
20 Revision History:
21 
22 --*/
23 
24 #include "fxdmapch.hpp"
25 
26 extern "C" {
27 // #include "FxCommonBufferAPI.tmh"
28 }
29 
30 //
31 // Extern "C" the entire file
32 //
33 extern "C" {
34 
35 _Must_inspect_result_
36 __drv_maxIRQL(PASSIVE_LEVEL)
37 NTSTATUS
38 STDCALL
39 WDFEXPORT(WdfCommonBufferCreate)(
40     __in
41     PWDF_DRIVER_GLOBALS DriverGlobals,
42     __in
43     WDFDMAENABLER DmaEnabler,
44     __in
45     __drv_when(Length == 0, __drv_reportError(Length cannot be zero))
46     size_t Length,
47     __in_opt
48     WDF_OBJECT_ATTRIBUTES * Attributes,
49     __out
50     WDFCOMMONBUFFER * CommonBufferHandle
51     )
52 {
53     FxCommonBuffer  * pComBuf;
54     FxDmaEnabler    * pDmaEnabler;
55     NTSTATUS          status;
56     WDFOBJECT         handle;
57     PFX_DRIVER_GLOBALS pFxDriverGlobals;
58 
59     //
60     // Get validate DmaEnabler handle
61     //
62     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
63                                    DmaEnabler,
64                                    FX_TYPE_DMA_ENABLER,
65                                    (PVOID *) &pDmaEnabler,
66                                    &pFxDriverGlobals);
67 
68     FxPointerNotNull(pFxDriverGlobals, CommonBufferHandle);
69 
70     *CommonBufferHandle = NULL;
71 
72     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
73     if (!NT_SUCCESS(status)) {
74         return status;
75     }
76 
77     //
78     // Basic parameter validation
79     //
80     if (Length == 0) {
81         status = STATUS_INVALID_PARAMETER;
82         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
83                             "Length is 0, %!STATUS!", status);
84         return status;
85     }
86 
87     status = FxValidateObjectAttributes(pFxDriverGlobals,
88                                         Attributes,
89                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED
90                                         );
91     if (!NT_SUCCESS(status)) {
92         return status;
93     }
94 
95     //
96     // Create a new CommonBuffer object
97     //
98     pComBuf = new(pFxDriverGlobals, Attributes)
99         FxCommonBuffer(pFxDriverGlobals, pDmaEnabler);
100 
101     if (pComBuf == NULL) {
102         status = STATUS_INSUFFICIENT_RESOURCES;
103 
104         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
105                             "Could not allocate memory for a WDFCOMMONBUFFER, "
106                             "%!STATUS!", status);
107         return status;
108     }
109 
110     //
111     // Assign this FxCommonBuffer to its parent FxDmaEnabler object.
112     //
113     status = pComBuf->Commit(Attributes, (WDFOBJECT*)&handle, pDmaEnabler);
114 
115     if (NT_SUCCESS(status)) {
116         //
117         // Ok: now allocate a CommonBuffer via this DmaEnabler
118         //
119         status = pComBuf->AllocateCommonBuffer( Length );
120     }
121 
122     if (NT_SUCCESS(status)) {
123         //
124         // Only return a valid handle on success.
125         //
126         *CommonBufferHandle = (WDFCOMMONBUFFER) handle;
127     }
128     else {
129         pComBuf->DeleteFromFailedCreate();
130     }
131 
132     return status;
133 }
134 
135 _Must_inspect_result_
136 __drv_maxIRQL(PASSIVE_LEVEL)
137 NTSTATUS
138 STDCALL
139 WDFEXPORT(WdfCommonBufferCreateWithConfig)(
140     __in
141     PWDF_DRIVER_GLOBALS DriverGlobals,
142     __in
143     WDFDMAENABLER DmaEnabler,
144     __in
145     __drv_when(Length == 0, __drv_reportError(Length cannot be zero))
146     size_t Length,
147     __in
148     PWDF_COMMON_BUFFER_CONFIG Config,
149     __in_opt
150     WDF_OBJECT_ATTRIBUTES * Attributes,
151     __out
152     WDFCOMMONBUFFER * CommonBufferHandle
153     )
154 {
155     FxCommonBuffer  * pComBuf;
156     FxDmaEnabler    * pDmaEnabler;
157     NTSTATUS          status;
158     WDFOBJECT         handle;
159     PFX_DRIVER_GLOBALS pFxDriverGlobals;
160 
161     //
162     // Get validate DmaEnabler handle
163     //
164     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
165                                    DmaEnabler,
166                                    FX_TYPE_DMA_ENABLER,
167                                    (PVOID *) &pDmaEnabler,
168                                    &pFxDriverGlobals);
169 
170     //
171     // Basic parameter validation
172     //
173     FxPointerNotNull(pFxDriverGlobals, Config);
174 
175     if (Config->Size != sizeof(WDF_COMMON_BUFFER_CONFIG)) {
176         status = STATUS_INFO_LENGTH_MISMATCH;
177 
178         DoTraceLevelMessage(
179             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
180             "WDF_COMMON_BUFFER_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
181             Config->Size, sizeof(WDF_COMMON_BUFFER_CONFIG), status);
182 
183         return status;
184     }
185 
186     FxPointerNotNull(pFxDriverGlobals, CommonBufferHandle);
187 
188     *CommonBufferHandle = NULL;
189 
190     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
191     if (!NT_SUCCESS(status)) {
192         return status;
193     }
194 
195     if (Length == 0) {
196         status = STATUS_INVALID_PARAMETER;
197         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
198                             "Length is 0, %!STATUS!", status);
199         return status;
200     }
201 
202     status = FxValidateObjectAttributes(pFxDriverGlobals,
203                                         Attributes,
204                                         FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED
205                                         );
206     if (!NT_SUCCESS(status)) {
207         return status;
208     }
209 
210     pComBuf = new(pFxDriverGlobals, Attributes)
211         FxCommonBuffer(pFxDriverGlobals, pDmaEnabler);
212 
213     if (pComBuf == NULL) {
214         status = STATUS_INSUFFICIENT_RESOURCES;
215 
216         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
217                             "Could not allocate memory for a WDFCOMMONBUFFER, "
218                             "%!STATUS!", status);
219         return status;
220     }
221 
222     //
223     // Assign this FxCommonBuffer to its parent FxDmaEnabler object.
224     //
225     status = pComBuf->Commit(Attributes, (WDFOBJECT*)&handle, pDmaEnabler);
226 
227     if (NT_SUCCESS(status)) {
228         //
229         // Set the alignment value before calling AllocateCommonBuffer.
230         //
231         pComBuf->SetAlignment(Config->AlignmentRequirement);
232         status = pComBuf->AllocateCommonBuffer( Length );
233     }
234 
235     if (NT_SUCCESS(status)) {
236         //
237         // Only return a valid handle on success.
238         //
239         *CommonBufferHandle = (WDFCOMMONBUFFER) handle;
240     }
241     else {
242         pComBuf->DeleteFromFailedCreate();
243     }
244 
245     return status;
246 }
247 
248 __drv_maxIRQL(DISPATCH_LEVEL)
249 PVOID
250 STDCALL
251 WDFEXPORT(WdfCommonBufferGetAlignedVirtualAddress)(
252     __in
253     PWDF_DRIVER_GLOBALS DriverGlobals,
254     __in
255     WDFCOMMONBUFFER CommonBuffer
256     )
257 {
258     FxCommonBuffer  * pComBuf;
259 
260     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
261                          CommonBuffer,
262                          FX_TYPE_COMMON_BUFFER,
263                          (PVOID *) &pComBuf);
264 
265     return pComBuf->GetAlignedVirtualAddress();
266 }
267 
268 __drv_maxIRQL(DISPATCH_LEVEL)
269 PHYSICAL_ADDRESS
270 STDCALL
271 WDFEXPORT(WdfCommonBufferGetAlignedLogicalAddress)(
272     __in
273     PWDF_DRIVER_GLOBALS DriverGlobals,
274     __in
275     WDFCOMMONBUFFER CommonBuffer
276     )
277 {
278     FxCommonBuffer  * pComBuf;
279 
280     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
281                          CommonBuffer,
282                          FX_TYPE_COMMON_BUFFER,
283                          (PVOID *) &pComBuf);
284 
285     return pComBuf->GetAlignedLogicalAddress();
286 }
287 
288 __drv_maxIRQL(DISPATCH_LEVEL)
289 size_t
290 STDCALL
291 WDFEXPORT(WdfCommonBufferGetLength)(
292     __in
293     PWDF_DRIVER_GLOBALS DriverGlobals,
294     __in
295     WDFCOMMONBUFFER CommonBuffer
296     )
297 {
298     FxCommonBuffer  * pComBuf;
299 
300     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
301                          CommonBuffer,
302                          FX_TYPE_COMMON_BUFFER,
303                          (PVOID *) &pComBuf);
304 
305     return pComBuf->GetLength();
306 }
307 
308 } // extern "C"
309