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