[CMAKE]
[reactos.git] / drivers / wdm / audio / backpln / portcls / port_wavepci.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/port_wavepci.cpp
5 * PURPOSE: Wave PCI Port driver
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortWavePci : public IPortWavePci,
12 public IPortEvents,
13 public ISubdevice,
14 public IServiceSink
15 {
16 public:
17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18
19 STDMETHODIMP_(ULONG) AddRef()
20 {
21 InterlockedIncrement(&m_Ref);
22 return m_Ref;
23 }
24 STDMETHODIMP_(ULONG) Release()
25 {
26 InterlockedDecrement(&m_Ref);
27
28 if (!m_Ref)
29 {
30 delete this;
31 return 0;
32 }
33 return m_Ref;
34 }
35 IMP_IPortWavePci;
36 IMP_ISubdevice;
37 IMP_IPortEvents;
38 IMP_IServiceSink;
39 CPortWavePci(IUnknown *OuterUnknown){}
40 virtual ~CPortWavePci() {}
41
42 protected:
43
44 PMINIPORTWAVEPCI m_Miniport;
45 PDEVICE_OBJECT m_pDeviceObject;
46 PSERVICEGROUP m_ServiceGroup;
47 PPINCOUNT m_pPinCount;
48 PPOWERNOTIFY m_pPowerNotify;
49 PPCFILTER_DESCRIPTOR m_pDescriptor;
50 PSUBDEVICE_DESCRIPTOR m_SubDeviceDescriptor;
51 IPortFilterWavePci * m_Filter;
52
53 LIST_ENTRY m_EventList;
54 KSPIN_LOCK m_EventListLock;
55
56 LONG m_Ref;
57
58 friend PDEVICE_OBJECT GetDeviceObjectFromPortWavePci(IPortWavePci* iface);
59 friend PMINIPORTWAVEPCI GetWavePciMiniport(PPORTWAVEPCI iface);
60
61 };
62
63 static GUID InterfaceGuids[3] =
64 {
65 {
66 /// KS_CATEGORY_AUDIO
67 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
68 },
69 {
70 /// KSCATEGORY_RENDER
71 0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
72 },
73 {
74 /// KSCATEGORY_CAPTURE
75 0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
76 }
77 };
78
79 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWavePciTopologySet, TopologyPropertyHandler);
80 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWavePciPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
81
82 KSPROPERTY_SET WavePciPropertySet[] =
83 {
84 {
85 &KSPROPSETID_Topology,
86 sizeof(PortFilterWavePciTopologySet) / sizeof(KSPROPERTY_ITEM),
87 (const KSPROPERTY_ITEM*)&PortFilterWavePciTopologySet,
88 0,
89 NULL
90 },
91 {
92 &KSPROPSETID_Pin,
93 sizeof(PortFilterWavePciPinSet) / sizeof(KSPROPERTY_ITEM),
94 (const KSPROPERTY_ITEM*)&PortFilterWavePciPinSet,
95 0,
96 NULL
97 }
98 };
99
100
101 //---------------------------------------------------------------
102 // IPortEvents
103 //
104
105 void
106 NTAPI
107 CPortWavePci::AddEventToEventList(
108 IN PKSEVENT_ENTRY EventEntry)
109 {
110 KIRQL OldIrql;
111
112 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
113
114 KeAcquireSpinLock(&m_EventListLock, &OldIrql);
115 InsertTailList(&m_EventList, &EventEntry->ListEntry);
116 KeReleaseSpinLock(&m_EventListLock, OldIrql);
117 }
118
119
120
121 void
122 NTAPI
123 CPortWavePci::GenerateEventList(
124 IN GUID* Set OPTIONAL,
125 IN ULONG EventId,
126 IN BOOL PinEvent,
127 IN ULONG PinId,
128 IN BOOL NodeEvent,
129 IN ULONG NodeId)
130 {
131 UNIMPLEMENTED
132 }
133 //---------------------------------------------------------------
134 // IServiceSink
135 //
136
137 VOID
138 NTAPI
139 CPortWavePci::RequestService()
140 {
141 //DPRINT("IServiceSink_fnRequestService entered\n");
142 if (m_Miniport)
143 {
144 m_Miniport->Service();
145 }
146 }
147
148 //---------------------------------------------------------------
149 // IPortWavePci
150 //
151
152 NTSTATUS
153 NTAPI
154 CPortWavePci::QueryInterface(
155 IN REFIID refiid,
156 OUT PVOID* Output)
157 {
158 UNICODE_STRING GuidString;
159
160 DPRINT("IPortWavePci_fnQueryInterface entered\n");
161
162 if (IsEqualGUIDAligned(refiid, IID_IPortWavePci) ||
163 IsEqualGUIDAligned(refiid, IID_IUnknown) ||
164 IsEqualGUIDAligned(refiid, IID_IPort))
165 {
166 *Output = PVOID(PPORTWAVEPCI(this));
167 PUNKNOWN(*Output)->AddRef();
168 return STATUS_SUCCESS;
169 }
170 else if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
171 {
172 *Output = PVOID(PSERVICESINK(this));
173 PUNKNOWN(*Output)->AddRef();
174 return STATUS_SUCCESS;
175 }
176 else if (IsEqualGUIDAligned(refiid, IID_IPortEvents))
177 {
178 *Output = PVOID(PPORTEVENTS(this));
179 PUNKNOWN(*Output)->AddRef();
180 return STATUS_SUCCESS;
181 }
182 else if (IsEqualGUIDAligned(refiid, IID_ISubdevice))
183 {
184 *Output = PVOID(PSUBDEVICE(this));
185 PUNKNOWN(*Output)->AddRef();
186 return STATUS_SUCCESS;
187 }
188 else if (IsEqualGUIDAligned(refiid, IID_IDrmPort) ||
189 IsEqualGUIDAligned(refiid, IID_IDrmPort2))
190 {
191 return NewIDrmPort((PDRMPORT2*)Output);
192 }
193 else if (IsEqualGUIDAligned(refiid, IID_IPortClsVersion))
194 {
195 return NewPortClsVersion((PPORTCLSVERSION*)Output);
196 }
197 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
198 {
199 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
200 }
201 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
202 {
203 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
204 }
205
206 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
207 {
208 DPRINT("IPortWavePci_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
209 RtlFreeUnicodeString(&GuidString);
210 }
211
212 return STATUS_UNSUCCESSFUL;
213 }
214
215 NTSTATUS
216 NTAPI
217 CPortWavePci::Init(
218 IN PDEVICE_OBJECT DeviceObject,
219 IN PIRP Irp,
220 IN PUNKNOWN UnknownMiniport,
221 IN PUNKNOWN UnknownAdapter OPTIONAL,
222 IN PRESOURCELIST ResourceList)
223 {
224 IMiniportWavePci * Miniport;
225 PSERVICEGROUP ServiceGroup;
226 NTSTATUS Status;
227 PPINCOUNT PinCount;
228 PPOWERNOTIFY PowerNotify;
229
230 DPRINT("IPortWavePci_fnInit entered with This %p, DeviceObject %p Irp %p UnknownMiniport %p, UnknownAdapter %p ResourceList %p\n",
231 this, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
232 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
233
234 Status = UnknownMiniport->QueryInterface(IID_IMiniportWavePci, (PVOID*)&Miniport);
235 if (!NT_SUCCESS(Status))
236 {
237 DPRINT("IPortWavePci_fnInit called with invalid IMiniport adapter\n");
238 return STATUS_INVALID_PARAMETER;
239 }
240
241 // Initialize port object
242 m_Miniport = Miniport;
243 m_pDeviceObject = DeviceObject;
244
245 InitializeListHead(&m_EventList);
246 KeInitializeSpinLock(&m_EventListLock);
247
248 // increment reference on miniport adapter
249 Miniport->AddRef();
250
251 Status = Miniport->Init(UnknownAdapter, ResourceList, this, &ServiceGroup);
252 if (!NT_SUCCESS(Status))
253 {
254 DPRINT("IPortWavePci_fnInit failed with %x\n", Status);
255
256 // release reference on miniport adapter
257 Miniport->Release();
258 return Status;
259 }
260
261 // check if the miniport adapter provides a valid device descriptor
262 Status = Miniport->GetDescription(&m_pDescriptor);
263 if (!NT_SUCCESS(Status))
264 {
265 DPRINT("failed to get description\n");
266 Miniport->Release();
267 return Status;
268 }
269
270 // create the subdevice descriptor
271 Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
272 3,
273 InterfaceGuids,
274 0,
275 NULL,
276 2,
277 WavePciPropertySet,
278 0,
279 0,
280 0,
281 NULL,
282 0,
283 NULL,
284 m_pDescriptor);
285
286
287 if (!NT_SUCCESS(Status))
288 {
289 DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status);
290 Miniport->Release();
291 return Status;
292 }
293
294 // did we get a service group
295 if (ServiceGroup)
296 {
297 // store service group in context
298 m_ServiceGroup = ServiceGroup;
299
300 // add ourselves to service group which is called when miniport receives an isr
301 m_ServiceGroup->AddMember(PSERVICESINK(this));
302
303 // increment reference on service group
304 m_ServiceGroup->AddRef();
305 }
306
307 // store for node property requests
308 m_SubDeviceDescriptor->UnknownMiniport = UnknownMiniport;
309
310 // check if it supports IPinCount interface
311 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
312 if (NT_SUCCESS(Status))
313 {
314 // store IPinCount interface
315 m_pPinCount = PinCount;
316 }
317
318 // does the Miniport adapter support IPowerNotify interface*/
319 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
320 if (NT_SUCCESS(Status))
321 {
322 // store reference
323 m_pPowerNotify = PowerNotify;
324 }
325
326 DPRINT("IPortWavePci_Init sucessfully initialized\n");
327 return STATUS_SUCCESS;
328 }
329
330 NTSTATUS
331 NTAPI
332 CPortWavePci::NewRegistryKey(
333 OUT PREGISTRYKEY *OutRegistryKey,
334 IN PUNKNOWN OuterUnknown OPTIONAL,
335 IN ULONG RegistryKeyType,
336 IN ACCESS_MASK DesiredAccess,
337 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
338 IN ULONG CreateOptions OPTIONAL,
339 OUT PULONG Disposition OPTIONAL)
340 {
341 DPRINT("IPortWavePci_fnNewRegistryKey entered\n");
342 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
343
344 return PcNewRegistryKey(OutRegistryKey,
345 OuterUnknown,
346 RegistryKeyType,
347 DesiredAccess,
348 m_pDeviceObject,
349 (ISubdevice*)this,
350 ObjectAttributes,
351 CreateOptions,
352 Disposition);
353 }
354
355 NTSTATUS
356 NTAPI
357 CPortWavePci::GetDeviceProperty(
358 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
359 IN ULONG BufferLength,
360 OUT PVOID PropertyBuffer,
361 OUT PULONG ReturnLength)
362 {
363 DPRINT("IPortWavePci_fnGetDeviceProperty entered\n");
364 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
365
366 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
367 }
368
369 NTSTATUS
370 NTAPI
371 CPortWavePci::NewMasterDmaChannel(
372 OUT PDMACHANNEL *DmaChannel,
373 IN PUNKNOWN OuterUnknown OPTIONAL,
374 IN POOL_TYPE PoolType,
375 IN PRESOURCELIST ResourceList OPTIONAL,
376 IN BOOLEAN ScatterGather,
377 IN BOOLEAN Dma32BitAddresses,
378 IN BOOLEAN Dma64BitAddresses,
379 IN BOOLEAN IgnoreCount,
380 IN DMA_WIDTH DmaWidth,
381 IN DMA_SPEED DmaSpeed,
382 IN ULONG MaximumLength,
383 IN ULONG DmaPort)
384 {
385 NTSTATUS Status;
386 DEVICE_DESCRIPTION DeviceDescription;
387
388 DPRINT("IPortWavePci_fnNewMasterDmaChannel This %p entered\n", this);
389 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
390
391 Status = PcDmaMasterDescription(ResourceList, ScatterGather, Dma32BitAddresses, IgnoreCount, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, DmaPort, &DeviceDescription);
392 if (NT_SUCCESS(Status))
393 {
394 return PcNewDmaChannel(DmaChannel, OuterUnknown, PoolType, &DeviceDescription, m_pDeviceObject);
395 }
396
397 return Status;
398 }
399
400 VOID
401 NTAPI
402 CPortWavePci::Notify(
403 IN PSERVICEGROUP ServiceGroup)
404 {
405 //DPRINT("IPortWavePci_fnNotify entered %p, ServiceGroup %p\n", This, ServiceGroup);
406
407 if (ServiceGroup)
408 {
409 ServiceGroup->RequestService ();
410 }
411 }
412
413 //---------------------------------------------------------------
414 // ISubdevice interface
415 //
416
417 NTSTATUS
418 NTAPI
419 CPortWavePci::NewIrpTarget(
420 OUT struct IIrpTarget **OutTarget,
421 IN PCWSTR Name,
422 IN PUNKNOWN Unknown,
423 IN POOL_TYPE PoolType,
424 IN PDEVICE_OBJECT DeviceObject,
425 IN PIRP Irp,
426 IN KSOBJECT_CREATE *CreateObject)
427 {
428 NTSTATUS Status;
429 IPortFilterWavePci * Filter;
430
431 DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
432
433 if (m_Filter)
434 {
435 *OutTarget = (IIrpTarget*)m_Filter;
436 return STATUS_SUCCESS;
437 }
438
439 Status = NewPortFilterWavePci(&Filter);
440 if (!NT_SUCCESS(Status))
441 {
442 return Status;
443 }
444
445 Status = Filter->Init((IPortWavePci*)this);
446 if (!NT_SUCCESS(Status))
447 {
448 Filter->Release();
449 return Status;
450 }
451
452 *OutTarget = (IIrpTarget*)Filter;
453 m_Filter = Filter;
454 return Status;
455 }
456
457 NTSTATUS
458 NTAPI
459 CPortWavePci::ReleaseChildren()
460 {
461 UNIMPLEMENTED
462 return STATUS_UNSUCCESSFUL;
463 }
464
465 NTSTATUS
466 NTAPI
467 CPortWavePci::GetDescriptor(
468 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
469 {
470 DPRINT("ISubDevice_GetDescriptor this %p\n", this);
471 *Descriptor = m_SubDeviceDescriptor;
472 return STATUS_SUCCESS;
473 }
474
475 NTSTATUS
476 NTAPI
477 CPortWavePci::DataRangeIntersection(
478 IN ULONG PinId,
479 IN PKSDATARANGE DataRange,
480 IN PKSDATARANGE MatchingDataRange,
481 IN ULONG OutputBufferLength,
482 OUT PVOID ResultantFormat OPTIONAL,
483 OUT PULONG ResultantFormatLength)
484 {
485 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
486
487 if (m_Miniport)
488 {
489 return m_Miniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
490 }
491
492 return STATUS_UNSUCCESSFUL;
493 }
494
495 NTSTATUS
496 NTAPI
497 CPortWavePci::PowerChangeNotify(
498 IN POWER_STATE PowerState)
499 {
500 if (m_pPowerNotify)
501 {
502 m_pPowerNotify->PowerChangeNotify(PowerState);
503 }
504
505 return STATUS_SUCCESS;
506 }
507
508 NTSTATUS
509 NTAPI
510 CPortWavePci::PinCount(
511 IN ULONG PinId,
512 IN OUT PULONG FilterNecessary,
513 IN OUT PULONG FilterCurrent,
514 IN OUT PULONG FilterPossible,
515 IN OUT PULONG GlobalCurrent,
516 IN OUT PULONG GlobalPossible)
517 {
518 if (m_pPinCount)
519 {
520 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
521 return STATUS_SUCCESS;
522 }
523
524 // FIXME
525 // scan filter descriptor
526
527 return STATUS_UNSUCCESSFUL;
528 }
529
530
531 NTSTATUS
532 NewPortWavePci(
533 OUT PPORT* OutPort)
534 {
535 CPortWavePci * Port;
536 NTSTATUS Status;
537
538 Port = new(NonPagedPool, TAG_PORTCLASS) CPortWavePci(NULL);
539 if (!Port)
540 return STATUS_INSUFFICIENT_RESOURCES;
541
542 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
543
544 if (!NT_SUCCESS(Status))
545 {
546 delete Port;
547 }
548
549 DPRINT("NewPortWavePci %p Status %u\n", Port, Status);
550 return Status;
551
552 }
553
554
555 PDEVICE_OBJECT
556 GetDeviceObjectFromPortWavePci(
557 IPortWavePci* iface)
558 {
559 CPortWavePci * This = (CPortWavePci*)iface;
560 return This->m_pDeviceObject;
561 }
562
563 PMINIPORTWAVEPCI
564 GetWavePciMiniport(
565 PPORTWAVEPCI iface)
566 {
567 CPortWavePci * This = (CPortWavePci*)iface;
568 return This->m_Miniport;
569 }