[HNETCFG] Sync with Wine 3.0. CORE-14225
[reactos.git] / win32ss / drivers / videoprt / dma.c
1 /*
2 * PROJECT: ReactOS Videoport
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32ss/drivers/videoprt/dma.c
5 * PURPOSE: Videoport Direct Memory Access Support
6 * PROGRAMMERS: ...
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <videoprt.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 typedef struct
17 {
18 LIST_ENTRY Entry;
19 PDMA_ADAPTER Adapter;
20 ULONG MapRegisters;
21 PVOID HwDeviceExtension;
22
23 }VIP_DMA_ADAPTER, *PVIP_DMA_ADAPTER;
24
25 typedef struct
26 {
27 PVOID HwDeviceExtension;
28 PSCATTER_GATHER_LIST ScatterGatherList;
29 PEXECUTE_DMA ExecuteDmaRoutine;
30 PVOID Context;
31 PVP_DMA_ADAPTER VpDmaAdapter;
32
33 }DMA_START_CONTEXT, *PDMA_START_CONTEXT;
34
35
36 /* PUBLIC FUNCTIONS ***********************************************************/
37
38 /*
39 * @implemented
40 */
41 PVOID
42 NTAPI
43 VideoPortAllocateCommonBuffer(IN PVOID HwDeviceExtension,
44 IN PVP_DMA_ADAPTER VpDmaAdapter,
45 IN ULONG DesiredLength,
46 OUT PPHYSICAL_ADDRESS LogicalAddress,
47 IN BOOLEAN CacheEnabled,
48 PVOID Reserved)
49 {
50 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
51
52 /* check for valid arguments */
53 if (!Adapter || !Adapter->Adapter)
54 {
55 /* invalid parameter */
56 return NULL;
57 }
58
59 /* allocate common buffer */
60 return Adapter->Adapter->DmaOperations->AllocateCommonBuffer(Adapter->Adapter, DesiredLength, LogicalAddress, CacheEnabled);
61 }
62
63 /*
64 * @implemented
65 */
66 VOID
67 NTAPI
68 VideoPortReleaseCommonBuffer(IN PVOID HwDeviceExtension,
69 IN PVP_DMA_ADAPTER VpDmaAdapter,
70 IN ULONG Length,
71 IN PHYSICAL_ADDRESS LogicalAddress,
72 IN PVOID VirtualAddress,
73 IN BOOLEAN CacheEnabled)
74 {
75 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
76
77 /* check for valid arguments */
78 if (!Adapter || !Adapter->Adapter)
79 {
80 /* invalid parameter */
81 return;
82 }
83
84 /* release common buffer */
85 Adapter->Adapter->DmaOperations->FreeCommonBuffer(Adapter->Adapter, Length, LogicalAddress, VirtualAddress, CacheEnabled);
86 }
87
88 /*
89 * @implemented
90 */
91 VOID
92 NTAPI
93 VideoPortPutDmaAdapter(IN PVOID HwDeviceExtension,
94 IN PVP_DMA_ADAPTER VpDmaAdapter)
95 {
96 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
97 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
98
99 /* get hw device extension */
100 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
101
102 /* sanity check */
103 ASSERT(!IsListEmpty(&DeviceExtension->DmaAdapterList));
104
105 /* remove dma adapter from list */
106 RemoveEntryList(&Adapter->Entry);
107
108 /* release dma adapter */
109 Adapter->Adapter->DmaOperations->PutDmaAdapter(Adapter->Adapter);
110
111 /* free memory */
112 ExFreePool(Adapter);
113 }
114
115 /*
116 * @implemented
117 */
118 PVP_DMA_ADAPTER
119 NTAPI
120 VideoPortGetDmaAdapter(IN PVOID HwDeviceExtension,
121 IN PVP_DEVICE_DESCRIPTION VpDeviceExtension)
122 {
123 DEVICE_DESCRIPTION DeviceDescription;
124 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
125 ULONG NumberOfMapRegisters;
126 PVIP_DMA_ADAPTER Adapter;
127 PDMA_ADAPTER DmaAdapter;
128
129 /* allocate private adapter structure */
130 Adapter = ExAllocatePool(NonPagedPool, sizeof(VIP_DMA_ADAPTER));
131 if (!Adapter)
132 {
133 /* failed to allocate adapter structure */
134 return NULL;
135 }
136
137 /* Zero the structure */
138 RtlZeroMemory(&DeviceDescription,
139 sizeof(DEVICE_DESCRIPTION));
140
141 /* Initialize the structure */
142 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
143 DeviceDescription.Master = TRUE;
144 DeviceDescription.DmaWidth = Width8Bits;
145 DeviceDescription.DmaSpeed = Compatible;
146
147 /* Copy data from caller's device extension */
148 DeviceDescription.ScatterGather = VpDeviceExtension->ScatterGather;
149 DeviceDescription.Dma32BitAddresses = VpDeviceExtension->Dma32BitAddresses;
150 DeviceDescription.Dma64BitAddresses = VpDeviceExtension->Dma64BitAddresses;
151 DeviceDescription.MaximumLength = VpDeviceExtension->MaximumLength;
152
153 /* Copy data from the internal device extension */
154 DeviceDescription.BusNumber = DeviceExtension->SystemIoBusNumber;
155 DeviceDescription.InterfaceType = DeviceExtension->AdapterInterfaceType;
156
157 /* acquire dma adapter */
158 DmaAdapter = IoGetDmaAdapter(DeviceExtension->PhysicalDeviceObject, &DeviceDescription, &NumberOfMapRegisters);
159 if (!DmaAdapter)
160 {
161 /* failed to acquire dma */
162 ExFreePool(Adapter);
163 return NULL;
164 }
165
166 /* store dma adapter */
167 Adapter->Adapter = DmaAdapter;
168
169 /* store map register count */
170 Adapter->MapRegisters = NumberOfMapRegisters;
171
172 /* store hw device extension */
173 Adapter->HwDeviceExtension = HwDeviceExtension;
174
175 /* store in dma adapter list */
176 InsertTailList(&DeviceExtension->DmaAdapterList, &Adapter->Entry);
177
178 /* return result */
179 return (PVP_DMA_ADAPTER)Adapter;
180 }
181
182 /*
183 * @implemented
184 */
185 VOID
186 NTAPI
187 VideoPortFreeCommonBuffer(IN PVOID HwDeviceExtension,
188 IN ULONG Length,
189 IN PVOID VirtualAddress,
190 IN PHYSICAL_ADDRESS LogicalAddress,
191 IN BOOLEAN CacheEnabled)
192 {
193 PVIP_DMA_ADAPTER VpDmaAdapter;
194 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
195
196 /* sanity check */
197 ASSERT(!IsListEmpty(&DeviceExtension->DmaAdapterList));
198
199 /* grab first dma adapter */
200 VpDmaAdapter = (PVIP_DMA_ADAPTER)CONTAINING_RECORD(DeviceExtension->DmaAdapterList.Flink, VIP_DMA_ADAPTER, Entry);
201
202 /* sanity checks */
203 ASSERT(VpDmaAdapter->HwDeviceExtension == HwDeviceExtension);
204 ASSERT(VpDmaAdapter->Adapter != NULL);
205 ASSERT(VpDmaAdapter->MapRegisters != 0);
206
207 VideoPortReleaseCommonBuffer(HwDeviceExtension, (PVP_DMA_ADAPTER)VpDmaAdapter, Length, LogicalAddress, VirtualAddress, CacheEnabled);
208 }
209
210 /*
211 * @implemented
212 */
213 PVOID
214 NTAPI
215 VideoPortGetCommonBuffer(IN PVOID HwDeviceExtension,
216 IN ULONG DesiredLength,
217 IN ULONG Alignment,
218 OUT PPHYSICAL_ADDRESS LogicalAddress,
219 OUT PULONG pActualLength,
220 IN BOOLEAN CacheEnabled)
221 {
222 PVOID Result;
223 PVIP_DMA_ADAPTER VpDmaAdapter;
224 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
225
226 /* maximum palette size */
227 if (DesiredLength > 262144)
228 {
229 /* size exceeded */
230 return NULL;
231 }
232
233 if (IsListEmpty(&DeviceExtension->DmaAdapterList))
234 {
235 /* no adapter available */
236 return NULL;
237 }
238
239 /* grab first dma adapter */
240 VpDmaAdapter = (PVIP_DMA_ADAPTER)CONTAINING_RECORD(DeviceExtension->DmaAdapterList.Flink, VIP_DMA_ADAPTER, Entry);
241
242 /* sanity checks */
243 ASSERT(VpDmaAdapter->HwDeviceExtension == HwDeviceExtension);
244 ASSERT(VpDmaAdapter->Adapter != NULL);
245 ASSERT(VpDmaAdapter->MapRegisters != 0);
246
247 /* allocate common buffer */
248 Result = VideoPortAllocateCommonBuffer(HwDeviceExtension, (PVP_DMA_ADAPTER)VpDmaAdapter, DesiredLength, LogicalAddress, CacheEnabled, NULL);
249
250 if (Result)
251 {
252 /* store length */
253 *pActualLength = DesiredLength;
254 }
255 else
256 {
257 /* failed to allocate common buffer */
258 *pActualLength = 0;
259 }
260
261 return Result;
262 }
263
264 /*
265 * @implemented
266 */
267 BOOLEAN
268 NTAPI
269 VideoPortUnmapDmaMemory(
270 PVOID HwDeviceExtension,
271 PVOID VirtualAddress,
272 HANDLE ProcessHandle,
273 PDMA BoardMemoryHandle)
274 {
275 /* Deprecated */
276 return FALSE;
277 }
278
279 /*
280 * @implemented
281 */
282 PDMA
283 NTAPI
284 VideoPortMapDmaMemory(IN PVOID HwDeviceExtension,
285 IN PVIDEO_REQUEST_PACKET pVrp,
286 IN PHYSICAL_ADDRESS BoardAddress,
287 IN PULONG Length,
288 IN PULONG InIoSpace,
289 IN PVOID MappedUserEvent,
290 IN PVOID DisplayDriverEvent,
291 IN OUT PVOID *VirtualAddress)
292 {
293 /* Deprecated */
294 return NULL;
295 }
296
297 /*
298 * @implemented
299 */
300 VOID
301 NTAPI
302 VideoPortSetDmaContext(IN PVOID HwDeviceExtension,
303 OUT PDMA pDma,
304 IN PVOID InstanceContext)
305 {
306 /* Deprecated */
307 return;
308 }
309
310 /*
311 * @implemented
312 */
313 BOOLEAN
314 NTAPI
315 VideoPortSignalDmaComplete(IN PVOID HwDeviceExtension,
316 IN PDMA pDmaHandle)
317 {
318 /* Deprecated */
319 return FALSE;
320 }
321
322
323 BOOLEAN
324 NTAPI
325 SyncScatterRoutine(
326 IN PVOID Context)
327 {
328 PDMA_START_CONTEXT StartContext = (PDMA_START_CONTEXT)Context;
329
330 StartContext->ExecuteDmaRoutine(StartContext->HwDeviceExtension, StartContext->VpDmaAdapter, (PVP_SCATTER_GATHER_LIST)StartContext->ScatterGatherList, StartContext->Context);
331 return TRUE;
332 }
333
334 VOID
335 NTAPI
336 ScatterAdapterControl(
337 IN PDEVICE_OBJECT *DeviceObject,
338 IN PIRP *Irp,
339 IN PSCATTER_GATHER_LIST ScatterGather,
340 IN PVOID Context)
341 {
342 PDMA_START_CONTEXT StartContext = (PDMA_START_CONTEXT)Context;
343
344 StartContext->ScatterGatherList = ScatterGather;
345
346 VideoPortSynchronizeExecution(StartContext->HwDeviceExtension, VpMediumPriority, SyncScatterRoutine, StartContext);
347 ExFreePool(StartContext);
348 }
349
350 /*
351 * @implemented
352 */
353 VP_STATUS
354 NTAPI
355 VideoPortStartDma(IN PVOID HwDeviceExtension,
356 IN PVP_DMA_ADAPTER VpDmaAdapter,
357 IN PVOID Mdl,
358 IN ULONG Offset,
359 IN OUT PULONG pLength,
360 IN PEXECUTE_DMA ExecuteDmaRoutine,
361 IN PVOID Context,
362 IN BOOLEAN WriteToDevice)
363 {
364 NTSTATUS Status;
365 KIRQL OldIrql;
366 PDMA_START_CONTEXT StartContext;
367 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
368 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
369
370 StartContext = ExAllocatePool(NonPagedPool, sizeof(DMA_START_CONTEXT));
371 if (!StartContext)
372 {
373 return ERROR_NOT_ENOUGH_MEMORY;
374 }
375
376 StartContext->Context = Context;
377 StartContext->ExecuteDmaRoutine = ExecuteDmaRoutine;
378 StartContext->HwDeviceExtension = HwDeviceExtension;
379 StartContext->VpDmaAdapter = VpDmaAdapter;
380
381 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
382
383 Status = Adapter->Adapter->DmaOperations->GetScatterGatherList(Adapter->Adapter,
384 DeviceExtension->PhysicalDeviceObject,
385 Mdl,
386 MmGetSystemAddressForMdl((PMDL)Mdl),
387 MmGetMdlByteCount((PMDL)Mdl),
388 (PDRIVER_LIST_CONTROL)ScatterAdapterControl,
389 StartContext,
390 WriteToDevice);
391
392 KeLowerIrql(OldIrql);
393
394 if (!NT_SUCCESS(Status))
395 {
396 *pLength = 0;
397 ExFreePool(StartContext);
398 Status = ERROR_NOT_ENOUGH_MEMORY;
399 }
400 else
401 {
402 Status = NO_ERROR;
403 }
404
405 /* Return status */
406 return Status;
407 }
408
409 /*
410 * @implemented
411 */
412 PVOID
413 NTAPI
414 VideoPortGetDmaContext(IN PVOID HwDeviceExtension,
415 IN PDMA pDma)
416 {
417 /* Deprecated */
418 return NULL;
419 }
420
421 /*
422 * @implemented
423 */
424 PDMA
425 NTAPI
426 VideoPortDoDma(IN PVOID HwDeviceExtension,
427 IN PDMA pDma,
428 IN DMA_FLAGS DmaFlags)
429 {
430 /* Deprecated */
431 return NULL;
432 }
433
434 /*
435 * @implemented
436 */
437 PDMA
438 NTAPI
439 VideoPortAssociateEventsWithDmaHandle(IN PVOID HwDeviceExtension,
440 IN OUT PVIDEO_REQUEST_PACKET pVrp,
441 IN PVOID MappedUserEvent,
442 IN PVOID DisplayDriverEvent)
443 {
444 /* Deprecated */
445 return NULL;
446 }
447
448 /*
449 * @implemented
450 */
451 VP_STATUS
452 NTAPI
453 VideoPortCompleteDma(IN PVOID HwDeviceExtension,
454 IN PVP_DMA_ADAPTER VpDmaAdapter,
455 IN PVP_SCATTER_GATHER_LIST VpScatterGather,
456 IN BOOLEAN WriteToDevice)
457 {
458 KIRQL OldIrql;
459 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
460
461 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
462 Adapter->Adapter->DmaOperations->PutScatterGatherList(Adapter->Adapter, (PSCATTER_GATHER_LIST)VpScatterGather, WriteToDevice);
463 KeLowerIrql(OldIrql);
464
465 return NO_ERROR;
466 }