/***************************************************************************** * StartDevice() ***************************************************************************** * * This function is called by the operating system when the device is started. * It is responsible for starting the miniports. This code is specific to * the adapter because it calls out miniports for functions that are specific * to the adapter. A list of no resources is not the same as a NULL list ptr. * */ NTSTATUS StartDevice ( IN PDEVICE_OBJECT pDeviceObject, // Context for the class driver. IN PIRP pIrp, // Context for the class driver. IN PRESOURCELIST ResourceList // List of hardware resources. ) { PAGED_CODE(); _DbgPrintF(DEBUGLVL_VERBOSE, ("StartDevice")); ASSERT(ResourceList); if (!ResourceList) { return STATUS_INVALID_PARAMETER; } PPORT port; NTSTATUS ntStatus = PcNewPort(&port, CLSID_PortDMus); if (!NT_SUCCESS(ntStatus)) { _DbgPrintF(DEBUGLVL_TERSE,("StartDevice PcNewPort failed (0x%08x)", ntStatus)); return ntStatus; } ASSERT(port); PUNKNOWN miniport; #ifdef USE_OBSOLETE_FUNCS ntStatus = CreateMiniportDmSynth(&miniport, NULL, NonPagedPool); #else ntStatus = CreateMiniportDmSynth(&miniport, NULL, NonPagedPool, pDeviceObject); #endif if (!NT_SUCCESS(ntStatus)) { _DbgPrintF(DEBUGLVL_TERSE,("StartDevice CreateMiniportDmSynth failed (0x%08x)", ntStatus)); port->Release(); return ntStatus; } ASSERT(miniport); ntStatus = port->Init ( pDeviceObject, pIrp, miniport, NULL, ResourceList ); if (!NT_SUCCESS(ntStatus)) { _DbgPrintF(DEBUGLVL_TERSE,("StartDevice port Init failed (0x%08x)", ntStatus)); port->Release(); miniport->Release(); return ntStatus; } ntStatus = PcRegisterSubdevice( pDeviceObject, L"DDKSynth", port); if (!NT_SUCCESS(ntStatus)) { _DbgPrintF(DEBUGLVL_TERSE,("StartDevice PcRegisterSubdevice failed (0x%08x)", ntStatus)); } // // We don't need the miniport any more. Either the port has it, // or we've failed, and it should be deleted. // miniport->Release(); // // Release the reference which existed when PcNewPort() gave us the // pointer in the first place. This is the right thing to do // regardless of the outcome. // port->Release(); return ntStatus; }
//============================================================================= NTSTATUS InstallSubdevice( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PWSTR Name, __in REFGUID PortClassId, __in REFGUID MiniportClassId, __in_opt PFNCREATEINSTANCE MiniportCreate, __in_opt PUNKNOWN UnknownAdapter, __in_opt PRESOURCELIST ResourceList, __in REFGUID PortInterfaceId, __out_opt PUNKNOWN * OutPortInterface, __out_opt PUNKNOWN * OutPortUnknown ) /*++ Routine Description: This function creates and registers a subdevice consisting of a port driver, a minport driver and a set of resources bound together. It will also optionally place a pointer to an interface on the port driver in a specified location before initializing the port driver. This is done so that a common ISR can have access to the port driver during initialization, when the ISR might fire. Arguments: DeviceObject - pointer to the driver object Irp - pointer to the irp object. Name - name of the miniport. Passes to PcRegisterSubDevice PortClassId - port class id. Passed to PcNewPort. MiniportClassId - miniport class id. Passed to PcNewMiniport. MiniportCreate - pointer to a miniport creation function. If NULL, PcNewMiniport is used. UnknownAdapter - pointer to the adapter object. Used for initializing the port. ResourceList - pointer to the resource list. PortInterfaceId - GUID that represents the port interface. OutPortInterface - pointer to store the port interface OutPortUnknown - pointer to store the unknown port interface. Return Value: NT status code. --*/ { PAGED_CODE(); ASSERT(DeviceObject); ASSERT(Irp); ASSERT(Name); NTSTATUS ntStatus; PPORT port = NULL; PUNKNOWN miniport = NULL; DPF_ENTER(("[InstallSubDevice %S]", Name)); // Create the port driver object ntStatus = PcNewPort(&port, PortClassId); // Create the miniport object if (NT_SUCCESS(ntStatus)) { if (MiniportCreate) { ntStatus = MiniportCreate(&miniport, MiniportClassId, NULL, NonPagedPool ); } else { ntStatus = PcNewMiniport((PMINIPORT *) &miniport, MiniportClassId); } } // Init the port driver and miniport in one go. if (NT_SUCCESS(ntStatus)) { ntStatus = port->Init(DeviceObject, Irp, miniport, UnknownAdapter, ResourceList); if (NT_SUCCESS(ntStatus)) { // Register the subdevice (port/miniport combination). ntStatus = PcRegisterSubdevice(DeviceObject, Name, port); } // We don't need the miniport any more. Either the port has it, // or we've failed, and it should be deleted. miniport->Release(); } // Deposit the port interfaces if it's needed. if (NT_SUCCESS(ntStatus)) { if (OutPortUnknown) { ntStatus = port->QueryInterface(IID_IUnknown, (PVOID *)OutPortUnknown); } if (OutPortInterface) { ntStatus = port->QueryInterface(PortInterfaceId, (PVOID *) OutPortInterface); } } if (port) { port->Release(); } return ntStatus; } // InstallSubDevice
//============================================================================= NTSTATUS StartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PRESOURCELIST ResourceList ) /*++ Routine Description: This function is called by the operating system when the device is started. It is responsible for starting the miniports. This code is specific to the adapter because it calls out miniports for functions that are specific to the adapter. Arguments: DeviceObject - pointer to the driver object Irp - pointer to the irp ResourceList - pointer to the resource list assigned by PnP manager Return Value: NT status code. --*/ { UNREFERENCED_PARAMETER(ResourceList); PAGED_CODE(); ASSERT(DeviceObject); ASSERT(Irp); ASSERT(ResourceList); NTSTATUS ntStatus = STATUS_SUCCESS; PUNKNOWN unknownTopology = NULL; PUNKNOWN unknownWave = NULL; PADAPTERCOMMON pAdapterCommon = NULL; PUNKNOWN pUnknownCommon = NULL; DPF_ENTER(("[StartDevice]")); // create a new adapter common object ntStatus = NewAdapterCommon(&pUnknownCommon, IID_IAdapterCommon, NULL, NonPagedPool); if (NT_SUCCESS(ntStatus)) { ntStatus = pUnknownCommon->QueryInterface(IID_IAdapterCommon, (PVOID *) &pAdapterCommon); if (NT_SUCCESS(ntStatus)) { ntStatus = pAdapterCommon->Init(DeviceObject); if (NT_SUCCESS(ntStatus)) { // register with PortCls for power-management services ntStatus = PcRegisterAdapterPowerManagement(PUNKNOWN(pAdapterCommon), DeviceObject); } } } // install MSVAD topology miniport. if (NT_SUCCESS(ntStatus)) { ntStatus = InstallSubdevice(DeviceObject, Irp, L"Topology", CLSID_PortTopology, CLSID_PortTopology, CreateMiniportTopologyMSVAD, pAdapterCommon, NULL, IID_IPortTopology, NULL, &unknownTopology); } // install MSVAD wavecyclic miniport. if (NT_SUCCESS(ntStatus)) { ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCyclicMSVAD, pAdapterCommon, NULL, IID_IPortWaveCyclic, pAdapterCommon->WavePortDriverDest(), &unknownWave); } if (unknownTopology && unknownWave) { // register wave <=> topology connections // This will connect bridge pins of wavecyclic and topology // miniports. if ((TopologyPhysicalConnections.ulTopologyOut != (ULONG)-1) && (TopologyPhysicalConnections.ulWaveIn != (ULONG)-1)) { ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownTopology, TopologyPhysicalConnections.ulTopologyOut, unknownWave, TopologyPhysicalConnections.ulWaveIn); } if (NT_SUCCESS(ntStatus)) { if ((TopologyPhysicalConnections.ulWaveOut != (ULONG)-1) && (TopologyPhysicalConnections.ulTopologyIn != (ULONG)-1)) { ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownWave, TopologyPhysicalConnections.ulWaveOut, unknownTopology, TopologyPhysicalConnections.ulTopologyIn); } } } // Release the adapter common object. It either has other references, // or we need to delete it anyway. if (pAdapterCommon) { pAdapterCommon->Release(); } if (pUnknownCommon) { pUnknownCommon->Release(); } if (unknownTopology) { unknownTopology->Release(); } if (unknownWave) { unknownWave->Release(); } return ntStatus; } // StartDevice
/***************************************************************************** * StartDevice ***************************************************************************** * This function is called by the operating system when the device is started. * It is responsible for starting the miniports. This code is specific to * the adapter because it calls out miniports for functions that are specific * to the adapter. */ NTSTATUS StartDevice ( IN PDEVICE_OBJECT DeviceObject, // Device object. IN PIRP Irp, // IO request packet. IN PRESOURCELIST ResourceList // List of hardware resources. ) { PAGED_CODE (); ASSERT (DeviceObject); ASSERT (Irp); ASSERT (ResourceList); NTSTATUS ntStatus; DOUT (DBG_PRINT, ("[StartDevice]")); // // Determine which version of the OS we are running under. We don't want // to run under Win98G. // // create a wave cyclic port PPORT pPort = 0; ntStatus = PcNewPort (&pPort,CLSID_PortWaveCyclic); // check error code if (NT_SUCCESS (ntStatus)) { // query for the event interface which is not supported in Win98 gold. PPORTEVENTS pPortEvents = 0; ntStatus = pPort->QueryInterface (IID_IPortEvents, (PVOID *)&pPortEvents); if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("This driver is not for Win98 Gold!")); ntStatus = STATUS_UNSUCCESSFUL; // change error code. } else { pPortEvents->Release (); } pPort->Release (); } // now return in case it was Win98 Gold. if (!NT_SUCCESS (ntStatus)) return ntStatus; // // Validate the resources. // We don't have to split the resources into several resource lists cause // the topology miniport doesn't need a resource list, the wave pci miniport // needs all resources like the adapter common object. // ntStatus = ValidateResources (ResourceList); // // return immediately in case of an error // if (!NT_SUCCESS (ntStatus)) return ntStatus; // // If the adapter has the right resources... // PADAPTERCOMMON pAdapterCommon = NULL; PUNKNOWN pUnknownCommon; // create a new adapter common object ntStatus = NewAdapterCommon (&pUnknownCommon, IID_IAC97AdapterCommon, NULL, NonPagedPool); if (NT_SUCCESS (ntStatus)) { // query for the IAC97AdapterCommon interface ntStatus = pUnknownCommon->QueryInterface (IID_IAC97AdapterCommon, (PVOID *)&pAdapterCommon); if (NT_SUCCESS (ntStatus)) { // Initialize the object ntStatus = pAdapterCommon->Init (ResourceList, DeviceObject); if (NT_SUCCESS (ntStatus)) { // register with PortCls for power-management services ntStatus = PcRegisterAdapterPowerManagement ((PUNKNOWN)pAdapterCommon, DeviceObject); } } // release the IID_IAC97AdapterCommon on adapter common pUnknownCommon->Release (); } // print error message. if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("Could not create or query AdapterCommon.")); } // // These are the port driver pointers we are keeping around for registering // physical connections. // PMINIPORT miniTopology = NULL; PUNKNOWN unknownWave = NULL; PUNKNOWN unknownTopology = NULL; PAC97MINIPORTTOPOLOGY pMiniportTopology = NULL; // // Start the topology miniport. // if (NT_SUCCESS (ntStatus)) { ntStatus = InstallSubdevice (DeviceObject, Irp, L"Topology", CLSID_PortTopology, CLSID_PortTopology, // not used CreateAC97MiniportTopology, pAdapterCommon, NULL, GUID_NULL, &miniTopology, &unknownTopology); if (NT_SUCCESS (ntStatus)) { // query for the IAC97MiniportTopology interface ntStatus = miniTopology->QueryInterface (IID_IAC97MiniportTopology, (PVOID *)&pMiniportTopology); miniTopology->Release (); miniTopology = NULL; } // print error message. if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("Could not create or query TopologyICH")); } } // // Start the wave miniport. // if (NT_SUCCESS (ntStatus)) { #if (NTDDI_VERSION >= NTDDI_VISTA) ntStatus = InstallSubdevice (DeviceObject, Irp, L"Wave", CLSID_PortWaveRT, CLSID_PortWaveRT, // not used CreateAC97MiniportWaveRT, pAdapterCommon, ResourceList, IID_IPortWaveRT, NULL, &unknownWave); if (!NT_SUCCESS (ntStatus)) { #endif // // If creation of the RT port failed we can fall back to the WavePCI // or WaveCyc port of portcls. In this case, we try the WavePCI port. // ntStatus = InstallSubdevice (DeviceObject, Irp, L"Wave", CLSID_PortWavePci, CLSID_PortWavePci, // not used CreateAC97MiniportWavePCI, pAdapterCommon, ResourceList, IID_IPortWavePci, NULL, &unknownWave); #if (NTDDI_VERSION >= NTDDI_VISTA) } #endif // print error message. if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("WaveRT and WavePCI miniport installation failed!")); } } // // Establish physical connections between filters as shown. // // +------+ +------+ // | Wave | | Topo | // Capture <---|2 3|<===|x |<--- CD // | | | | // Render --->|0 1|===>|y |<--- Line In // | | | | // Mic <---|4 5|<===|z |<--- Mic // +------+ | | // | |---> Line Out // +------+ // // Note that the pin numbers for the nodes to be connected // vary depending on the hardware/codec configuration. // Also, the mic input may or may not be present. // // So, // Do a QI on unknownTopology to get an interface to call // a method on to get the topology miniport pin IDs. if (NT_SUCCESS (ntStatus)) { ULONG ulWaveOut, ulWaveIn, ulMicIn; // get the pin numbers. DOUT (DBG_PRINT, ("Connecting topo and wave.")); ntStatus = pMiniportTopology->GetPhysicalConnectionPins (&ulWaveOut, &ulWaveIn, &ulMicIn); // register wave render connection if (NT_SUCCESS (ntStatus)) { ntStatus = PcRegisterPhysicalConnection (DeviceObject, unknownWave, PIN_WAVEOUT_BRIDGE, unknownTopology, ulWaveOut); // print error message. if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport" " (render)!")); } } if (NT_SUCCESS (ntStatus)) { // register wave capture connection ntStatus = PcRegisterPhysicalConnection (DeviceObject, unknownTopology, ulWaveIn, unknownWave, PIN_WAVEIN_BRIDGE); // print error message. if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport" " (capture)!")); } } if (NT_SUCCESS (ntStatus)) { // register mic capture connection if (pAdapterCommon->GetPinConfig (PINC_MICIN_PRESENT)) { ntStatus = PcRegisterPhysicalConnection (DeviceObject, unknownTopology, ulMicIn, unknownWave, PIN_MICIN_BRIDGE); // print error message. if (!NT_SUCCESS (ntStatus)) { DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport" " (MIC)!")); } } } } // // Release the adapter common object. It either has other references, // or we need to delete it anyway. // if (pAdapterCommon) pAdapterCommon->Release (); // // Release the unknowns. // if (unknownTopology) unknownTopology->Release (); if (unknownWave) unknownWave->Release (); // and the AC97 miniport. if (pMiniportTopology) pMiniportTopology->Release (); return ntStatus; // whatever this is ... }