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
;
201 CDmaChannelInit::PhysicalAddress()
203 DPRINT("CDmaChannelInit_PhysicalAdress: this %p Virtuell %p Physical High %x Low %x%\n", this, m_Buffer
, m_Address
.HighPart
, m_Address
.LowPart
);
212 CDmaChannelInit::PhysicalAddress(
213 PPHYSICAL_ADDRESS Address
)
215 DPRINT("CDmaChannelInit_PhysicalAdress: this %p Virtuell %p Physical High %x Low %x%\n", this, m_Buffer
, m_Address
.HighPart
, m_Address
.LowPart
);
217 PHYSICAL_ADDRESS Result
;
219 Address
->QuadPart
= m_Address
.QuadPart
;
220 Result
.QuadPart
= (PtrToUlong(Address
));
229 CDmaChannelInit::SetBufferSize(
232 DPRINT("CDmaChannelInit_SetBufferSize: this %p\n", this);
233 m_BufferSize
= BufferSize
;
239 CDmaChannelInit::BufferSize()
241 DPRINT("BufferSize %u\n", m_BufferSize
);
242 PC_ASSERT(m_BufferSize
);
249 CDmaChannelInit::SystemAddress()
251 DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this);
257 CDmaChannelInit::TransferCount()
259 DPRINT("CDmaChannelInit_TransferCount: this %p\n", this);
260 return m_LastTransferCount
;
265 CDmaChannelInit::ReadCounter()
269 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
271 Counter
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
273 if (!m_DmaStarted
|| Counter
>= m_LastTransferCount
)
276 DPRINT("ReadCounter %u\n", Counter
);
284 IN PDEVICE_OBJECT DeviceObject
,
286 IN PVOID MapRegisterBase
,
290 CDmaChannelInit
* This
= (CDmaChannelInit
*)Context
;
292 Length
= This
->m_MapSize
;
293 This
->m_MapRegisterBase
= MapRegisterBase
;
295 This
->m_pAdapter
->DmaOperations
->MapTransfer(This
->m_pAdapter
,
298 (PVOID
)((ULONG_PTR
)This
->m_Mdl
->StartVa
+ This
->m_Mdl
->ByteOffset
),
300 This
->m_WriteToDevice
);
302 if (Length
== This
->m_BufferSize
)
304 This
->m_DmaStarted
= TRUE
;
312 CDmaChannelInit::Start(
314 BOOLEAN WriteToDevice
)
320 DPRINT("CDmaChannelInit_Start: this %p\n", this);
322 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
325 return STATUS_UNSUCCESSFUL
;
329 m_Mdl
= IoAllocateMdl(m_Buffer
, m_MaximumBufferSize
, FALSE
, FALSE
, NULL
);
332 return STATUS_INSUFFICIENT_RESOURCES
;
334 MmBuildMdlForNonPagedPool(m_Mdl
);
338 m_WriteToDevice
= WriteToDevice
;
339 m_LastTransferCount
= MapSize
;
342 // synchronize access
344 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
346 MapRegisters
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer
, MapSize
);
347 Status
= m_pAdapter
->DmaOperations
->AllocateAdapterChannel(m_pAdapter
, m_pDeviceObject
, MapRegisters
, AdapterControl
, (PVOID
)this);
348 KeLowerIrql(OldIrql
);
350 if(!NT_SUCCESS(Status
))
351 m_LastTransferCount
= 0;
358 CDmaChannelInit::Stop()
362 DPRINT("CDmaChannelInit::Stop: this %p\n", this);
363 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
366 return STATUS_SUCCESS
;
368 m_pAdapter
->DmaOperations
->FlushAdapterBuffers(m_pAdapter
,
371 (PVOID
)((ULONG_PTR
)m_Mdl
->StartVa
+ m_Mdl
->ByteOffset
),
375 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
377 m_pAdapter
->DmaOperations
->FreeAdapterChannel(m_pAdapter
);
379 KeLowerIrql(OldIrql
);
381 m_DmaStarted
= FALSE
;
386 return STATUS_SUCCESS
;
391 CDmaChannelInit::WaitForTC(
395 ULONG BytesRemaining
;
396 ULONG PrevBytesRemaining
;
398 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
400 BytesRemaining
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
403 return STATUS_SUCCESS
;
406 RetryCount
= Timeout
/ 10;
407 PrevBytesRemaining
= 0xFFFFFFFF;
410 BytesRemaining
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
415 if (PrevBytesRemaining
== BytesRemaining
)
418 KeStallExecutionProcessor(10);
419 PrevBytesRemaining
= BytesRemaining
;
421 }while(RetryCount
-- >= 1);
425 return STATUS_UNSUCCESSFUL
;
428 return STATUS_SUCCESS
;
434 CDmaChannelInit::Init(
435 IN PDEVICE_DESCRIPTION DeviceDescription
,
436 IN PDEVICE_OBJECT DeviceObject
)
438 INTERFACE_TYPE BusType
;
440 PDMA_ADAPTER Adapter
;
441 PPCLASS_DEVICE_EXTENSION DeviceExt
;
446 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyLegacyBusType
, sizeof(BusType
), (PVOID
)&BusType
, &ResultLength
);
447 if (NT_SUCCESS(Status
))
449 DeviceDescription
->InterfaceType
= BusType
;
451 // Fetch device extension
452 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
453 // Acquire dma adapter
454 Adapter
= IoGetDmaAdapter(DeviceExt
->PhysicalDeviceObject
, DeviceDescription
, &MapRegisters
);
457 FreeItem(this, TAG_PORTCLASS
);
458 return STATUS_DEVICE_CONFIGURATION_ERROR
;
462 m_pAdapter
= Adapter
;
463 m_pDeviceObject
= DeviceObject
;
464 m_MaximumBufferSize
= DeviceDescription
->MaximumLength
;
465 m_MaxMapRegisters
= MapRegisters
;
467 return STATUS_SUCCESS
;
473 OUT PDMACHANNEL
* OutDmaChannel
,
474 IN PUNKNOWN OuterUnknown OPTIONAL
,
475 IN POOL_TYPE PoolType
,
476 IN PDEVICE_DESCRIPTION DeviceDescription
,
477 IN PDEVICE_OBJECT DeviceObject
)
480 CDmaChannelInit
* This
;
482 DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
483 OutDmaChannel
, OuterUnknown
, PoolType
, DeviceDescription
, DeviceObject
);
485 This
= new(PoolType
, TAG_PORTCLASS
)CDmaChannelInit(OuterUnknown
);
487 return STATUS_INSUFFICIENT_RESOURCES
;
489 Status
= This
->QueryInterface(IID_IDmaChannel
, (PVOID
*)OutDmaChannel
);
491 if (!NT_SUCCESS(Status
))
497 Status
= This
->Init(DeviceDescription
, DeviceObject
);
499 if (!NT_SUCCESS(Status
))