ReactOS  0.4.15-dev-4603-gb922b6d
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 CUnknownImpl<IDmaChannelInit>
18 {
19 public:
20  inline
21  PVOID
22  operator new(
23  size_t Size,
25  ULONG Tag)
26  {
28  }
29 
31 
33  CDmaChannelInit(IUnknown * OuterUnknown) :
34  m_pDeviceObject(nullptr),
35  m_pAdapter(nullptr),
37  m_MapSize(0),
38  m_MapRegisterBase(nullptr),
43  m_BufferSize(0),
44  m_Address({0}),
45  m_Buffer(nullptr),
46  m_Mdl(nullptr),
48  {
49  }
50  virtual ~CDmaChannelInit(){}
51 
52 protected:
53 
56 
58 
61 
63 
68 
73 
75 };
76 
77 
78 
79 //---------------------------------------------------------------
80 // IUnknown methods
81 //
82 
84 
86 NTAPI
88  IN REFIID refiid,
89  OUT PVOID* Output)
90 {
91  if (IsEqualGUIDAligned(refiid, IID_IUnknown) ||
92  IsEqualGUIDAligned(refiid, IID_IDmaChannel))
93  //IsEqualGUIDAligned(refiid, IID_IDmaChannelSlave)) // HACK
94  {
95  *Output = PVOID(PUNKNOWN(this));
96  PUNKNOWN(*Output)->AddRef();
97  return STATUS_SUCCESS;
98  }
99  DPRINT("No interface!!!\n");
100  return STATUS_UNSUCCESSFUL;
101 }
102 
103 //---------------------------------------------------------------
104 // IDmaChannel methods
105 //
106 
107 NTSTATUS
108 NTAPI
109 CDmaChannelInit::AllocateBuffer(
111  IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL)
112 {
114 
115  // Did the caller already allocate a buffer ?*/
116  if (m_Buffer)
117  {
118  DPRINT("CDmaChannelInit_AllocateBuffer free common buffer first \n");
119  return STATUS_UNSUCCESSFUL;
120  }
121 
122  m_Buffer = m_pAdapter->DmaOperations->AllocateCommonBuffer(m_pAdapter, BufferSize, &m_Address, FALSE);
123  if (!m_Buffer)
124  {
125  DPRINT("CDmaChannelInit_AllocateBuffer fAllocateCommonBuffer failed \n");
126  return STATUS_UNSUCCESSFUL;
127  }
128 
131  DPRINT("CDmaChannelInit::AllocateBuffer Success Buffer %p BufferSize %u Address %x\n", m_Buffer, BufferSize, m_Address);
132 
133  return STATUS_SUCCESS;
134 }
135 
136 ULONG
137 NTAPI
138 CDmaChannelInit::AllocatedBufferSize()
139 {
140  DPRINT("CDmaChannelInit_AllocatedBufferSize: this %p BufferSize %u\n", this, m_BufferSize);
141  return m_AllocatedBufferSize;
142 }
143 
144 VOID
145 NTAPI
146 CDmaChannelInit::CopyFrom(
148  IN PVOID Source,
150  )
151 {
152  DPRINT("CDmaChannelInit_CopyFrom: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount);
153 
154  CopyTo(Destination, Source, ByteCount);
155 }
156 
157 VOID
158 NTAPI
159 CDmaChannelInit::CopyTo(
161  IN PVOID Source,
163  )
164 {
165  DPRINT("CDmaChannelInit_CopyTo: this %p Destination %p Source %p ByteCount %u\n", this, Destination, Source, ByteCount);
167 }
168 
169 VOID
170 NTAPI
171 CDmaChannelInit::FreeBuffer()
172 {
173  DPRINT("CDmaChannelInit_FreeBuffer: this %p\n", this);
174 
176 
177  if (!m_Buffer)
178  {
179  DPRINT("CDmaChannelInit_FreeBuffer allocate common buffer first \n");
180  return;
181  }
182 
184  m_Buffer = NULL;
186  m_Address.QuadPart = 0LL;
187 
188  if (m_Mdl)
189  {
190  IoFreeMdl(m_Mdl);
191  m_Mdl = NULL;
192  }
193 }
194 
196 NTAPI
197 CDmaChannelInit::GetAdapterObject()
198 {
199  DPRINT("CDmaChannelInit_GetAdapterObject: this %p\n", this);
200  return (PADAPTER_OBJECT)m_pAdapter;
201 }
202 
203 ULONG
204 NTAPI
205 CDmaChannelInit::MaximumBufferSize()
206 {
207  DPRINT("CDmaChannelInit_MaximumBufferSize: this %p\n", this);
208  return m_MaximumBufferSize;
209 }
210 
211 #ifdef _MSC_VER
212 
214 NTAPI
216 {
217  DPRINT("CDmaChannelInit_PhysicalAddress: this %p Virtual %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart);
218 
219  return m_Address;
220 }
221 
222 #else
223 
225 NTAPI
228 {
229  DPRINT("CDmaChannelInit_PhysicalAddress: this %p Virtual %p Physical High %x Low %x%\n", this, m_Buffer, m_Address.HighPart, m_Address.LowPart);
230 
232 
233  Address->QuadPart = m_Address.QuadPart;
234  Result.QuadPart = (ULONG_PTR)Address;
235  return Result;
236 }
237 
238 
239 #endif
240 
241 VOID
242 NTAPI
243 CDmaChannelInit::SetBufferSize(
245 {
246  DPRINT("CDmaChannelInit_SetBufferSize: this %p\n", this);
248 
249 }
250 
251 ULONG
252 NTAPI
254 {
255  DPRINT("BufferSize %u\n", m_BufferSize);
257  return m_BufferSize;
258 }
259 
260 
261 PVOID
262 NTAPI
263 CDmaChannelInit::SystemAddress()
264 {
265  DPRINT("CDmaChannelInit_SystemAddress: this %p\n", this);
266  return m_Buffer;
267 }
268 
269 ULONG
270 NTAPI
271 CDmaChannelInit::TransferCount()
272 {
273  DPRINT("CDmaChannelInit_TransferCount: this %p\n", this);
274  return m_LastTransferCount;
275 }
276 
277 ULONG
278 NTAPI
279 CDmaChannelInit::ReadCounter()
280 {
281  ULONG Counter;
282 
284 
285  Counter = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
286 
288  Counter = 0;
289 
290  DPRINT("ReadCounter %u\n", Counter);
291 
292  return Counter;
293 }
294 
296 NTAPI
299  IN PIRP Irp,
301  IN PVOID Context)
302 {
303  ULONG Length;
305 
306  Length = This->m_MapSize;
307  This->m_MapRegisterBase = MapRegisterBase;
308 
309  This->m_pAdapter->DmaOperations->MapTransfer(This->m_pAdapter,
310  This->m_Mdl,
312  (PVOID)((ULONG_PTR)This->m_Mdl->StartVa + This->m_Mdl->ByteOffset),
313  &Length,
314  This->m_WriteToDevice);
315 
316  if (Length == This->m_BufferSize)
317  {
318  This->m_DmaStarted = TRUE;
319  }
320 
321  return KeepObject;
322 }
323 
324 NTSTATUS
325 NTAPI
327  ULONG MapSize,
329 {
331  ULONG MapRegisters;
332  KIRQL OldIrql;
333 
334  DPRINT("CDmaChannelInit_Start: this %p\n", this);
335 
337 
338  if (m_DmaStarted)
339  return STATUS_UNSUCCESSFUL;
340 
341  if (!m_Mdl)
342  {
344  if (!m_Mdl)
345  {
347  }
349  }
350 
351  m_MapSize = MapSize;
353  m_LastTransferCount = MapSize;
354 
355  //FIXME
356  // synchronize access
357  //
359 
360  MapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(m_Buffer, MapSize);
361  Status = m_pAdapter->DmaOperations->AllocateAdapterChannel(m_pAdapter, m_pDeviceObject, MapRegisters, AdapterControl, (PVOID)this);
363 
364  if(!NT_SUCCESS(Status))
366 
367  return Status;
368 }
369 
370 NTSTATUS
371 NTAPI
373 {
374  KIRQL OldIrql;
375 
376  DPRINT("CDmaChannelInit::Stop: this %p\n", this);
378 
379  if (!m_DmaStarted)
380  return STATUS_SUCCESS;
381 
382  m_pAdapter->DmaOperations->FlushAdapterBuffers(m_pAdapter,
383  m_Mdl,
385  (PVOID)((ULONG_PTR)m_Mdl->StartVa + m_Mdl->ByteOffset),
386  m_MapSize,
388 
390 
391  m_pAdapter->DmaOperations->FreeAdapterChannel(m_pAdapter);
392 
394 
396 
397  IoFreeMdl(m_Mdl);
398  m_Mdl = NULL;
399 
400  return STATUS_SUCCESS;
401 }
402 
403 NTSTATUS
404 NTAPI
405 CDmaChannelInit::WaitForTC(
406  ULONG Timeout)
407 {
408  ULONG RetryCount;
409  ULONG BytesRemaining;
410  ULONG PrevBytesRemaining;
411 
413 
414  BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
415  if (!BytesRemaining)
416  {
417  return STATUS_SUCCESS;
418  }
419 
420  RetryCount = Timeout / 10;
421  PrevBytesRemaining = 0xFFFFFFFF;
422  do
423  {
424  BytesRemaining = m_pAdapter->DmaOperations->ReadDmaCounter(m_pAdapter);
425 
426  if (!BytesRemaining)
427  break;
428 
429  if (PrevBytesRemaining == BytesRemaining)
430  break;
431 
433  PrevBytesRemaining = BytesRemaining;
434 
435  }while(RetryCount-- >= 1);
436 
437  if (BytesRemaining)
438  {
439  return STATUS_UNSUCCESSFUL;
440  }
441 
442  return STATUS_SUCCESS;
443 
444 }
445 
446 NTSTATUS
447 NTAPI
451 {
454  PDMA_ADAPTER Adapter;
455  PPCLASS_DEVICE_EXTENSION DeviceExt;
456  ULONG MapRegisters;
458 
459  // Get bus type
461  if (NT_SUCCESS(Status))
462  {
463  DeviceDescription->InterfaceType = BusType;
464  }
465  // Fetch device extension
466  DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
467  // Acquire dma adapter
468  Adapter = IoGetDmaAdapter(DeviceExt->PhysicalDeviceObject, DeviceDescription, &MapRegisters);
469  if (!Adapter)
470  {
471  FreeItem(this, TAG_PORTCLASS);
473  }
474 
475  // initialize object
476  m_pAdapter = Adapter;
478  m_MaximumBufferSize = DeviceDescription->MaximumLength;
479  m_MaxMapRegisters = MapRegisters;
480 
481  return STATUS_SUCCESS;
482 }
483 
484 NTSTATUS
485 NTAPI
487  OUT PDMACHANNEL* OutDmaChannel,
488  IN PUNKNOWN OuterUnknown OPTIONAL,
492 {
495 
496  DPRINT("OutDmaChannel %p OuterUnknown %p PoolType %p DeviceDescription %p DeviceObject %p\n",
497  OutDmaChannel, OuterUnknown, PoolType, DeviceDescription, DeviceObject);
498 
499  This = new(PoolType, TAG_PORTCLASS)CDmaChannelInit(OuterUnknown);
500  if (!This)
502 
503  Status = This->QueryInterface(IID_IDmaChannel, (PVOID*)OutDmaChannel);
504 
505  if (!NT_SUCCESS(Status))
506  {
507  delete This;
508  return Status;
509  }
510 
512 
513  if (!NT_SUCCESS(Status))
514  {
515  delete This;
516  return Status;
517  }
518 
519  return Status;
520 }
ULONG m_MaxMapRegisters
Definition: dma_slave.cpp:65
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
#define IN
Definition: typedefs.h:39
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
Definition: dma_slave.cpp:87
IDmaChannel * PDMACHANNEL
Definition: portcls.h:782
#define REFIID
Definition: guiddef.h:118
#define LL
Definition: tui.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
IO_ALLOCATION_ACTION NTAPI AdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma_slave.cpp:297
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
enum _INTERFACE_TYPE INTERFACE_TYPE
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
#define TRUE
Definition: types.h:120
IUnknown * PUNKNOWN
Definition: com_apitest.h:45
#define TAG_PORTCLASS
Definition: private.hpp:24
PDEVICE_OBJECT m_pDeviceObject
Definition: dma_slave.cpp:54
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:420
LONG NTSTATUS
Definition: precomp.h:26
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
BOOL Init(PUSERCONNECT UserCon)
Definition: dllmain.c:385
ULONG m_MaximumBufferSize
Definition: dma_slave.cpp:64
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2295
PVOID m_MapRegisterBase
Definition: dma_slave.cpp:60
_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:235
uint32_t ULONG_PTR
Definition: typedefs.h:65
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
VOID FreeItem(IN PVOID Item)
Definition: misc.c:43
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceDescription
Definition: wdfpdo.h:430
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
unsigned int BOOL
Definition: ntddk_ex.h:94
#define STDMETHODIMP
Definition: basetyps.h:43
unsigned char BOOLEAN
static WCHAR Address[46]
Definition: ping.c:68
_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:1952
void * PVOID
Definition: retypes.h:9
GUID IID_IDmaChannelSlave
BOOLEAN m_WriteToDevice
Definition: dma_slave.cpp:72
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
Status
Definition: gdiplustypes.h:24
PDMA_ADAPTER m_pAdapter
Definition: dma_slave.cpp:55
friend IO_ALLOCATION_ACTION NTAPI AdapterControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: dma_slave.cpp:297
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
INT POOL_TYPE
Definition: typedefs.h:78
PDEVICE_OBJECT PhysicalDeviceObject
Definition: private.hpp:402
const GUID IID_IUnknown
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2950
#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:1098
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
Definition: arc.h:85
virtual ~CDmaChannelInit()
Definition: dma_slave.cpp:50
ULONG LowPart
Definition: typedefs.h:106
PHYSICAL_ADDRESS m_Address
Definition: dma_slave.cpp:69
ULONG m_AllocatedBufferSize
Definition: dma_slave.cpp:66
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4061
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1098
ULONG m_LastTransferCount
Definition: dma_slave.cpp:62
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:989
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
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:486
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:212
static ULONG Timeout
Definition: ping.c:61
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:361
#define NULL
Definition: types.h:112
VOID NTAPI KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
Definition: spinlock.c:27
ULONG m_BufferSize
Definition: dma_slave.cpp:67
static LARGE_INTEGER Counter
Definition: clock.c:43
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3810
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:619
CDmaChannelInit(IUnknown *OuterUnknown)
Definition: dma_slave.cpp:33
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
#define PC_ASSERT_IRQL(x)
Definition: private.hpp:30
#define BufferSize
Definition: mmc.h:75
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
LONGLONG QuadPart
Definition: typedefs.h:114
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68