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