60d50ee4c89a8b9fdcab186bee97de3419cf73ec
[reactos.git] / reactos / 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 if (IsListEmpty(&DeviceExtension->DmaAdapterList))
233 {
234 /* no adapter available */
235 return NULL;
236 }
237
238 /* grab first dma adapter */
239 VpDmaAdapter = (PVIP_DMA_ADAPTER)CONTAINING_RECORD(DeviceExtension->DmaAdapterList.Flink, VIP_DMA_ADAPTER, Entry);
240
241 /* sanity checks */
242 ASSERT(VpDmaAdapter->HwDeviceExtension == HwDeviceExtension);
243 ASSERT(VpDmaAdapter->Adapter != NULL);
244 ASSERT(VpDmaAdapter->MapRegisters != 0);
245
246 /* allocate common buffer */
247 Result = VideoPortAllocateCommonBuffer(HwDeviceExtension, (PVP_DMA_ADAPTER)VpDmaAdapter, DesiredLength, LogicalAddress, CacheEnabled, NULL);
248
249 if (Result)
250 {
251 /* store length */
252 *pActualLength = DesiredLength;
253 }
254 else
255 {
256 /* failed to allocate common buffer */
257 *pActualLength = 0;
258 }
259
260 return Result;
261 }
262
263 /*
264 * @implemented
265 */
266 BOOLEAN
267 NTAPI
268 VideoPortUnmapDmaMemory(
269 PVOID HwDeviceExtension,
270 PVOID VirtualAddress,
271 HANDLE ProcessHandle,
272 PDMA BoardMemoryHandle)
273 {
274 /* Deprecated */
275 return FALSE;
276 }
277
278 /*
279 * @implemented
280 */
281 PDMA
282 NTAPI
283 VideoPortMapDmaMemory(IN PVOID HwDeviceExtension,
284 IN PVIDEO_REQUEST_PACKET pVrp,
285 IN PHYSICAL_ADDRESS BoardAddress,
286 IN PULONG Length,
287 IN PULONG InIoSpace,
288 IN PVOID MappedUserEvent,
289 IN PVOID DisplayDriverEvent,
290 IN OUT PVOID *VirtualAddress)
291 {
292 /* Deprecated */
293 return NULL;
294 }
295
296 /*
297 * @implemented
298 */
299 VOID
300 NTAPI
301 VideoPortSetDmaContext(IN PVOID HwDeviceExtension,
302 OUT PDMA pDma,
303 IN PVOID InstanceContext)
304 {
305 /* Deprecated */
306 return;
307 }
308
309 /*
310 * @implemented
311 */
312 BOOLEAN
313 NTAPI
314 VideoPortSignalDmaComplete(IN PVOID HwDeviceExtension,
315 IN PDMA pDmaHandle)
316 {
317 /* Deprecated */
318 return FALSE;
319 }
320
321
322 BOOLEAN
323 NTAPI
324 SyncScatterRoutine(
325 IN PVOID Context)
326 {
327 PDMA_START_CONTEXT StartContext = (PDMA_START_CONTEXT)Context;
328
329 StartContext->ExecuteDmaRoutine(StartContext->HwDeviceExtension, StartContext->VpDmaAdapter, (PVP_SCATTER_GATHER_LIST)StartContext->ScatterGatherList, StartContext->Context);
330 return TRUE;
331 }
332
333 VOID
334 NTAPI
335 ScatterAdapterControl(
336 IN PDEVICE_OBJECT *DeviceObject,
337 IN PIRP *Irp,
338 IN PSCATTER_GATHER_LIST ScatterGather,
339 IN PVOID Context)
340 {
341 PDMA_START_CONTEXT StartContext = (PDMA_START_CONTEXT)Context;
342
343 StartContext->ScatterGatherList = ScatterGather;
344
345 VideoPortSynchronizeExecution(StartContext->HwDeviceExtension, VpMediumPriority, SyncScatterRoutine, StartContext);
346 ExFreePool(StartContext);
347 }
348
349 /*
350 * @implemented
351 */
352 VP_STATUS
353 NTAPI
354 VideoPortStartDma(IN PVOID HwDeviceExtension,
355 IN PVP_DMA_ADAPTER VpDmaAdapter,
356 IN PVOID Mdl,
357 IN ULONG Offset,
358 IN OUT PULONG pLength,
359 IN PEXECUTE_DMA ExecuteDmaRoutine,
360 IN PVOID Context,
361 IN BOOLEAN WriteToDevice)
362 {
363 NTSTATUS Status;
364 KIRQL OldIrql;
365 PDMA_START_CONTEXT StartContext;
366 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
367 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
368
369 StartContext = ExAllocatePool(NonPagedPool, sizeof(DMA_START_CONTEXT));
370 if (!StartContext)
371 {
372 return ERROR_NOT_ENOUGH_MEMORY;
373 }
374
375 StartContext->Context = Context;
376 StartContext->ExecuteDmaRoutine = ExecuteDmaRoutine;
377 StartContext->HwDeviceExtension = HwDeviceExtension;
378 StartContext->VpDmaAdapter = VpDmaAdapter;
379
380 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
381
382 Status = Adapter->Adapter->DmaOperations->GetScatterGatherList(Adapter->Adapter,
383 DeviceExtension->PhysicalDeviceObject,
384 Mdl,
385 MmGetSystemAddressForMdl((PMDL)Mdl),
386 MmGetMdlByteCount((PMDL)Mdl),
387 (PDRIVER_LIST_CONTROL)ScatterAdapterControl,
388 StartContext,
389 WriteToDevice);
390
391 KeLowerIrql(OldIrql);
392
393 if (!NT_SUCCESS(Status))
394 {
395 *pLength = 0;
396 ExFreePool(StartContext);
397 Status = ERROR_NOT_ENOUGH_MEMORY;
398 }
399 else
400 {
401 Status = NO_ERROR;
402 }
403
404 /* Return status */
405 return Status;
406 }
407
408 /*
409 * @implemented
410 */
411 PVOID
412 NTAPI
413 VideoPortGetDmaContext(IN PVOID HwDeviceExtension,
414 IN PDMA pDma)
415 {
416 /* Deprecated */
417 return NULL;
418 }
419
420 /*
421 * @implemented
422 */
423 PDMA
424 NTAPI
425 VideoPortDoDma(IN PVOID HwDeviceExtension,
426 IN PDMA pDma,
427 IN DMA_FLAGS DmaFlags)
428 {
429 /* Deprecated */
430 return NULL;
431 }
432
433 /*
434 * @implemented
435 */
436 PDMA
437 NTAPI
438 VideoPortAssociateEventsWithDmaHandle(IN PVOID HwDeviceExtension,
439 IN OUT PVIDEO_REQUEST_PACKET pVrp,
440 IN PVOID MappedUserEvent,
441 IN PVOID DisplayDriverEvent)
442 {
443 /* Deprecated */
444 return NULL;
445 }
446
447 /*
448 * @implemented
449 */
450 VP_STATUS
451 NTAPI
452 VideoPortCompleteDma(IN PVOID HwDeviceExtension,
453 IN PVP_DMA_ADAPTER VpDmaAdapter,
454 IN PVP_SCATTER_GATHER_LIST VpScatterGather,
455 IN BOOLEAN WriteToDevice)
456 {
457 KIRQL OldIrql;
458 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter;
459
460 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
461 Adapter->Adapter->DmaOperations->PutScatterGatherList(Adapter->Adapter, (PSCATTER_GATHER_LIST)VpScatterGather, WriteToDevice);
462 KeLowerIrql(OldIrql);
463
464 return NO_ERROR;
465 }