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