minwave.cpp

来自「winddk src目录下的WDM源码压缩!」· C++ 代码 · 共 1,666 行 · 第 1/5 页

CPP
1,666
字号
    // We only have a set defined.
    if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
    {
        // validate buffer size.
        if (PropertyRequest->ValueSize < sizeof(LONG))
            return ntStatus;

        // The "Value" is the input buffer with the channel config.
        if (PropertyRequest->Value)
        {
            // We can accept different channel configurations, depending
            // on the number of channels we can play.
            if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
            {
                if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
                {
                    // we accept 5.1
                    if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1)
                    {
                        that->m_dwChannelMask =  *(PLONG)PropertyRequest->Value;
                        that->m_wChannels = 6;
                        that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
                        ntStatus = STATUS_SUCCESS;
                    }
                }
                
                // accept also surround or quad.
                if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) ||
                    (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND))
                {
                    that->m_dwChannelMask =  *(PLONG)PropertyRequest->Value;
                    that->m_wChannels = 4;
                    that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
                    ntStatus = STATUS_SUCCESS;
                }
            }
            
            // accept also stereo speakers.
            if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO)
            {
                that->m_dwChannelMask =  *(PLONG)PropertyRequest->Value;
                that->m_wChannels = 2;
                that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
                ntStatus = STATUS_SUCCESS;
            }
        }
    }

    return ntStatus;
}

/*****************************************************************************
 * CreateMiniportWaveICH
 *****************************************************************************
 * Creates a ICH wave miniport object for the ICH adapter.
 * This uses a macro from STDUNK.H to do all the work.
 */
NTSTATUS CreateMiniportWaveICH
(
    OUT PUNKNOWN   *Unknown,
    IN  REFCLSID,
    IN  PUNKNOWN    UnknownOuter    OPTIONAL,
    IN  POOL_TYPE   PoolType
)
{
    PAGED_CODE ();

    ASSERT (Unknown);

    DOUT (DBG_PRINT, ("[CreateMiniportWaveICH]"));

    STD_CREATE_BODY_(CMiniportWaveICH,Unknown,UnknownOuter,PoolType,
                     PMINIPORTWAVEPCI);
}


/*****************************************************************************
 * CMiniportWaveICH::NonDelegatingQueryInterface
 *****************************************************************************
 * Obtains an interface.  This function works just like a COM QueryInterface
 * call and is used if the object is not being aggregated.
 */
STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::NonDelegatingQueryInterface
(
    IN  REFIID  Interface,
    OUT PVOID  *Object
)
{
    PAGED_CODE ();

    ASSERT (Object);

    DOUT (DBG_PRINT, ("[CMiniportWaveICH::NonDelegatingQueryInterface]"));

    // Is it IID_IUnknown?
    if (IsEqualGUIDAligned (Interface, IID_IUnknown))
    {
        *Object = (PVOID)(PUNKNOWN)(PMINIPORTWAVEPCI)this;
    } 
    // or IID_IMiniport ...
    else if (IsEqualGUIDAligned (Interface, IID_IMiniport))
    {
        *Object = (PVOID)(PMINIPORT)this;
    } 
    // or IID_IMiniportWavePci ...
    else if (IsEqualGUIDAligned (Interface, IID_IMiniportWavePci))
    {
        *Object = (PVOID)(PMINIPORTWAVEPCI)this;
    } 
    // or IID_IPowerNotify ...
    else if (IsEqualGUIDAligned (Interface, IID_IPowerNotify))
    {
        *Object = (PVOID)(PPOWERNOTIFY)this;
    } 
    else
    {
        // nothing found, must be an unknown interface.
        *Object = NULL;
        return STATUS_INVALID_PARAMETER;
    }

    //
    // We reference the interface for the caller.
    //
    ((PUNKNOWN)(*Object))->AddRef();
    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CMiniportWaveICH::~CMiniportWaveICH
 *****************************************************************************
 * Destructor.
 */
CMiniportWaveICH::~CMiniportWaveICH ()
{
    PAGED_CODE ();

    DOUT (DBG_PRINT, ("[CMiniportWaveICH::~CMiniportWaveICH]"));

    //
    // Release the DMA channel.
    //
    if (DmaChannel)
    {
        DmaChannel->Release ();
        DmaChannel = NULL;
    }

    //
    // Release the interrupt sync.
    //
    if (InterruptSync)
    {
        InterruptSync->Release ();
        InterruptSync = NULL;
    }

    //
    // Release adapter common object.
    //
    if (AdapterCommon)
    {
        AdapterCommon->Release ();
        AdapterCommon = NULL;
    }

    //
    // Release the port.
    //
    if (Port)
    {
        Port->Release ();
        Port = NULL;
    }
}


/*****************************************************************************
 * CMiniportWaveICH::Init
 *****************************************************************************
 * Initializes the miniport.
 * Initializes variables and modifies the wave topology if needed.
 */
STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::Init
(
    IN  PUNKNOWN       UnknownAdapter,
    IN  PRESOURCELIST  ResourceList,
    IN  PPORTWAVEPCI   Port_,
    OUT PSERVICEGROUP *ServiceGroup_
)
{
    PAGED_CODE ();

    ASSERT (UnknownAdapter);
    ASSERT (ResourceList);
    ASSERT (Port_);

    DOUT (DBG_PRINT, ("[CMiniportWaveICH::Init]"));

    //
    // AddRef() is required because we are keeping this pointer.
    //
    Port = Port_;
    Port->AddRef ();

    //
    // No miniport service group
    //
    *ServiceGroup_ = NULL;

    //
    // Set initial device power state
    //
    m_PowerState = PowerDeviceD0;

    NTSTATUS ntStatus = UnknownAdapter->
        QueryInterface (IID_IAdapterCommon, (PVOID *)&AdapterCommon);
    if (NT_SUCCESS (ntStatus))
    {
        //
        // Alter the topology for the wave miniport.
        //
        if (!(AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT) &&
              AdapterCommon->GetPinConfig (PINC_MIC_PRESENT)))
        {
            //
            // Remove the pins, nodes and connections for the MICIN.
            //
            MiniportFilterDescriptor.PinCount = SIZEOF_ARRAY(MiniportPins) - 2;
            MiniportFilterDescriptor.NodeCount = SIZEOF_ARRAY(MiniportNodes) - 1;
            MiniportFilterDescriptor.ConnectionCount = SIZEOF_ARRAY(MiniportConnections) - 2;
        }

        //
        // Process the resources.
        //
        ntStatus = ProcessResources (ResourceList);

        //
        // Get the default channel config
        //
        AdapterCommon->ReadChannelConfigDefault (&m_dwChannelMask, &m_wChannels);

        //
        // If we came till that point, check the CoDec for supported standard
        // sample rates. This function will then fill the data range information
        //
        if (NT_SUCCESS (ntStatus))
            ntStatus = BuildDataRangeInformation ();
    }

    //
    // If we fail we get destroyed anyway (that's where we clean up).
    //
    return ntStatus;
}


/*****************************************************************************
 * CMiniportWaveICH::ProcessResources
 *****************************************************************************
 * Processes the resource list, setting up helper objects accordingly.
 * Sets up the Interrupt + Service routine and DMA.
 */
NTSTATUS CMiniportWaveICH::ProcessResources
(
    IN  PRESOURCELIST ResourceList
)
{
    PAGED_CODE ();

    ASSERT (ResourceList);


    DOUT (DBG_PRINT, ("[CMiniportWaveICH::ProcessResources]"));


    ULONG countIRQ = ResourceList->NumberOfInterrupts ();
    if (countIRQ < 1)
    {
        DOUT (DBG_ERROR, ("Unknown configuration for wave miniport!"));
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    
    //
    // Create an interrupt sync object
    //
    NTSTATUS ntStatus = STATUS_SUCCESS;
    ntStatus = PcNewInterruptSync (&InterruptSync,
                                   NULL,
                                   ResourceList,
                                   0,
                                   InterruptSyncModeNormal);

    if (!NT_SUCCESS (ntStatus) || !InterruptSync)
    {
        DOUT (DBG_ERROR, ("Failed to create an interrupt sync!"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Register our ISR.
    //
    ntStatus = InterruptSync->RegisterServiceRoutine (InterruptServiceRoutine,
                                                      (PVOID)this, FALSE);
    if (!NT_SUCCESS (ntStatus))
    {
        DOUT (DBG_ERROR, ("Failed to register ISR!"));
        return ntStatus;
    }

    //
    // Connect the interrupt.
    //
    ntStatus = InterruptSync->Connect ();
    if (!NT_SUCCESS (ntStatus))
    {
        DOUT (DBG_ERROR, ("Failed to connect the ISR with InterruptSync!"));
        return ntStatus;
    }

    //
    // Create the DMA Channel object.
    //
    ntStatus = Port->NewMasterDmaChannel (&DmaChannel,      // OutDmaChannel
                                          NULL,             // OuterUnknown (opt)
                                          NonPagedPool,     // Pool Type
                                          NULL,             // ResourceList (opt)
                                          TRUE,             // ScatterGather
                                          TRUE,             // Dma32BitAddresses
                                          FALSE,            // Dma64BitAddresses
                                          FALSE,            // IgnoreCount
                                          Width32Bits,      // DmaWidth

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?