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