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 DPRINT1("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 DPRINT1("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 DPRINT1("CDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
112 return STATUS_UNSUCCESSFUL
;
115 m_BufferSize
= BufferSize
;
116 m_AllocatedBufferSize
= BufferSize
;
117 DPRINT1("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 DPRINT1("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()
231 CDmaChannelInit::SystemAddress()
233 DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this);
239 CDmaChannelInit::TransferCount()
241 DPRINT("CDmaChannelInit_TransferCount: this %p\n", this);
242 return m_LastTransferCount
;
247 CDmaChannelInit::ReadCounter()
251 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
253 Counter
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
255 if (!m_DmaStarted
|| Counter
>= m_LastTransferCount
)
264 IN PDEVICE_OBJECT DeviceObject
,
266 IN PVOID MapRegisterBase
,
270 CDmaChannelInit
* This
= (CDmaChannelInit
*)Context
;
272 Length
= This
->m_MapSize
;
273 This
->m_MapRegisterBase
= MapRegisterBase
;
275 This
->m_pAdapter
->DmaOperations
->MapTransfer(This
->m_pAdapter
,
278 (PVOID
)((ULONG_PTR
)This
->m_Mdl
->StartVa
+ This
->m_Mdl
->ByteOffset
),
280 This
->m_WriteToDevice
);
282 if (Length
== This
->m_BufferSize
)
284 This
->m_DmaStarted
= TRUE
;
292 CDmaChannelInit::Start(
294 BOOLEAN WriteToDevice
)
300 DPRINT("CDmaChannelInit_Start: this %p\n", this);
302 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
305 return STATUS_UNSUCCESSFUL
;
309 m_Mdl
= IoAllocateMdl(m_Buffer
, m_MaximumBufferSize
, FALSE
, FALSE
, NULL
);
312 return STATUS_INSUFFICIENT_RESOURCES
;
314 MmBuildMdlForNonPagedPool(m_Mdl
);
318 m_WriteToDevice
= WriteToDevice
;
319 m_LastTransferCount
= MapSize
;
322 // synchronize access
324 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
326 MapRegisters
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer
, MapSize
);
327 Status
= m_pAdapter
->DmaOperations
->AllocateAdapterChannel(m_pAdapter
, m_pDeviceObject
, MapRegisters
, AdapterControl
, (PVOID
)this);
328 KeLowerIrql(OldIrql
);
330 if(!NT_SUCCESS(Status
))
331 m_LastTransferCount
= 0;
338 CDmaChannelInit::Stop()
342 DPRINT("CDmaChannelInit::Stop: this %p\n", this);
343 PC_ASSERT_IRQL(DISPATCH_LEVEL
);
346 return STATUS_SUCCESS
;
348 m_pAdapter
->DmaOperations
->FlushAdapterBuffers(m_pAdapter
,
351 (PVOID
)((ULONG_PTR
)m_Mdl
->StartVa
+ m_Mdl
->ByteOffset
),
355 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
357 m_pAdapter
->DmaOperations
->FreeAdapterChannel(m_pAdapter
);
359 KeLowerIrql(OldIrql
);
361 m_DmaStarted
= FALSE
;
366 return STATUS_SUCCESS
;
371 CDmaChannelInit::WaitForTC(
375 ULONG BytesRemaining
;
376 ULONG PrevBytesRemaining
;
378 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
380 BytesRemaining
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
383 return STATUS_SUCCESS
;
386 RetryCount
= Timeout
/ 10;
387 PrevBytesRemaining
= 0xFFFFFFFF;
390 BytesRemaining
= m_pAdapter
->DmaOperations
->ReadDmaCounter(m_pAdapter
);
395 if (PrevBytesRemaining
== BytesRemaining
)
398 KeStallExecutionProcessor(10);
399 PrevBytesRemaining
= BytesRemaining
;
401 }while(RetryCount
-- >= 1);
405 return STATUS_UNSUCCESSFUL
;
408 return STATUS_SUCCESS
;
414 CDmaChannelInit::Init(
415 IN PDEVICE_DESCRIPTION DeviceDescription
,
416 IN PDEVICE_OBJECT DeviceObject
)
418 INTERFACE_TYPE BusType
;
420 PDMA_ADAPTER Adapter
;
421 PPCLASS_DEVICE_EXTENSION DeviceExt
;
426 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyLegacyBusType
, sizeof(BusType
), (PVOID
)&BusType
, &ResultLength
);
427 if (NT_SUCCESS(Status
))
429 DeviceDescription
->InterfaceType
= BusType
;
431 // Fetch device extension
432 DeviceExt
= (PPCLASS_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
433 // Acquire dma adapter
434 Adapter
= IoGetDmaAdapter(DeviceExt
->PhysicalDeviceObject
, DeviceDescription
, &MapRegisters
);
437 FreeItem(this, TAG_PORTCLASS
);
438 return STATUS_DEVICE_CONFIGURATION_ERROR
;
442 m_pAdapter
= Adapter
;
443 m_pDeviceObject
= DeviceObject
;
444 m_MaximumBufferSize
= DeviceDescription
->MaximumLength
;
445 m_MaxMapRegisters
= MapRegisters
;
447 return STATUS_SUCCESS
;
453 OUT PDMACHANNEL
* OutDmaChannel
,
454 IN PUNKNOWN OuterUnknown OPTIONAL
,
455 IN POOL_TYPE PoolType
,
456 IN PDEVICE_DESCRIPTION DeviceDescription
,
457 IN PDEVICE_OBJECT DeviceObject
)
460 CDmaChannelInit
* This
;
462 DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
463 OutDmaChannel
, OuterUnknown
, PoolType
, DeviceDescription
, DeviceObject
);
465 This
= new(PoolType
, TAG_PORTCLASS
)CDmaChannelInit(OuterUnknown
);
467 return STATUS_INSUFFICIENT_RESOURCES
;
469 Status
= This
->QueryInterface(IID_IDmaChannel
, (PVOID
*)OutDmaChannel
);
471 if (!NT_SUCCESS(Status
))
477 Status
= This
->Init(DeviceDescription
, DeviceObject
);
479 if (!NT_SUCCESS(Status
))