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