xref: /reactos/win32ss/drivers/videoprt/dma.c (revision 84344399)
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 }
467