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
14 IDmaChannelInitVtbl
*lpVtbl
;
19 PDEVICE_OBJECT pDeviceObject
;
20 PDMA_ADAPTER pAdapter
;
25 PVOID MapRegisterBase
;
27 ULONG LastTransferCount
;
29 ULONG MaximumBufferSize
;
30 ULONG MaxMapRegisters
;
31 ULONG AllocatedBufferSize
;
34 PHYSICAL_ADDRESS Address
;
37 BOOLEAN WriteToDevice
;
41 //---------------------------------------------------------------
45 extern GUID IID_IDmaChannelSlave
;
49 IDmaChannelInit_fnQueryInterface(
50 IDmaChannelInit
* iface
,
54 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
56 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
) ||
57 IsEqualGUIDAligned(refiid
, &IID_IDmaChannel
) ||
58 IsEqualGUIDAligned(refiid
, &IID_IDmaChannelSlave
))
60 *Output
= &This
->lpVtbl
;
61 InterlockedIncrement(&This
->ref
);
62 return STATUS_SUCCESS
;
64 DPRINT1("No interface!!!\n");
65 return STATUS_UNSUCCESSFUL
;
70 IDmaChannelInit_fnAddRef(
71 IDmaChannelInit
* iface
)
73 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
75 DPRINT("IDmaChannelInit_AddRef: This %p\n", This
);
77 return InterlockedIncrement(&This
->ref
);
82 IDmaChannelInit_fnRelease(
83 IDmaChannelInit
* iface
)
85 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
87 InterlockedDecrement(&This
->ref
);
89 DPRINT("IDmaChannelInit_Release: This %p new ref %u\n", This
, This
->ref
);
93 This
->pAdapter
->DmaOperations
->PutDmaAdapter(This
->pAdapter
);
94 FreeItem(This
, TAG_PORTCLASS
);
97 /* Return new reference count */
101 //---------------------------------------------------------------
102 // IDmaChannel methods
107 IDmaChannelInit_fnAllocateBuffer(
108 IN IDmaChannelInit
* iface
,
110 IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL
)
112 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
114 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
116 /* Did the caller already allocate a buffer ?*/
119 DPRINT1("IDmaChannelInit_AllocateBuffer free common buffer first \n");
120 return STATUS_UNSUCCESSFUL
;
123 This
->Buffer
= This
->pAdapter
->DmaOperations
->AllocateCommonBuffer(This
->pAdapter
, BufferSize
, &This
->Address
, FALSE
);
126 DPRINT1("IDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
127 return STATUS_UNSUCCESSFUL
;
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
);
134 return STATUS_SUCCESS
;
139 IDmaChannelInit_fnAllocatedBufferSize(
140 IN IDmaChannelInit
* iface
)
142 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
144 DPRINT("IDmaChannelInit_AllocatedBufferSize: This %p BufferSize %u\n", This
, This
->BufferSize
);
145 return This
->AllocatedBufferSize
;
150 IDmaChannelInit_fnCopyFrom(
151 IN IDmaChannelInit
* iface
,
152 IN PVOID Destination
,
157 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
159 DPRINT("IDmaChannelInit_CopyFrom: This %p Destination %p Source %p ByteCount %u\n", This
, Destination
, Source
, ByteCount
);
161 iface
->lpVtbl
->CopyTo(iface
, Destination
, Source
, ByteCount
);
166 IDmaChannelInit_fnCopyTo(
167 IN IDmaChannelInit
* iface
,
168 IN PVOID Destination
,
173 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
175 DPRINT("IDmaChannelInit_CopyTo: This %p Destination %p Source %p ByteCount %u\n", This
, Destination
, Source
, ByteCount
);
176 RtlCopyMemory(Destination
, Source
, ByteCount
);
181 IDmaChannelInit_fnFreeBuffer(
182 IN IDmaChannelInit
* iface
)
184 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
186 DPRINT("IDmaChannelInit_FreeBuffer: This %p\n", This
);
188 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
192 DPRINT1("IDmaChannelInit_FreeBuffer allocate common buffer first \n");
196 This
->pAdapter
->DmaOperations
->FreeCommonBuffer(This
->pAdapter
, This
->AllocatedBufferSize
, This
->Address
, This
->Buffer
, FALSE
);
198 This
->AllocatedBufferSize
= 0;
199 This
->Address
.QuadPart
= 0LL;
203 IoFreeMdl(This
->Mdl
);
210 IDmaChannelInit_fnGetAdapterObject(
211 IN IDmaChannelInit
* iface
)
213 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
215 DPRINT("IDmaChannelInit_GetAdapterObject: This %p\n", This
);
216 return (PADAPTER_OBJECT
)This
->pAdapter
;
221 IDmaChannelInit_fnMaximumBufferSize(
222 IN IDmaChannelInit
* iface
)
224 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
226 DPRINT("IDmaChannelInit_MaximumBufferSize: This %p\n", This
);
227 return This
->MaximumBufferSize
;
232 IDmaChannelInit_fnPhysicalAdress(
233 IN IDmaChannelInit
* iface
,
234 PPHYSICAL_ADDRESS Address
)
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
);
240 Address
->QuadPart
= This
->Address
.QuadPart
;
241 Result
.QuadPart
= (PtrToUlong(Address
));
247 IDmaChannelInit_fnSetBufferSize(
248 IN IDmaChannelInit
* iface
,
251 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
253 DPRINT("IDmaChannelInit_SetBufferSize: This %p\n", This
);
254 This
->BufferSize
= BufferSize
;
260 IDmaChannelInit_fnBufferSize(
261 IN IDmaChannelInit
* iface
)
263 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
265 return This
->BufferSize
;
271 IDmaChannelInit_fnSystemAddress(
272 IN IDmaChannelInit
* iface
)
274 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
276 DPRINT("IDmaChannelInit_SystemAddress: This %p\n", This
);
282 IDmaChannelInit_fnTransferCount(
283 IN IDmaChannelInit
* iface
)
285 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
287 DPRINT("IDmaChannelInit_TransferCount: This %p\n", This
);
288 return This
->LastTransferCount
;
293 IDmaChannelInit_fnReadCounter(
294 IN IDmaChannelInit
* iface
)
297 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
299 ASSERT_IRQL(DISPATCH_LEVEL
);
301 Counter
= This
->pAdapter
->DmaOperations
->ReadDmaCounter(This
->pAdapter
);
303 if (!This
->DmaStarted
|| Counter
>= This
->LastTransferCount
) //FIXME
312 IN PDEVICE_OBJECT DeviceObject
,
314 IN PVOID MapRegisterBase
,
318 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)Context
;
320 Length
= This
->MapSize
;
321 This
->MapRegisterBase
= MapRegisterBase
;
323 This
->pAdapter
->DmaOperations
->MapTransfer(This
->pAdapter
,
326 (PVOID
)((ULONG_PTR
)This
->Mdl
->StartVa
+ This
->Mdl
->ByteOffset
),
328 This
->WriteToDevice
);
330 if (Length
== This
->BufferSize
)
332 This
->DmaStarted
= TRUE
;
340 IDmaChannelInit_fnStart(
341 IN IDmaChannelInit
* iface
,
343 BOOLEAN WriteToDevice
)
348 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
350 DPRINT("IDmaChannelInit_Start: This %p\n", This
);
352 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
354 if (This
->DmaStarted
)
355 return STATUS_UNSUCCESSFUL
;
359 This
->Mdl
= IoAllocateMdl(This
->Buffer
, This
->MaximumBufferSize
, FALSE
, FALSE
, NULL
);
362 return STATUS_INSUFFICIENT_RESOURCES
;
364 MmBuildMdlForNonPagedPool(This
->Mdl
);
367 This
->MapSize
= MapSize
;
368 This
->WriteToDevice
= WriteToDevice
;
369 This
->LastTransferCount
= MapSize
;
372 // synchronize access
374 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
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
);
380 if(!NT_SUCCESS(Status
))
381 This
->LastTransferCount
= 0;
388 IDmaChannelInit_fnStop(
389 IN IDmaChannelInit
* iface
)
392 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
394 DPRINT("IDmaChannelInit_fnStop: This %p\n", This
);
395 ASSERT_IRQL(DISPATCH_LEVEL
);
397 if (!This
->DmaStarted
)
398 return STATUS_SUCCESS
;
400 This
->pAdapter
->DmaOperations
->FlushAdapterBuffers(This
->pAdapter
,
402 This
->MapRegisterBase
,
403 (PVOID
)((ULONG_PTR
)This
->Mdl
->StartVa
+ This
->Mdl
->ByteOffset
),
405 This
->WriteToDevice
);
407 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
409 This
->pAdapter
->DmaOperations
->FreeAdapterChannel(This
->pAdapter
);
411 KeLowerIrql(OldIrql
);
413 This
->DmaStarted
= FALSE
;
415 IoFreeMdl(This
->Mdl
);
418 return STATUS_SUCCESS
;
423 IDmaChannelInit_fnWaitForTC(
424 IN IDmaChannelInit
* iface
,
428 ULONG BytesRemaining
;
429 ULONG PrevBytesRemaining
;
431 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
433 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
435 BytesRemaining
= This
->pAdapter
->DmaOperations
->ReadDmaCounter(This
->pAdapter
);
438 return STATUS_SUCCESS
;
441 RetryCount
= Timeout
/ 10;
442 PrevBytesRemaining
= 0xFFFFFFFF;
445 BytesRemaining
= This
->pAdapter
->DmaOperations
->ReadDmaCounter(This
->pAdapter
);
450 if (PrevBytesRemaining
== BytesRemaining
)
453 KeStallExecutionProcessor(10);
454 PrevBytesRemaining
= BytesRemaining
;
456 }while(RetryCount
-- >= 1);
460 return STATUS_UNSUCCESSFUL
;
463 return STATUS_SUCCESS
;
469 IDmaChannelInit_fnInit(
470 IN IDmaChannelInit
* iface
,
471 IN PDEVICE_DESCRIPTION DeviceDescription
,
472 IN PDEVICE_OBJECT DeviceObject
)
474 INTERFACE_TYPE BusType
;
476 PDMA_ADAPTER Adapter
;
477 PPCLASS_DEVICE_EXTENSION DeviceExt
;
480 IDmaChannelInitImpl
* This
= (IDmaChannelInitImpl
*)iface
;
483 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyLegacyBusType
, sizeof(BusType
), (PVOID
)&BusType
, &ResultLength
);
484 if (NT_SUCCESS(Status
))
486 DeviceDescription
->InterfaceType
= BusType
;
488 /* Fetch device extension */
489 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
490 /* Acquire dma adapter */
491 Adapter
= IoGetDmaAdapter(DeviceExt
->PhysicalDeviceObject
, DeviceDescription
, &MapRegisters
);
494 FreeItem(This
, TAG_PORTCLASS
);
495 return STATUS_DEVICE_CONFIGURATION_ERROR
;
498 /* initialize object */
500 This
->pAdapter
= Adapter
;
501 This
->pDeviceObject
= DeviceObject
;
502 This
->MaximumBufferSize
= DeviceDescription
->MaximumLength
;
503 This
->MaxMapRegisters
= MapRegisters
;
505 return STATUS_SUCCESS
;
509 IDmaChannelInitVtbl vt_IDmaChannelInitVtbl
=
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
543 OUT PDMACHANNEL
* OutDmaChannel
,
544 IN PUNKNOWN OuterUnknown OPTIONAL
,
545 IN POOL_TYPE PoolType
,
546 IN PDEVICE_DESCRIPTION DeviceDescription
,
547 IN PDEVICE_OBJECT DeviceObject
)
550 IDmaChannelInitImpl
* This
;
552 DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
553 OutDmaChannel
, OuterUnknown
, PoolType
, DeviceDescription
, DeviceObject
);
555 This
= AllocateItem(PoolType
, sizeof(IDmaChannelInitImpl
), TAG_PORTCLASS
);
558 return STATUS_INSUFFICIENT_RESOURCES
;
561 /* initialize object */
562 Status
= IDmaChannelInit_fnInit((IDmaChannelInit
*)This
, DeviceDescription
, DeviceObject
);
563 if (NT_SUCCESS(Status
))
566 This
->lpVtbl
= &vt_IDmaChannelInitVtbl
;
567 *OutDmaChannel
= (PVOID
)(&This
->lpVtbl
);