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