[PORTCLS]
[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_IPortClsVersion))
191 {
192 return NewPortClsVersion((PPORTCLSVERSION*)Output);
193 }
194 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterSubdevice))
195 {
196 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
197 }
198 else if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection))
199 {
200 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
201 }
202
203 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
204 {
205 DPRINT("IPortWavePci_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
206 RtlFreeUnicodeString(&GuidString);
207 }
208
209 return STATUS_UNSUCCESSFUL;
210 }
211
212 NTSTATUS
213 NTAPI
214 CPortWavePci::Init(
215 IN PDEVICE_OBJECT DeviceObject,
216 IN PIRP Irp,
217 IN PUNKNOWN UnknownMiniport,
218 IN PUNKNOWN UnknownAdapter OPTIONAL,
219 IN PRESOURCELIST ResourceList)
220 {
221 IMiniportWavePci * Miniport;
222 PSERVICEGROUP ServiceGroup;
223 NTSTATUS Status;
224 PPINCOUNT PinCount;
225 PPOWERNOTIFY PowerNotify;
226
227 DPRINT("IPortWavePci_fnInit entered with This %p, DeviceObject %p Irp %p UnknownMiniport %p, UnknownAdapter %p ResourceList %p\n",
228 this, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
229 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
230
231 if (m_bInitialized)
232 {
233 DPRINT("IPortWavePci_fnInit called again\n");
234 return STATUS_SUCCESS;
235 }
236
237 Status = UnknownMiniport->QueryInterface(IID_IMiniportWavePci, (PVOID*)&Miniport);
238 if (!NT_SUCCESS(Status))
239 {
240 DPRINT("IPortWavePci_fnInit called with invalid IMiniport adapter\n");
241 return STATUS_INVALID_PARAMETER;
242 }
243
244 // Initialize port object
245 m_Miniport = Miniport;
246 m_pDeviceObject = DeviceObject;
247 m_bInitialized = TRUE;
248 m_pResourceList = ResourceList;
249 InitializeListHead(&m_EventList);
250 KeInitializeSpinLock(&m_EventListLock);
251
252 // increment reference on miniport adapter
253 Miniport->AddRef();
254
255
256 if (ResourceList)
257 {
258 // increment reference on resource list
259 ResourceList->AddRef();
260 }
261
262 Status = Miniport->Init(UnknownAdapter, ResourceList, this, &ServiceGroup);
263 if (!NT_SUCCESS(Status))
264 {
265 DPRINT("IPortWavePci_fnInit failed with %x\n", Status);
266 m_bInitialized = FALSE;
267 // release reference on miniport adapter
268 Miniport->Release();
269 // increment reference on resource list
270 ResourceList->Release();
271 return Status;
272 }
273
274 // check if the miniport adapter provides a valid device descriptor
275 Status = Miniport->GetDescription(&m_pDescriptor);
276 if (!NT_SUCCESS(Status))
277 {
278 DPRINT("failed to get description\n");
279 Miniport->Release();
280 m_bInitialized = FALSE;
281 return Status;
282 }
283
284 // create the subdevice descriptor
285 Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
286 3,
287 InterfaceGuids,
288 0,
289 NULL,
290 2,
291 WavePciPropertySet,
292 0,
293 0,
294 0,
295 NULL,
296 0,
297 NULL,
298 m_pDescriptor);
299
300
301 if (!NT_SUCCESS(Status))
302 {
303 DPRINT("PcCreateSubdeviceDescriptor failed with %x\n", Status);
304 Miniport->Release();
305 m_bInitialized = FALSE;
306 return Status;
307 }
308
309 // did we get a service group
310 if (ServiceGroup)
311 {
312 // store service group in context
313 m_ServiceGroup = ServiceGroup;
314
315 // add ourselves to service group which is called when miniport receives an isr
316 m_ServiceGroup->AddMember(PSERVICESINK(this));
317
318 // increment reference on service group
319 m_ServiceGroup->AddRef();
320 }
321
322 // check if it supports IPinCount interface
323 Status = UnknownMiniport->QueryInterface(IID_IPinCount, (PVOID*)&PinCount);
324 if (NT_SUCCESS(Status))
325 {
326 // store IPinCount interface
327 m_pPinCount = PinCount;
328 }
329
330 // does the Miniport adapter support IPowerNotify interface*/
331 Status = UnknownMiniport->QueryInterface(IID_IPowerNotify, (PVOID*)&PowerNotify);
332 if (NT_SUCCESS(Status))
333 {
334 // store reference
335 m_pPowerNotify = PowerNotify;
336 }
337
338 DPRINT("IPortWavePci_Init sucessfully initialized\n");
339 return STATUS_SUCCESS;
340 }
341
342 NTSTATUS
343 NTAPI
344 CPortWavePci::NewRegistryKey(
345 OUT PREGISTRYKEY *OutRegistryKey,
346 IN PUNKNOWN OuterUnknown OPTIONAL,
347 IN ULONG RegistryKeyType,
348 IN ACCESS_MASK DesiredAccess,
349 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
350 IN ULONG CreateOptions OPTIONAL,
351 OUT PULONG Disposition OPTIONAL)
352 {
353 DPRINT("IPortWavePci_fnNewRegistryKey entered\n");
354 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
355
356 if (!m_bInitialized)
357 {
358 DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
359 return STATUS_UNSUCCESSFUL;
360 }
361
362 return PcNewRegistryKey(OutRegistryKey,
363 OuterUnknown,
364 RegistryKeyType,
365 DesiredAccess,
366 m_pDeviceObject,
367 (ISubdevice*)this,
368 ObjectAttributes,
369 CreateOptions,
370 Disposition);
371 }
372
373 NTSTATUS
374 NTAPI
375 CPortWavePci::GetDeviceProperty(
376 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
377 IN ULONG BufferLength,
378 OUT PVOID PropertyBuffer,
379 OUT PULONG ReturnLength)
380 {
381 DPRINT("IPortWavePci_fnGetDeviceProperty entered\n");
382 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
383
384 if (!m_bInitialized)
385 {
386 DPRINT("IPortWavePci_fnNewRegistryKey called w/o initiazed\n");
387 return STATUS_UNSUCCESSFUL;
388 }
389
390 return IoGetDeviceProperty(m_pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
391 }
392
393 NTSTATUS
394 NTAPI
395 CPortWavePci::NewMasterDmaChannel(
396 OUT PDMACHANNEL *DmaChannel,
397 IN PUNKNOWN OuterUnknown OPTIONAL,
398 IN POOL_TYPE PoolType,
399 IN PRESOURCELIST ResourceList OPTIONAL,
400 IN BOOLEAN ScatterGather,
401 IN BOOLEAN Dma32BitAddresses,
402 IN BOOLEAN Dma64BitAddresses,
403 IN BOOLEAN IgnoreCount,
404 IN DMA_WIDTH DmaWidth,
405 IN DMA_SPEED DmaSpeed,
406 IN ULONG MaximumLength,
407 IN ULONG DmaPort)
408 {
409 NTSTATUS Status;
410 DEVICE_DESCRIPTION DeviceDescription;
411
412 DPRINT("IPortWavePci_fnNewMasterDmaChannel This %p entered\n", this);
413 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
414
415 Status = PcDmaMasterDescription(ResourceList, ScatterGather, Dma32BitAddresses, IgnoreCount, Dma64BitAddresses, DmaWidth, DmaSpeed, MaximumLength, DmaPort, &DeviceDescription);
416 if (NT_SUCCESS(Status))
417 {
418 return PcNewDmaChannel(DmaChannel, OuterUnknown, PoolType, &DeviceDescription, m_pDeviceObject);
419 }
420
421 return Status;
422 }
423
424 VOID
425 NTAPI
426 CPortWavePci::Notify(
427 IN PSERVICEGROUP ServiceGroup)
428 {
429 //IPortWavePciImpl * This = (IPortWavePciImpl*)iface;
430
431 //DPRINT("IPortWavePci_fnNotify entered %p, ServiceGroup %p\n", This, ServiceGroup);
432
433 if (ServiceGroup)
434 {
435 ServiceGroup->RequestService ();
436 }
437 }
438
439 //---------------------------------------------------------------
440 // ISubdevice interface
441 //
442
443 NTSTATUS
444 NTAPI
445 CPortWavePci::NewIrpTarget(
446 OUT struct IIrpTarget **OutTarget,
447 IN PCWSTR Name,
448 IN PUNKNOWN Unknown,
449 IN POOL_TYPE PoolType,
450 IN PDEVICE_OBJECT DeviceObject,
451 IN PIRP Irp,
452 IN KSOBJECT_CREATE *CreateObject)
453 {
454 NTSTATUS Status;
455 IPortFilterWavePci * Filter;
456
457 DPRINT("ISubDevice_NewIrpTarget this %p\n", this);
458
459 if (m_Filter)
460 {
461 *OutTarget = (IIrpTarget*)m_Filter;
462 return STATUS_SUCCESS;
463 }
464
465 Status = NewPortFilterWavePci(&Filter);
466 if (!NT_SUCCESS(Status))
467 {
468 return Status;
469 }
470
471 Status = Filter->Init((IPortWavePci*)this);
472 if (!NT_SUCCESS(Status))
473 {
474 Filter->Release();
475 return Status;
476 }
477
478 *OutTarget = (IIrpTarget*)Filter;
479 m_Filter = Filter;
480 return Status;
481 }
482
483 NTSTATUS
484 NTAPI
485 CPortWavePci::ReleaseChildren()
486 {
487 //IPortWavePciImpl * This = (IPortWavePciImpl*)CONTAINING_RECORD(iface, IPortWavePciImpl, lpVtblSubDevice);
488
489 UNIMPLEMENTED
490 return STATUS_UNSUCCESSFUL;
491 }
492
493 NTSTATUS
494 NTAPI
495 CPortWavePci::GetDescriptor(
496 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
497 {
498 DPRINT("ISubDevice_GetDescriptor this %p\n", this);
499 *Descriptor = m_SubDeviceDescriptor;
500 return STATUS_SUCCESS;
501 }
502
503 NTSTATUS
504 NTAPI
505 CPortWavePci::DataRangeIntersection(
506 IN ULONG PinId,
507 IN PKSDATARANGE DataRange,
508 IN PKSDATARANGE MatchingDataRange,
509 IN ULONG OutputBufferLength,
510 OUT PVOID ResultantFormat OPTIONAL,
511 OUT PULONG ResultantFormatLength)
512 {
513 DPRINT("ISubDevice_DataRangeIntersection this %p\n", this);
514
515 if (m_Miniport)
516 {
517 return m_Miniport->DataRangeIntersection (PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
518 }
519
520 return STATUS_UNSUCCESSFUL;
521 }
522
523 NTSTATUS
524 NTAPI
525 CPortWavePci::PowerChangeNotify(
526 IN POWER_STATE PowerState)
527 {
528 if (m_pPowerNotify)
529 {
530 m_pPowerNotify->PowerChangeNotify(PowerState);
531 }
532
533 return STATUS_SUCCESS;
534 }
535
536 NTSTATUS
537 NTAPI
538 CPortWavePci::PinCount(
539 IN ULONG PinId,
540 IN OUT PULONG FilterNecessary,
541 IN OUT PULONG FilterCurrent,
542 IN OUT PULONG FilterPossible,
543 IN OUT PULONG GlobalCurrent,
544 IN OUT PULONG GlobalPossible)
545 {
546 if (m_pPinCount)
547 {
548 m_pPinCount->PinCount(PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
549 return STATUS_SUCCESS;
550 }
551
552 // FIXME
553 // scan filter descriptor
554
555 return STATUS_UNSUCCESSFUL;
556 }
557
558
559 NTSTATUS
560 NewPortWavePci(
561 OUT PPORT* OutPort)
562 {
563 CPortWavePci * Port;
564 NTSTATUS Status;
565
566 Port = new(NonPagedPool, TAG_PORTCLASS) CPortWavePci(NULL);
567 if (!Port)
568 return STATUS_INSUFFICIENT_RESOURCES;
569
570 Status = Port->QueryInterface(IID_IPort, (PVOID*)OutPort);
571
572 if (!NT_SUCCESS(Status))
573 {
574 delete Port;
575 }
576
577 DPRINT("NewPortWavePci %p Status %u\n", Port, Status);
578 return Status;
579
580 }
581
582
583 PDEVICE_OBJECT
584 GetDeviceObjectFromPortWavePci(
585 IPortWavePci* iface)
586 {
587 CPortWavePci * This = (CPortWavePci*)iface;
588 return This->m_pDeviceObject;
589 }
590
591 PMINIPORTWAVEPCI
592 GetWavePciMiniport(
593 PPORTWAVEPCI iface)
594 {
595 CPortWavePci * This = (CPortWavePci*)iface;
596 return This->m_Miniport;
597 }