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