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