- Remove dead code
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / dma_slave.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/dma_Init.c
5 * PURPOSE: portcls dma support object
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.h"
10
11
12 typedef struct
13 {
14 IDmaChannelInitVtbl *lpVtbl;
15
16 LONG ref;
17
18
19 PDEVICE_OBJECT pDeviceObject;
20 PDMA_ADAPTER pAdapter;
21
22 BOOL DmaStarted;
23
24 ULONG MapSize;
25 PVOID MapRegisterBase;
26
27 ULONG LastTransferCount;
28
29 ULONG MaximumBufferSize;
30 ULONG MaxMapRegisters;
31 ULONG AllocatedBufferSize;
32 ULONG BufferSize;
33
34 PHYSICAL_ADDRESS Address;
35 PVOID Buffer;
36 PMDL Mdl;
37 BOOLEAN WriteToDevice;
38
39 }IDmaChannelInitImpl;
40
41 //---------------------------------------------------------------
42 // IUnknown methods
43 //
44
45 extern GUID IID_IDmaChannelSlave;
46
47 NTSTATUS
48 NTAPI
49 IDmaChannelInit_fnQueryInterface(
50 IDmaChannelInit * iface,
51 IN REFIID refiid,
52 OUT PVOID* Output)
53 {
54 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
55
56 if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
57 IsEqualGUIDAligned(refiid, &IID_IDmaChannel) ||
58 IsEqualGUIDAligned(refiid, &IID_IDmaChannelSlave))
59 {
60 *Output = &This->lpVtbl;
61 InterlockedIncrement(&This->ref);
62 return STATUS_SUCCESS;
63 }
64 DPRINT1("No interface!!!\n");
65 return STATUS_UNSUCCESSFUL;
66 }
67
68 ULONG
69 NTAPI
70 IDmaChannelInit_fnAddRef(
71 IDmaChannelInit * iface)
72 {
73 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
74
75 DPRINT("IDmaChannelInit_AddRef: This %p\n", This);
76
77 return InterlockedIncrement(&This->ref);
78 }
79
80 ULONG
81 NTAPI
82 IDmaChannelInit_fnRelease(
83 IDmaChannelInit* iface)
84 {
85 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
86
87 InterlockedDecrement(&This->ref);
88
89 DPRINT("IDmaChannelInit_Release: This %p new ref %u\n", This, This->ref);
90
91 if (This->ref == 0)
92 {
93 This->pAdapter->DmaOperations->PutDmaAdapter(This->pAdapter);
94 FreeItem(This, TAG_PORTCLASS);
95 return 0;
96 }
97 /* Return new reference count */
98 return This->ref;
99 }
100
101 //---------------------------------------------------------------
102 // IDmaChannel methods
103 //
104
105 NTSTATUS
106 NTAPI
107 IDmaChannelInit_fnAllocateBuffer(
108 IN IDmaChannelInit * iface,
109 IN ULONG BufferSize,
110 IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL)
111 {
112 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
113
114 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
115
116 /* Did the caller already allocate a buffer ?*/
117 if (This->Buffer)
118 {
119 DPRINT1("IDmaChannelInit_AllocateBuffer free common buffer first \n");
120 return STATUS_UNSUCCESSFUL;
121 }
122
123 This->Buffer = This->pAdapter->DmaOperations->AllocateCommonBuffer(This->pAdapter, BufferSize, &This->Address, FALSE);
124 if (!This->Buffer)
125 {
126 DPRINT1("IDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
127 return STATUS_UNSUCCESSFUL;
128 }
129
130 This->BufferSize = BufferSize;
131 This->AllocatedBufferSize = BufferSize;
132 DPRINT1("IDmaChannelInit_fnAllocateBuffer Success Buffer %p BufferSize %u Address %x\n", This->Buffer, BufferSize, This->Address);
133
134 return STATUS_SUCCESS;
135 }
136
137 ULONG
138 NTAPI
139 IDmaChannelInit_fnAllocatedBufferSize(
140 IN IDmaChannelInit * iface)
141 {
142 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
143
144 DPRINT("IDmaChannelInit_AllocatedBufferSize: This %p BufferSize %u\n", This, This->BufferSize);
145 return This->AllocatedBufferSize;
146 }
147
148 VOID
149 NTAPI
150 IDmaChannelInit_fnCopyFrom(
151 IN IDmaChannelInit * iface,
152 IN PVOID Destination,
153 IN PVOID Source,
154 IN ULONG ByteCount
155 )
156 {
157 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
158
159 DPRINT("IDmaChannelInit_CopyFrom: This %p Destination %p Source %p ByteCount %u\n", This, Destination, Source, ByteCount);
160
161 iface->lpVtbl->CopyTo(iface, Destination, Source, ByteCount);
162 }
163
164 VOID
165 NTAPI
166 IDmaChannelInit_fnCopyTo(
167 IN IDmaChannelInit * iface,
168 IN PVOID Destination,
169 IN PVOID Source,
170 IN ULONG ByteCount
171 )
172 {
173 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
174
175 DPRINT("IDmaChannelInit_CopyTo: This %p Destination %p Source %p ByteCount %u\n", This, Destination, Source, ByteCount);
176 RtlCopyMemory(Destination, Source, ByteCount);
177 }
178
179 VOID
180 NTAPI
181 IDmaChannelInit_fnFreeBuffer(
182 IN IDmaChannelInit * iface)
183 {
184 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
185
186 DPRINT("IDmaChannelInit_FreeBuffer: This %p\n", This);
187
188 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
189
190 if (!This->Buffer)
191 {
192 DPRINT1("IDmaChannelInit_FreeBuffer allocate common buffer first \n");
193 return;
194 }
195
196 This->pAdapter->DmaOperations->FreeCommonBuffer(This->pAdapter, This->AllocatedBufferSize, This->Address, This->Buffer, FALSE);
197 This->Buffer = NULL;
198 This->AllocatedBufferSize = 0;
199 This->Address.QuadPart = 0LL;
200
201 if (This->Mdl)
202 {
203 IoFreeMdl(This->Mdl);
204 This->Mdl = NULL;
205 }
206 }
207
208 PADAPTER_OBJECT
209 NTAPI
210 IDmaChannelInit_fnGetAdapterObject(
211 IN IDmaChannelInit * iface)
212 {
213 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
214
215 DPRINT("IDmaChannelInit_GetAdapterObject: This %p\n", This);
216 return (PADAPTER_OBJECT)This->pAdapter;
217 }
218
219 ULONG
220 NTAPI
221 IDmaChannelInit_fnMaximumBufferSize(
222 IN IDmaChannelInit * iface)
223 {
224 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
225
226 DPRINT("IDmaChannelInit_MaximumBufferSize: This %p\n", This);
227 return This->MaximumBufferSize;
228 }
229
230 PHYSICAL_ADDRESS
231 NTAPI
232 IDmaChannelInit_fnPhysicalAdress(
233 IN IDmaChannelInit * iface,
234 PPHYSICAL_ADDRESS Address)
235 {
236 PHYSICAL_ADDRESS Result;
237 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
238 DPRINT("IDmaChannelInit_PhysicalAdress: This %p Virtuell %p Physical High %x Low %x%\n", This, This->Buffer, This->Address.HighPart, This->Address.LowPart);
239
240 Address->QuadPart = This->Address.QuadPart;
241 Result.QuadPart = (PtrToUlong(Address));
242 return Result;
243 }
244
245 VOID
246 NTAPI
247 IDmaChannelInit_fnSetBufferSize(
248 IN IDmaChannelInit * iface,
249 IN ULONG BufferSize)
250 {
251 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
252
253 DPRINT("IDmaChannelInit_SetBufferSize: This %p\n", This);
254 This->BufferSize = BufferSize;
255
256 }
257
258 ULONG
259 NTAPI
260 IDmaChannelInit_fnBufferSize(
261 IN IDmaChannelInit * iface)
262 {
263 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
264
265 return This->BufferSize;
266 }
267
268
269 PVOID
270 NTAPI
271 IDmaChannelInit_fnSystemAddress(
272 IN IDmaChannelInit * iface)
273 {
274 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
275
276 DPRINT("IDmaChannelInit_SystemAddress: This %p\n", This);
277 return This->Buffer;
278 }
279
280 ULONG
281 NTAPI
282 IDmaChannelInit_fnTransferCount(
283 IN IDmaChannelInit * iface)
284 {
285 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
286
287 DPRINT("IDmaChannelInit_TransferCount: This %p\n", This);
288 return This->LastTransferCount;
289 }
290
291 ULONG
292 NTAPI
293 IDmaChannelInit_fnReadCounter(
294 IN IDmaChannelInit * iface)
295 {
296 ULONG Counter;
297 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
298
299 ASSERT_IRQL(DISPATCH_LEVEL);
300
301 Counter = This->pAdapter->DmaOperations->ReadDmaCounter(This->pAdapter);
302
303 if (!This->DmaStarted || Counter >= This->LastTransferCount) //FIXME
304 Counter = 0;
305
306 return Counter;
307 }
308
309 IO_ALLOCATION_ACTION
310 NTAPI
311 AdapterControl(
312 IN PDEVICE_OBJECT DeviceObject,
313 IN PIRP Irp,
314 IN PVOID MapRegisterBase,
315 IN PVOID Context)
316 {
317 ULONG Length;
318 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)Context;
319
320 Length = This->MapSize;
321 This->MapRegisterBase = MapRegisterBase;
322
323 This->pAdapter->DmaOperations->MapTransfer(This->pAdapter,
324 This->Mdl,
325 MapRegisterBase,
326 (PVOID)((ULONG_PTR)This->Mdl->StartVa + This->Mdl->ByteOffset),
327 &Length,
328 This->WriteToDevice);
329
330 if (Length == This->BufferSize)
331 {
332 This->DmaStarted = TRUE;
333 }
334
335 return KeepObject;
336 }
337
338 NTSTATUS
339 NTAPI
340 IDmaChannelInit_fnStart(
341 IN IDmaChannelInit * iface,
342 ULONG MapSize,
343 BOOLEAN WriteToDevice)
344 {
345 NTSTATUS Status;
346 ULONG MapRegisters;
347 KIRQL OldIrql;
348 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
349
350 DPRINT("IDmaChannelInit_Start: This %p\n", This);
351
352 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
353
354 if (This->DmaStarted)
355 return STATUS_UNSUCCESSFUL;
356
357 if (!This->Mdl)
358 {
359 This->Mdl = IoAllocateMdl(This->Buffer, This->MaximumBufferSize, FALSE, FALSE, NULL);
360 if (!This->Mdl)
361 {
362 return STATUS_INSUFFICIENT_RESOURCES;
363 }
364 MmBuildMdlForNonPagedPool(This->Mdl);
365 }
366
367 This->MapSize = MapSize;
368 This->WriteToDevice = WriteToDevice;
369 This->LastTransferCount = MapSize;
370
371 //FIXME
372 // synchronize access
373 //
374 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
375
376 MapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(This->Buffer, MapSize);
377 Status = This->pAdapter->DmaOperations->AllocateAdapterChannel(This->pAdapter, This->pDeviceObject, MapRegisters, AdapterControl, (PVOID)This);
378 KeLowerIrql(OldIrql);
379
380 if(!NT_SUCCESS(Status))
381 This->LastTransferCount = 0;
382
383 return Status;
384 }
385
386 NTSTATUS
387 NTAPI
388 IDmaChannelInit_fnStop(
389 IN IDmaChannelInit * iface)
390 {
391 KIRQL OldIrql;
392 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
393
394 DPRINT("IDmaChannelInit_fnStop: This %p\n", This);
395 ASSERT_IRQL(DISPATCH_LEVEL);
396
397 if (!This->DmaStarted)
398 return STATUS_SUCCESS;
399
400 This->pAdapter->DmaOperations->FlushAdapterBuffers(This->pAdapter,
401 This->Mdl,
402 This->MapRegisterBase,
403 (PVOID)((ULONG_PTR)This->Mdl->StartVa + This->Mdl->ByteOffset),
404 This->MapSize,
405 This->WriteToDevice);
406
407 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
408
409 This->pAdapter->DmaOperations->FreeAdapterChannel(This->pAdapter);
410
411 KeLowerIrql(OldIrql);
412
413 This->DmaStarted = FALSE;
414
415 IoFreeMdl(This->Mdl);
416 This->Mdl = NULL;
417
418 return STATUS_SUCCESS;
419 }
420
421 NTSTATUS
422 NTAPI
423 IDmaChannelInit_fnWaitForTC(
424 IN IDmaChannelInit * iface,
425 ULONG Timeout)
426 {
427 ULONG RetryCount;
428 ULONG BytesRemaining;
429 ULONG PrevBytesRemaining;
430
431 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
432
433 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
434
435 BytesRemaining = This->pAdapter->DmaOperations->ReadDmaCounter(This->pAdapter);
436 if (!BytesRemaining)
437 {
438 return STATUS_SUCCESS;
439 }
440
441 RetryCount = Timeout / 10;
442 PrevBytesRemaining = 0xFFFFFFFF;
443 do
444 {
445 BytesRemaining = This->pAdapter->DmaOperations->ReadDmaCounter(This->pAdapter);
446
447 if (!BytesRemaining)
448 break;
449
450 if (PrevBytesRemaining == BytesRemaining)
451 break;
452
453 KeStallExecutionProcessor(10);
454 PrevBytesRemaining = BytesRemaining;
455
456 }while(RetryCount-- >= 1);
457
458 if (BytesRemaining)
459 {
460 return STATUS_UNSUCCESSFUL;
461 }
462
463 return STATUS_SUCCESS;
464
465 }
466
467 NTSTATUS
468 NTAPI
469 IDmaChannelInit_fnInit(
470 IN IDmaChannelInit * iface,
471 IN PDEVICE_DESCRIPTION DeviceDescription,
472 IN PDEVICE_OBJECT DeviceObject)
473 {
474 INTERFACE_TYPE BusType;
475 NTSTATUS Status;
476 PDMA_ADAPTER Adapter;
477 PPCLASS_DEVICE_EXTENSION DeviceExt;
478 ULONG MapRegisters;
479 ULONG ResultLength;
480 IDmaChannelInitImpl * This = (IDmaChannelInitImpl*)iface;
481
482 /* Get bus type */
483 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyLegacyBusType, sizeof(BusType), (PVOID)&BusType, &ResultLength);
484 if (NT_SUCCESS(Status))
485 {
486 DeviceDescription->InterfaceType = BusType;
487 }
488 /* Fetch device extension */
489 DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
490 /* Acquire dma adapter */
491 Adapter = IoGetDmaAdapter(DeviceExt->PhysicalDeviceObject, DeviceDescription, &MapRegisters);
492 if (!Adapter)
493 {
494 FreeItem(This, TAG_PORTCLASS);
495 return STATUS_DEVICE_CONFIGURATION_ERROR;
496 }
497
498 /* initialize object */
499 This->ref = 1;
500 This->pAdapter = Adapter;
501 This->pDeviceObject = DeviceObject;
502 This->MaximumBufferSize = DeviceDescription->MaximumLength;
503 This->MaxMapRegisters = MapRegisters;
504
505 return STATUS_SUCCESS;
506 }
507
508
509 IDmaChannelInitVtbl vt_IDmaChannelInitVtbl =
510 {
511 /* IUnknown methods */
512 IDmaChannelInit_fnQueryInterface,
513 IDmaChannelInit_fnAddRef,
514 IDmaChannelInit_fnRelease,
515 /* IDmaChannel methods */
516 IDmaChannelInit_fnAllocateBuffer,
517 IDmaChannelInit_fnFreeBuffer,
518 IDmaChannelInit_fnTransferCount,
519 IDmaChannelInit_fnMaximumBufferSize,
520 IDmaChannelInit_fnAllocatedBufferSize,
521 IDmaChannelInit_fnBufferSize,
522 IDmaChannelInit_fnSetBufferSize,
523 IDmaChannelInit_fnSystemAddress,
524 IDmaChannelInit_fnPhysicalAdress,
525 IDmaChannelInit_fnGetAdapterObject,
526 IDmaChannelInit_fnCopyTo,
527 IDmaChannelInit_fnCopyFrom,
528 /* IDmaChannelSlave methods */
529 IDmaChannelInit_fnStart,
530 IDmaChannelInit_fnStop,
531 IDmaChannelInit_fnReadCounter,
532 IDmaChannelInit_fnWaitForTC,
533 /* IDmaChannelInit methods */
534 IDmaChannelInit_fnInit
535 };
536
537
538 /*
539 * @unimplemented
540 */
541 NTSTATUS NTAPI
542 PcNewDmaChannel(
543 OUT PDMACHANNEL* OutDmaChannel,
544 IN PUNKNOWN OuterUnknown OPTIONAL,
545 IN POOL_TYPE PoolType,
546 IN PDEVICE_DESCRIPTION DeviceDescription,
547 IN PDEVICE_OBJECT DeviceObject)
548 {
549 NTSTATUS Status;
550 IDmaChannelInitImpl * This;
551
552 DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
553 OutDmaChannel, OuterUnknown, PoolType, DeviceDescription, DeviceObject);
554
555 This = AllocateItem(PoolType, sizeof(IDmaChannelInitImpl), TAG_PORTCLASS);
556 if (!This)
557 {
558 return STATUS_INSUFFICIENT_RESOURCES;
559 }
560
561 /* initialize object */
562 Status = IDmaChannelInit_fnInit((IDmaChannelInit*)This, DeviceDescription, DeviceObject);
563 if (NT_SUCCESS(Status))
564 {
565 /* store result */
566 This->lpVtbl = &vt_IDmaChannelInitVtbl;
567 *OutDmaChannel = (PVOID)(&This->lpVtbl);
568 }
569
570 return Status;
571
572 }