ReactOS  0.4.15-dev-321-g2d9b385
dma_slave.cpp
Go to the documentation of this file.
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.hpp"
10 
11 #ifndef YDEBUG
12 #define NDEBUG
13 #endif
14 
15 #include <debug.h>
16 
17 class CDmaChannelInit : public IDmaChannelInit
18 {
19 public:
20  inline
21  PVOID
22  operator new(
23  size_t Size,
25  ULONG Tag)
26  {
28  if (P)
30  return P;
31  }
32 
34 
36  {
38  return m_Ref;
39  }
41  {
43 
44  if (!m_Ref)
45  {
46  delete this;
47  return 0;
48  }
49  return m_Ref;
50  }
52  CDmaChannelInit(IUnknown * OuterUnknown){}
53  virtual ~CDmaChannelInit(){}
54 
55 protected:
56 
59 
61 
64 
66 
71 
76 
78 
80 };
81 
82 
83 
84 //---------------------------------------------------------------
85 // IUnknown methods
86 //
87 
89 
91 NTAPI
93  IN REFIID refiid,
94  OUT PVOID* Output)
95 {
96  if (IsEqualGUIDAligned(refiid, IID_IUnknown) ||
97  IsEqualGUIDAligned(refiid, IID_IDmaChannel))
98  //IsEqualGUIDAligned(refiid, IID_IDmaChannelSlave)) // HACK
99  {
100  *Output = PVOID(PUNKNOWN(this));
101  PUNKNOWN(*Output)->AddRef();
102  return STATUS_SUCCESS;
103  }
104  DPRINT("No interface!!!\n");
105  return STATUS_UNSUCCESSFUL;
106 }
107 
108 //---------------------------------------------------------------
109 // IDmaChannel methods
110 //
111 
112 NTSTATUS
113 NTAPI
114 CDmaChannelInit::AllocateBuffer(
116  IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL)
117 {
119 
120  // Did the caller already allocate a buffer ?*/
121  if (m_Buffer)
122  {
123  DPRINT("CDmaChannelInit_AllocateBuffer free common buffer first \n");
124  return STATUS_UNSUCCESSFUL;
125  }
126 
127  m_Buffer = m_pAdapter->DmaOperations->AllocateCommonBuffer(m_pAdapter, BufferSize, &m_Address, FALSE);
128  if (!m_Buffer)
129  {
130  DPRINT("CDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
131  return STATUS_UNSUCCESSFUL;
132  }
133 
136  DPRINT("CDmaChannelInit::AllocateBuffer Success Buffer %p BufferSize %u Address %x\n", m_Buffer, BufferSize, m_Address);
137 
138  return STATUS_SUCCESS;
139 }
140 
141 ULONG
142 NTAPI
143 CDmaChannelInit::AllocatedBufferSize()
144 {
145  DPRINT("CDmaChannelInit_AllocatedBufferSize: this %p BufferSize %u\n", this, m_BufferSize);
146  return m_AllocatedBufferSize;
147 }
148 
149 VOID
150 NTAPI
151 CDmaChannelInit::CopyFrom(
153  IN PVOID Source,
155  )
156 {
157  DPRINT("CDmaChannelInit_CopyFrom: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount);
158 
159  CopyTo(Destination, Source, ByteCount);
160 }
161 
162 VOID
163 NTAPI
164 CDmaChannelInit::CopyTo(
166  IN PVOID Source,
168  )
169 {
170  DPRINT("CDmaChannelInit_CopyTo: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount);
172 }
173 
174 VOID
175 NTAPI
176 CDmaChannelInit::FreeBuffer()
177 {
178  DPRINT("CDmaChannelInit_FreeBuffer: this %p\n", this);
179 
181 
182  if (!m_Buffer)
183  {
184  DPRINT("CDmaChannelInit_FreeBuffer allocate common buffer first \n");
185  return;
186  }
187 
189  m_Buffer = NULL;
191  m_Address.QuadPart = 0LL;
192 
193  if (m_Mdl)
194  {
195  IoFreeMdl(m_Mdl);
196  m_Mdl = NULL;
197  }
198 }
199 
201 NTAPI
202 CDmaChannelInit::GetAdapterObject()
203 {
204  DPRINT("CDmaChannelInit_GetAdapterObject: this %p\n", this);
205  return (PADAPTER_OBJECT)m_pAdapter;
206 }
207 
208 ULONG
209 NTAPI
210 CDmaChannelInit::MaximumBufferSize()
211 {
212  DPRINT("CDmaChannelInit_MaximumBufferSize: this %p\n", this);
213  return m_MaximumBufferSize;
214 }
215 
216 #ifdef _MSC_VER
217 
219 NTAPI
221 {
222  DPRINT("CDmaChannelInit_PhysicalAddress: this %p Virtual %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart);
223 
224  return m_Address;
225 }
226 
227 #else
228 
230 NTAPI
233 {
234  DPRINT("CDmaChannelInit_PhysicalAddress: this %p Virtual %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart);
235 
237 
238  Address->QuadPart = m_Address.QuadPart;
239  Result.QuadPart = (ULONG_PTR)Address;
240  return Result;
241 }
242 
243 
244 #endif
245 
246 VOID
247 NTAPI
248 CDmaChannelInit::SetBufferSize(
250 {
251  DPRINT("CDmaChannelInit_SetBufferSize: this %p\n", this);
253 
254 }
255 
256 ULONG
257 NTAPI
259 {
260  DPRINT("BufferSize %u\n", m_BufferSize);
262  return m_BufferSize;
263 }
264 
265 
266 PVOID
267 NTAPI
268 CDmaChannelInit::SystemAddress()
269 {
270  DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this);
271  return m_Buffer;
272 }
273 
274 ULONG
275 NTAPI
276 CDmaChannelInit::TransferCount()
277 {
278  DPRINT("CDmaChannelInit_TransferCount: this %p\n", this);
279  return m_LastTransferCount;
280 }
281 
282 ULONG
283 NTAPI
284 CDmaChannelInit::ReadCounter()
285 {
286  ULONG Counter;
287 
289 
290  Counter = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
291 
293  Counter = 0;
294 
295  DPRINT("ReadCounter %u\n", Counter);
296 
297  return Counter;
298 }
299 
301 NTAPI
304  IN PIRP Irp,
306  IN PVOID Context)
307 {
308  ULONG Length;
310 
311  Length = This->m_MapSize;
312  This->m_MapRegisterBase = MapRegisterBase;
313 
314  This->m_pAdapter->DmaOperations->MapTransfer(This->m_pAdapter,
315  This->m_Mdl,
317  (PVOID)((ULONG_PTR)This->m_Mdl->StartVa + This->m_Mdl->ByteOffset),
318  &Length,
319  This->m_WriteToDevice);
320 
321  if (Length == This->m_BufferSize)
322  {
323  This->m_DmaStarted = TRUE;
324  }
325 
326  return KeepObject;
327 }
328 
329 NTSTATUS
330 NTAPI
332  ULONG MapSize,
333  BOOLEAN WriteToDevice)
334 {
336  ULONG MapRegisters;
337  KIRQL OldIrql;
338 
339  DPRINT("CDmaChannelInit_Start: this %p\n", this);
340 
342 
343  if (m_DmaStarted)
344  return STATUS_UNSUCCESSFUL;
345 
346  if (!m_Mdl)
347  {
349  if (!m_Mdl)
350  {
352  }
354  }
355 
356  m_MapSize = MapSize;
357  m_WriteToDevice = WriteToDevice;
358  m_LastTransferCount = MapSize;
359 
360  //FIXME
361  // synchronize access
362  //
364 
365  MapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer, MapSize);
366  Status = m_pAdapter->DmaOperations->AllocateAdapterChannel(m_pAdapter, m_pDeviceObject, MapRegisters, AdapterControl, (PVOID)this);
368 
369  if(!NT_SUCCESS(Status))
371 
372  return Status;
373 }
374 
375 NTSTATUS
376 NTAPI
378 {
379  KIRQL OldIrql;
380 
381  DPRINT("CDmaChannelInit::Stop: this %p\n", this);
383 
384  if (!m_DmaStarted)
385  return STATUS_SUCCESS;
386 
387  m_pAdapter->DmaOperations->FlushAdapterBuffers(m_pAdapter,
388  m_Mdl,
390  (PVOID)((ULONG_PTR)m_Mdl->StartVa + m_Mdl->ByteOffset),
391  m_MapSize,
393 
395 
396  m_pAdapter->DmaOperations->FreeAdapterChannel(m_pAdapter);
397 
399 
401 
402  IoFreeMdl(m_Mdl);
403  m_Mdl = NULL;
404 
405  return STATUS_SUCCESS;
406 }
407 
408 NTSTATUS
409 NTAPI
410 CDmaChannelInit::WaitForTC(
411  ULONG Timeout)
412 {
413  ULONG RetryCount;
414  ULONG BytesRemaining;
415  ULONG PrevBytesRemaining;
416 
418 
419  BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
420  if (!BytesRemaining)
421  {
422  return STATUS_SUCCESS;
423  }
424 
425  RetryCount = Timeout / 10;
426  PrevBytesRemaining = 0xFFFFFFFF;
427  do
428  {
429  BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
430 
431  if (!BytesRemaining)
432  break;
433 
434  if (PrevBytesRemaining == BytesRemaining)
435  break;
436 
438  PrevBytesRemaining = BytesRemaining;
439 
440  }while(RetryCount-- >= 1);
441 
442  if (BytesRemaining)
443  {
444  return STATUS_UNSUCCESSFUL;
445  }
446 
447  return STATUS_SUCCESS;
448 
449 }
450 
451 NTSTATUS
452 NTAPI
456 {
459  PDMA_ADAPTER Adapter;
460  PPCLASS_DEVICE_EXTENSION DeviceExt;
461  ULONG MapRegisters;
463 
464  // Get bus type
466  if (NT_SUCCESS(Status))
467  {
469  }
470  // Fetch device extension
472  // Acquire dma adapter
473  Adapter = IoGetDmaAdapter(DeviceExt->PhysicalDeviceObject, DeviceDescription, &MapRegisters);
474  if (!Adapter)
475  {
476  FreeItem(this, TAG_PORTCLASS);
478  }
479 
480  // initialize object
481  m_pAdapter = Adapter;
484  m_MaxMapRegisters = MapRegisters;
485 
486  return STATUS_SUCCESS;
487 }
488 
489 NTSTATUS
490 NTAPI
492  OUT PDMACHANNEL* OutDmaChannel,
493  IN PUNKNOWN OuterUnknown OPTIONAL,
497 {
500 
501  DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
502  OutDmaChannel, OuterUnknown, PoolType, DeviceDescription, DeviceObject);
503 
504  This = new(PoolType, TAG_PORTCLASS)CDmaChannelInit(OuterUnknown);
505  if (!This)
507 
508  Status = This->QueryInterface(IID_IDmaChannel, (PVOID*)OutDmaChannel);
509 
510  if (!NT_SUCCESS(Status))
511  {
512  delete This;
513  return Status;
514  }
515 
517 
518  if (!NT_SUCCESS(Status))
519  {
520  delete This;
521  return Status;
522  }
523 
524  return Status;
525 }
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
ULONG m_MaxMapRegisters
Definition: dma_slave.cpp:68
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
#define IN
Definition: typedefs.h:39
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
Definition: dma_slave.cpp:92
IDmaChannel * PDMACHANNEL
Definition: portcls.h:772
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define LL
Definition: tui.h:84
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
IO_ALLOCATION_ACTION NTAPI AdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma_slave.cpp:302
enum _INTERFACE_TYPE INTERFACE_TYPE
_In_ BOOLEAN Release
Definition: classpnp.h:929
PDMA_ADAPTER NTAPI IoGetDmaAdapter(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PDEVICE_DESCRIPTION DeviceDescription, IN OUT PULONG NumberOfMapRegisters)
Definition: pnpdma.c:23
_In_opt_ PUNICODE_STRING _In_ PDRIVER_OBJECT _In_ PDEVICE_OBJECT _In_ INTERFACE_TYPE BusType
Definition: halfuncs.h:156
struct PCLASS_DEVICE_EXTENSION * PPCLASS_DEVICE_EXTENSION
_In_ PIRP Irp
Definition: csq.h:116
IUnknown * PUNKNOWN
Definition: com_apitest.h:45
#define TAG_PORTCLASS
Definition: private.hpp:24
PDEVICE_OBJECT m_pDeviceObject
Definition: dma_slave.cpp:57
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
LONG NTSTATUS
Definition: precomp.h:26
BOOL Init(PUSERCONNECT UserCon)
Definition: dllmain.c:385
ULONG m_MaximumBufferSize
Definition: dma_slave.cpp:67
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2187
PVOID m_MapRegisterBase
Definition: dma_slave.cpp:63
_In_ PVOID _Out_ BOOLEAN * Stop
Definition: ldrtypes.h:241
#define PC_ASSERT(exp)
Definition: private.hpp:26
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:233
uint32_t ULONG_PTR
Definition: typedefs.h:64
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID FreeItem(IN PVOID Item)
Definition: misc.c:43
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define STDMETHODIMP
Definition: basetyps.h:43
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
STDMETHODIMP_(ULONG) Release()
Definition: dma_slave.cpp:40
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
NTSTATUS NTAPI IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_REGISTRY_PROPERTY DeviceProperty, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength)
Definition: pnpmgr.c:4300
void DPRINT(...)
Definition: polytest.cpp:61
void * PVOID
Definition: retypes.h:9
GUID IID_IDmaChannelSlave
BOOLEAN m_WriteToDevice
Definition: dma_slave.cpp:75
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
PDMA_ADAPTER m_pAdapter
Definition: dma_slave.cpp:58
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:361
friend IO_ALLOCATION_ACTION NTAPI AdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma_slave.cpp:302
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
INT POOL_TYPE
Definition: typedefs.h:77
PDEVICE_OBJECT PhysicalDeviceObject
Definition: private.hpp:402
const GUID IID_IUnknown
#define BufferSize
Definition: classpnp.h:419
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2937
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define PC_ASSERT_IRQL_EQUAL(x)
Definition: private.hpp:31
Definition: partlist.h:33
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
ULONG AddRef()
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
#define InterlockedDecrement
Definition: armddk.h:52
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
Definition: arc.h:85
virtual ~CDmaChannelInit()
Definition: dma_slave.cpp:53
ULONG LowPart
Definition: typedefs.h:105
PHYSICAL_ADDRESS m_Address
Definition: dma_slave.cpp:72
ULONG m_AllocatedBufferSize
Definition: dma_slave.cpp:69
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define P(row, col)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1061
ULONG m_LastTransferCount
Definition: dma_slave.cpp:65
Status
Definition: gdiplustypes.h:24
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
NTSTATUS NTAPI PcNewDmaChannel(OUT PDMACHANNEL *OutDmaChannel, IN PUNKNOWN OuterUnknown OPTIONAL, IN POOL_TYPE PoolType, IN PDEVICE_DESCRIPTION DeviceDescription, IN PDEVICE_OBJECT DeviceObject)
Definition: dma_slave.cpp:491
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:189
static ULONG Timeout
Definition: ping.c:61
#define InterlockedIncrement
Definition: armddk.h:53
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
ULONG m_BufferSize
Definition: dma_slave.cpp:70
static LARGE_INTEGER Counter
Definition: clock.c:43
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
STDMETHODIMP_(ULONG) AddRef()
Definition: dma_slave.cpp:35
#define OUT
Definition: typedefs.h:40
INTERFACE_TYPE InterfaceType
Definition: iotypes.h:2036
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:605
CDmaChannelInit(IUnknown *OuterUnknown)
Definition: dma_slave.cpp:52
return STATUS_SUCCESS
Definition: btrfs.c:3014
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T _In_ POOL_TYPE PoolType
Definition: fltkernel.h:1444
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:95
#define PC_ASSERT_IRQL(x)
Definition: private.hpp:30
LONGLONG QuadPart
Definition: typedefs.h:113
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68