ec451fe6067ab86cfca2733fdbbc15f392590eed
[reactos.git] / reactos / 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 // store for node property requests
328 m_SubDeviceDescriptor->UnknownMiniport = UnknownMiniport;
329
330 // check if it supports IPinCount interface
331 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
332 if (NT_SUCCESS(Status))
333 {
334 // store IPinCount interface
335 m_pPinCount = PinCount;
336 }
337
338 // does the Miniport adapter support IPowerNotify interface*/
339 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
340 if (NT_SUCCESS(Status))
341 {
342 // store reference
343 m_pPowerNotify = PowerNotify;
344 }
345
346 DPRINT("IPortWavePci_Init sucessfully initialized\n");
347 return STATUS_SUCCESS;
348 }
349
350 NTSTATUS
351 NTAPI
352 CPortWavePci::NewRegistryKey(
353 OUT PREGISTRYKEY *OutRegistryKey,
354 IN PUNKNOWN OuterUnknown OPTIONAL,
355 IN ULONG RegistryKeyType,
356 IN ACCESS_MASK DesiredAccess,
357 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
358 IN ULONG CreateOptions OPTIONAL,
359 OUT PULONG Disposition OPTIONAL)
360 {
361 DPRINT("IPortWavePci_fnNewRegistryKey entered\n");
362 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
363
364 if (!m_bInitialized)
365 {
366 DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
367 return STATUS_UNSUCCESSFUL;
368 }
369
370 return PcNewRegistryKey(OutRegistryKey,
371 OuterUnknown,
372 RegistryKeyType,
373 DesiredAccess,
374 m_pDeviceObject,
375 (ISubdevice*)this,
376 ObjectAttributes,
377 CreateOptions,
378 Disposition);
379 }
380
381 NTSTATUS
382 NTAPI
383 CPortWavePci::GetDeviceProperty(
384 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
385 IN ULONG BufferLength,
386 OUT PVOID PropertyBuffer,
387 OUT PULONG ReturnLength)
388 {
389 DPRINT("IPortWavePci_fnGetDeviceProperty entered\n");
390 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
391
392 if (!m_bInitialized)
393 {
394 DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
395 return STATUS_UNSUCCESSFUL;
396 }
397
398 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
399 }
400
401 NTSTATUS
402 NTAPI
403 CPortWavePci::NewMasterDmaChannel(
404 OUT PDMACHANNEL *DmaChannel,
405 IN PUNKNOWN OuterUnknown OPTIONAL,
406 IN POOL_TYPE PoolType,
407 IN PRESOURCELIST ResourceList OPTIONAL,
408 IN BOOLEAN ScatterGather,
409 IN BOOLEAN Dma32BitAddresses,
410 IN BOOLEAN Dma64BitAddresses,
411 IN BOOLEAN IgnoreCount,
412 IN DMA_WIDTH DmaWidth,
413 IN DMA_SPEED DmaSpeed,
414 IN ULONG MaximumLength,
415 IN ULONG DmaPort)
416 {
417 NTSTATUS Status;
418 DEVICE_DESCRIPTION DeviceDescription;
419
420 DPRINT("IPortWavePci_fnNewMasterDmaChannel This %p entered\n", this);
421 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
422
423 Status = PcDmaMasterDescription(ResourceList, ScatterGather, Dma32BitAddresses, IgnoreCount, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, DmaPort, &DeviceDescription);
424 if (NT_SUCCESS(Status))
425 {
426 return PcNewDmaChannel(DmaChannel, OuterUnknown, PoolType, &DeviceDescription, m_pDeviceObject);
427 }
428
429 return Status;
430 }
431
432 VOID
433 NTAPI
434 CPortWavePci::Notify(
435 IN PSERVICEGROUP ServiceGroup)
436 {
437 //IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
438
439 //DPRINT("IPortWavePci_fnNotify entered %p, ServiceGroup %p\n", This, ServiceGroup);
440
441 if (ServiceGroup)
442 {
443 ServiceGroup->RequestService ();
444 }
445 }
446
447 //---------------------------------------------------------------
448 // ISubdevice interface
449 //
450
451 NTSTATUS
452 NTAPI
453 CPortWavePci::NewIrpTarget(
454 OUT struct IIrpTarget **OutTarget,
455 IN PCWSTR Name,
456 IN PUNKNOWN Unknown,
457 IN POOL_TYPE PoolType,
458 IN PDEVICE_OBJECT DeviceObject,
459 IN PIRP Irp,
460 IN KSOBJECT_CREATE *CreateObject)
461 {
462 NTSTATUS Status;
463 IPortFilterWavePci * Filter;
464
465 DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
466
467 if (m_Filter)
468 {
469 *OutTarget = (IIrpTarget*)m_Filter;
470 return STATUS_SUCCESS;
471 }
472
473 Status = NewPortFilterWavePci(&Filter);
474 if (!NT_SUCCESS(Status))
475 {
476 return Status;
477 }
478
479 Status = Filter->Init((IPortWavePci*)this);
480 if (!NT_SUCCESS(Status))
481 {
482 Filter->Release();
483 return Status;
484 }
485
486 *OutTarget = (IIrpTarget*)Filter;
487 m_Filter = Filter;
488 return Status;
489 }
490
491 NTSTATUS
492 NTAPI
493 CPortWavePci::ReleaseChildren()
494 {
495 //IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
496
497 UNIMPLEMENTED
498 return STATUS_UNSUCCESSFUL;
499 }
500
501 NTSTATUS
502 NTAPI
503 CPortWavePci::GetDescriptor(
504 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
505 {
506 DPRINT("ISubDevice_GetDescriptor this %p\n", this);
507 *Descriptor = m_SubDeviceDescriptor;
508 return STATUS_SUCCESS;
509 }
510
511 NTSTATUS
512 NTAPI
513 CPortWavePci::DataRangeIntersection(
514 IN ULONG PinId,
515 IN PKSDATARANGE DataRange,
516 IN PKSDATARANGE MatchingDataRange,
517 IN ULONG OutputBufferLength,
518 OUT PVOID ResultantFormat OPTIONAL,
519 OUT PULONG ResultantFormatLength)
520 {
521 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
522
523 if (m_Miniport)
524 {
525 return m_Miniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
526 }
527
528 return STATUS_UNSUCCESSFUL;
529 }
530
531 NTSTATUS
532 NTAPI
533 CPortWavePci::PowerChangeNotify(
534 IN POWER_STATE PowerState)
535 {
536 if (m_pPowerNotify)
537 {
538 m_pPowerNotify->PowerChangeNotify(PowerState);
539 }
540
541 return STATUS_SUCCESS;
542 }
543
544 NTSTATUS
545 NTAPI
546 CPortWavePci::PinCount(
547 IN ULONG PinId,
548 IN OUT PULONG FilterNecessary,
549 IN OUT PULONG FilterCurrent,
550 IN OUT PULONG FilterPossible,
551 IN OUT PULONG GlobalCurrent,
552 IN OUT PULONG GlobalPossible)
553 {
554 if (m_pPinCount)
555 {
556 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
557 return STATUS_SUCCESS;
558 }
559
560 // FIXME
561 // scan filter descriptor
562
563 return STATUS_UNSUCCESSFUL;
564 }
565
566
567 NTSTATUS
568 NewPortWavePci(
569 OUT PPORT* OutPort)
570 {
571 CPortWavePci * Port;
572 NTSTATUS Status;
573
574 Port = new(NonPagedPool, TAG_PORTCLASS) CPortWavePci(NULL);
575 if (!Port)
576 return STATUS_INSUFFICIENT_RESOURCES;
577
578 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
579
580 if (!NT_SUCCESS(Status))
581 {
582 delete Port;
583 }
584
585 DPRINT("NewPortWavePci %p Status %u\n", Port, Status);
586 return Status;
587
588 }
589
590
591 PDEVICE_OBJECT
592 GetDeviceObjectFromPortWavePci(
593 IPortWavePci* iface)
594 {
595 CPortWavePci * This = (CPortWavePci*)iface;
596 return This->m_pDeviceObject;
597 }
598
599 PMINIPORTWAVEPCI
600 GetWavePciMiniport(
601 PPORTWAVEPCI iface)
602 {
603 CPortWavePci * This = (CPortWavePci*)iface;
604 return This->m_Miniport;
605 }