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
11 class CDmaChannelInit
: public IDmaChannelInit
14 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
16 STDMETHODIMP_(ULONG
) AddRef()
18 InterlockedIncrement(&m_Ref
);
21 STDMETHODIMP_(ULONG
) Release()
23 InterlockedDecrement(&m_Ref
);
33 CDmaChannelInit(IUnknown
* OuterUnknown
){}
34 virtual ~CDmaChannelInit(){}
38 PDEVICE_OBJECT m_pDeviceObject
;
39 PDMA_ADAPTER m_pAdapter
;
44 PVOID m_MapRegisterBase
;
46 ULONG m_LastTransferCount
;
48 ULONG m_MaximumBufferSize
;
49 ULONG m_MaxMapRegisters
;
50 ULONG m_AllocatedBufferSize
;
53 PHYSICAL_ADDRESS m_Address
;
56 BOOLEAN m_WriteToDevice
;
58 friend IO_ALLOCATION_ACTION NTAPI
AdapterControl(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PVOID MapRegisterBase
, IN PVOID Context
);
65 //---------------------------------------------------------------
69 extern GUID IID_IDmaChannelSlave
;
73 CDmaChannelInit::QueryInterface(
77 if (IsEqualGUIDAligned(refiid
, IID_IUnknown
) ||
78 IsEqualGUIDAligned(refiid
, IID_IDmaChannel
))
79 //IsEqualGUIDAligned(refiid, IID_IDmaChannelSlave)) // HACK
81 *Output
= PVOID(PUNKNOWN(this));
82 PUNKNOWN(*Output
)->AddRef();
83 return STATUS_SUCCESS
;
85 DPRINT("No interface!!!\n");
86 return STATUS_UNSUCCESSFUL
;
89 //---------------------------------------------------------------
90 // IDmaChannel methods
95 CDmaChannelInit::AllocateBuffer(
97 IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL
)
99 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
101 // Did the caller already allocate a buffer ?*/
104 DPRINT("CDmaChannelInit_AllocateBuffer free common buffer first \n");
105 return STATUS_UNSUCCESSFUL
;
108 m_Buffer
= m_pAdapter
->DmaOperations
->AllocateCommonBuffer(m_pAdapter
, BufferSize
, &m_Address
, FALSE
);
111 DPRINT("CDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
112 return STATUS_UNSUCCESSFUL
;
115 m_BufferSize
= BufferSize
;
116 m_AllocatedBufferSize
= BufferSize
;
117 DPRINT("CDmaChannelInit::AllocateBuffer Success Buffer %p BufferSize %u Address %x\n", m_Buffer
, BufferSize
, m_Address
);
119 return STATUS_SUCCESS
;
124 CDmaChannelInit::AllocatedBufferSize()
126 DPRINT("CDmaChannelInit_AllocatedBufferSize: this %p BufferSize %u\n", this, m_BufferSize
);
127 return m_AllocatedBufferSize
;
132 CDmaChannelInit::CopyFrom(
133 IN PVOID Destination
,
138 DPRINT("CDmaChannelInit_CopyFrom: this %p Destination %p Source %p ByteCount %u\n", this, Destination
, Source
, ByteCount
);
140 CopyTo(Destination
, Source
, ByteCount
);
145 CDmaChannelInit::CopyTo(
146 IN PVOID Destination
,
151 DPRINT("CDmaChannelInit_CopyTo: this %p Destination %p Source %p ByteCount %u\n", this, Destination
, Source
, ByteCount
);
152 RtlCopyMemory(Destination
, Source
, ByteCount
);
157 CDmaChannelInit::FreeBuffer()
159 DPRINT("CDmaChannelInit_FreeBuffer: this %p\n", this);
161 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
165 DPRINT("CDmaChannelInit_FreeBuffer allocate common buffer first \n");
169 m_pAdapter
->DmaOperations
->FreeCommonBuffer(m_pAdapter
, m_AllocatedBufferSize
, m_Address
, m_Buffer
, FALSE
);
171 m_AllocatedBufferSize
= 0;
172 m_Address
.QuadPart
= 0LL;
183 CDmaChannelInit::GetAdapterObject()
185 DPRINT("CDmaChannelInit_GetAdapterObject: this %p\n", this);
186 return (PADAPTER_OBJECT
)m_pAdapter
;
191 CDmaChannelInit::MaximumBufferSize()
193 DPRINT("CDmaChannelInit_MaximumBufferSize: this %p\n", this);
194 return m_MaximumBufferSize
;
199 CDmaChannelInit::PhysicalAddress(
200 PPHYSICAL_ADDRESS Address
)
202 DPRINT("CDmaChannelInit_PhysicalAdress: this %p Virtuell %p Physical High %x Low %x%\n", this, m_Buffer
, m_Address
.HighPart
, m_Address
.LowPart
);
204 PHYSICAL_ADDRESS Result
;
206 Address
->QuadPart
= m_Address
.QuadPart
;
207 Result
.QuadPart
= (PtrToUlong(Address
));
213 CDmaChannelInit::SetBufferSize(
216 DPRINT("CDmaChannelInit_SetBufferSize: this %p\n", this);
217 m_BufferSize
= BufferSize
;
223 CDmaChannelInit::BufferSize()
225 DPRINT("BufferSize %u\n", m_BufferSize
);
226 PC_ASSERT(m_BufferSize
);
233 CDmaChannelInit::SystemAddress()
235 DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this);
241 CDmaChannelInit::TransferCount()
243 DPRINT("CDmaChannelInit_TransferCount: this %p\n", this);
244 return m_LastTransferCount
;
249 CDmaChannelInit::ReadCounter()
253 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
255 Counter
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
257 if (!m_DmaStarted
|| Counter
>= m_LastTransferCount
)
260 DPRINT("ReadCounter %u\n", Counter
);
268 IN PDEVICE_OBJECT DeviceObject
,
270 IN PVOID MapRegisterBase
,
274 CDmaChannelInit
* This
= (CDmaChannelInit
*)Context
;
276 Length
= This
->m_MapSize
;
277 This
->m_MapRegisterBase
= MapRegisterBase
;
279 This
->m_pAdapter
->DmaOperations
->MapTransfer(This
->m_pAdapter
,
282 (PVOID
)((ULONG_PTR
)This
->m_Mdl
->StartVa
+ This
->m_Mdl
->ByteOffset
),
284 This
->m_WriteToDevice
);
286 if (Length
== This
->m_BufferSize
)
288 This
->m_DmaStarted
= TRUE
;
296 CDmaChannelInit::Start(
298 BOOLEAN WriteToDevice
)
304 DPRINT("CDmaChannelInit_Start: this %p\n", this);
306 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
309 return STATUS_UNSUCCESSFUL
;
313 m_Mdl
= IoAllocateMdl(m_Buffer
, m_MaximumBufferSize
, FALSE
, FALSE
, NULL
);
316 return STATUS_INSUFFICIENT_RESOURCES
;
318 MmBuildMdlForNonPagedPool(m_Mdl
);
322 m_WriteToDevice
= WriteToDevice
;
323 m_LastTransferCount
= MapSize
;
326 // synchronize access
328 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
330 MapRegisters
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer
, MapSize
);
331 Status
= m_pAdapter
->DmaOperations
->AllocateAdapterChannel(m_pAdapter
, m_pDeviceObject
, MapRegisters
, AdapterControl
, (PVOID
)this);
332 KeLowerIrql(OldIrql
);
334 if(!NT_SUCCESS(Status
))
335 m_LastTransferCount
= 0;
342 CDmaChannelInit::Stop()
346 DPRINT("CDmaChannelInit::Stop: this %p\n", this);
347 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
350 return STATUS_SUCCESS
;
352 m_pAdapter
->DmaOperations
->FlushAdapterBuffers(m_pAdapter
,
355 (PVOID
)((ULONG_PTR
)m_Mdl
->StartVa
+ m_Mdl
->ByteOffset
),
359 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
361 m_pAdapter
->DmaOperations
->FreeAdapterChannel(m_pAdapter
);
363 KeLowerIrql(OldIrql
);
365 m_DmaStarted
= FALSE
;
370 return STATUS_SUCCESS
;
375 CDmaChannelInit::WaitForTC(
379 ULONG BytesRemaining
;
380 ULONG PrevBytesRemaining
;
382 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
384 BytesRemaining
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
387 return STATUS_SUCCESS
;
390 RetryCount
= Timeout
/ 10;
391 PrevBytesRemaining
= 0xFFFFFFFF;
394 BytesRemaining
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
399 if (PrevBytesRemaining
== BytesRemaining
)
402 KeStallExecutionProcessor(10);
403 PrevBytesRemaining
= BytesRemaining
;
405 }while(RetryCount
-- >= 1);
409 return STATUS_UNSUCCESSFUL
;
412 return STATUS_SUCCESS
;
418 CDmaChannelInit::Init(
419 IN PDEVICE_DESCRIPTION DeviceDescription
,
420 IN PDEVICE_OBJECT DeviceObject
)
422 INTERFACE_TYPE BusType
;
424 PDMA_ADAPTER Adapter
;
425 PPCLASS_DEVICE_EXTENSION DeviceExt
;
430 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyLegacyBusType
, sizeof(BusType
), (PVOID
)&BusType
, &ResultLength
);
431 if (NT_SUCCESS(Status
))
433 DeviceDescription
->InterfaceType
= BusType
;
435 // Fetch device extension
436 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
437 // Acquire dma adapter
438 Adapter
= IoGetDmaAdapter(DeviceExt
->PhysicalDeviceObject
, DeviceDescription
, &MapRegisters
);
441 FreeItem(this, TAG_PORTCLASS
);
442 return STATUS_DEVICE_CONFIGURATION_ERROR
;
446 m_pAdapter
= Adapter
;
447 m_pDeviceObject
= DeviceObject
;
448 m_MaximumBufferSize
= DeviceDescription
->MaximumLength
;
449 m_MaxMapRegisters
= MapRegisters
;
451 return STATUS_SUCCESS
;
457 OUT PDMACHANNEL
* OutDmaChannel
,
458 IN PUNKNOWN OuterUnknown OPTIONAL
,
459 IN POOL_TYPE PoolType
,
460 IN PDEVICE_DESCRIPTION DeviceDescription
,
461 IN PDEVICE_OBJECT DeviceObject
)
464 CDmaChannelInit
* This
;
466 DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
467 OutDmaChannel
, OuterUnknown
, PoolType
, DeviceDescription
, DeviceObject
);
469 This
= new(PoolType
, TAG_PORTCLASS
)CDmaChannelInit(OuterUnknown
);
471 return STATUS_INSUFFICIENT_RESOURCES
;
473 Status
= This
->QueryInterface(IID_IDmaChannel
, (PVOID
*)OutDmaChannel
);
475 if (!NT_SUCCESS(Status
))
481 Status
= This
->Init(DeviceDescription
, DeviceObject
);
483 if (!NT_SUCCESS(Status
))