⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mintopo.cpp

📁 AC97 Sample Driver and Related Code Samples. This directory contains a sample AC97 adapter driver a
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        AdapterCommon = NULL;
    }

    if (FilterDescriptor)
    {
        ExFreePool (FilterDescriptor);
        FilterDescriptor = NULL;
    }

    if (ConnectionDescriptors)
    {
        ExFreePool (ConnectionDescriptors);
        ConnectionDescriptors = NULL;
    }

    if (NodeDescriptors)
    {
        ExFreePool (NodeDescriptors);
        NodeDescriptors = NULL;
    }

    if (PinDescriptors)
    {
        ExFreePool (PinDescriptors);
        PinDescriptors = NULL;
    }
}

/*****************************************************************************
 * CMiniportTopologyICH::DataRangeIntersection
 *****************************************************************************
 * Is defined in the IMiniportTopology interface. We just return
 * STATUS_NOT_IMPLEMENTED and portcls will use a default handler for this.
 */
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::DataRangeIntersection
(
    IN      ULONG           PinId,
    IN      PKSDATARANGE    DataRange,
    IN      PKSDATARANGE    MatchingDataRange,
    IN      ULONG           OutputBufferLength,
    OUT     PVOID           ResultantFormat     OPTIONAL,
    OUT     PULONG          ResultantFormatLength
)
{
    return STATUS_NOT_IMPLEMENTED;
};

/*****************************************************************************
 * CMiniportTopologyICH::Init
 *****************************************************************************
 * Initializes the miniport.
 * We initialize the translation tables, add reference to the port driver and
 * build the topology.
 */
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::Init
(
    IN      PUNKNOWN        UnknownAdapter,
    IN      PRESOURCELIST   ResourceList,
    IN      PPORTTOPOLOGY   Port_
)
{
    PAGED_CODE ();

    ASSERT (UnknownAdapter);
    ASSERT (Port_);

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

    //
    // Set the copy protect flag to FALSE.
    //
    m_bCopyProtectFlag = FALSE;

    // 
    // get the IAdapterCommon interface from the adapter.
    //
    NTSTATUS ntStatus = UnknownAdapter->QueryInterface (IID_IAdapterCommon,
                                                       (PVOID *) &AdapterCommon);

    //
    // initialize translation tables
    //
    for (int i = 0; i < PIN_TOP_ELEMENT; i++)
    {
        stPinTrans[i].PinDef = PIN_INVALID;
        stPinTrans[i].PinNr = -1;
    }

    for (i = 0; i < NODE_TOP_ELEMENT; i++)
    {
        stNodeTrans[i].NodeDef = NODE_INVALID;
        stNodeTrans[i].NodeNr = -1;
    }

    // build the topology (means register pins, nodes, connections).
    if (NT_SUCCESS (ntStatus))
    {
        ntStatus = BuildTopology ();
    }
    
    if (NT_SUCCESS (ntStatus))
    {
        //
        // Notify AdapterCommon that we are ready now.
        //
        AdapterCommon->SetMiniportTopology (this);
    }
    else
    {
        //
        // clean up our mess
        //

        // clean up AdapterCommon
        if (AdapterCommon)
        {
            AdapterCommon->Release ();
            AdapterCommon = NULL;
        }
    }

    return ntStatus;
}

/*****************************************************************************
 * CMiniportTopologyICH::GetDescription
 *****************************************************************************
 * Gets/returns the topology to the system.
 */
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::GetDescription
(
    OUT     PPCFILTER_DESCRIPTOR *  OutFilterDescriptor
)
{
    PAGED_CODE ();

    ASSERT (OutFilterDescriptor);

    DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetDescription]"));

#if (DBG)
    // Dump it here. The system requests the topology only once.
    DumpTopology ();
#endif

    if (FilterDescriptor)
    {
        *OutFilterDescriptor = FilterDescriptor;
        return STATUS_SUCCESS;
    }
    else
        return STATUS_DEVICE_CONFIGURATION_ERROR;
}

#if (DBG)
/*****************************************************************************
 * CMiniportTopologyICH::DumpTopology
 *****************************************************************************
 * Dumps the topology for debugging.
 * See the defines at the beginning of this file?
 */
void CMiniportTopologyICH::DumpTopology (void)
{
    PAGED_CODE ();

    if (FilterDescriptor)
    {
        // dump the pins
        DOUT (DBG_PINS, ("TOPOLOGY MINIPORT PINS"));
        for(ULONG index = 0; index < FilterDescriptor->PinCount; index++)
        {
            DOUT (DBG_PINS, ("  %2d %s", index,
                             TopoPinStrings[TransPinNrToPinDef (index)]));
        }

        // dump the nodes
        DOUT (DBG_NODES, ("TOPOLOGY MINIPORT NODES"));
        for(index = 0; index < FilterDescriptor->NodeCount; index++)
        {
            DOUT (DBG_NODES, ("  %2d %s", index,
                              NodeStrings[TransNodeNrToNodeDef (index)]));
        }

        // dump the connections
        DOUT (DBG_CONNS, ("TOPOLOGY MINIPORT CONNECTIONS"));
        for(index = 0; index < FilterDescriptor->ConnectionCount; index++)
        {
            DOUT (DBG_CONNS, ("  %2d (%d,%d)->(%d,%d)", index,
                FilterDescriptor->Connections[index].FromNode,
                FilterDescriptor->Connections[index].FromNodePin,
                FilterDescriptor->Connections[index].ToNode,
                FilterDescriptor->Connections[index].ToNodePin));
        }
    }
}
#endif


/*****************************************************************************
 * Miniport Topology               V = Volume, M = Mute, L = Loudness, A = AGC
 *====================             T = Treble, B = Bass, 0-9 = PinNr of node
 *
 * PCBEEP ---> V ---> M -----------------------------\
 * PHONE  ---> V ---> M ----------------------------\ \
 *                                                   \ \
 * WaveOut -------> V --> M --------------> 1+-----+  \ \
 * MIC1 or MIC2 --> L --> A --> V --> M --> 2| SUM |   \ \
 * LineIn  -------> V --> M --------------> 3|     |    \ \
 * CD      -------> V --> M --------------> 4|     |0--->SUM--> T --> B --> L --> V --> M (MasterOut)
 * Video   -------> V --> M --------------> 5|     |
 * AUX     -------> V --> M --------------> 6|     |
 * 3D Depth  -----> V --> L --> A --------> 7|     |
 * 3D Center -----> V --> L --> A --------> 8|     |
 * Headphone -----> V --> M --------------> 9|     |
 * Front Speaker -> V --> M -------------->10|     |
 * Surround ------> V --> M -------------->11|     |
 * Center   ------> V --> M -------------->12|     |
 * LFE      ------> V --> M -------------->13+-----+
 *
 * 
 * virt. Pin: Tone mix mono   ---> V --> M ---> 7+-------+
 * virt. Pin: Tone mix stereo ---> V --> M ---> 6|       |
 * Phone                      ---> V --> M ---> 8|   M   |
 * Mic (after AGC)            ---> V --> M ---> 1|       |0-----> (WaveIn)
 * LineIn                     ---> V --> M ---> 5|   U   |
 * CD                         ---> V --> M ---> 2|       |
 * Video                      ---> V --> M ---> 3|   X   |
 * AUX                        ---> V --> M ---> 4+-------+
 *
 *
 * virt. Pin: 3D mix mono ---> V ---> M ---> 1+-----+
 *                                            | MUX |0----> (MonoOut)
 * Mic (after AGC)        ---> V ---> M ---> 2+-----+
 *
 *
 * Mic (after AGC) ----> V ----> M -----> (MicIn)
 *
 *----------------------------------------------------------------------------
 *
 * As you can see, the exposed topology is somewhat different from the real AC97
 * topology. This is because the system that translates the topology to "mixer
 * lines" gets confused if it has to deal with all the mess. So we have to make it
 * plain and simple for the system.
 * Some issues block us from exposing a nice plain and simple topology. The prg.
 * which displayes the "Volume Control Panel" (sndvol32) does _only_ display
 * Volumes, Mutes (only one "in a row"), Treble, Bass, Loudness and AGC under
 * Advanced control panel. We don't have 3D controls, and before we go into a
 * Muxer, there has to be Volume controls in front.
 * So what do we do?
 * 1) We fake 3D controls as Volume controls. The Mutes represent 3D bypass and
 *    3D on/off
 * 2) All inputs (including the 3D controls) go staight into a SUM. Important is
 *    that there are not 2 Volumes, Mutes in a row, e.g. ---> V ---> M ---> V ---> M
 *    In that case, only one Volume/Mute would be displayed.
 * 3) We can't make a connection from the tone controls to the Wave In muxer (even
 *    with Volumes in front), so we create fake pins that we name user friendly.
 *    Same with the connection from the 3D mixer to the Mono output.
 * 4) We discard all supermixer controls that would convert stereo to mono or vice
 *    versa. Instead, we just connect the lines and when the control is queried we
 *    fail a right channel request (mono has only left channel).
 * 5) We have to make virtual volume and mute controls in front of each muxer.
 *    As you can see, these controls can be mono or stereo and there is only one
 *    HW register for them, so we have to cache the values and prg. the register
 *    each time the select changes or the selected volume control changes.
 */

/*****************************************************************************
 * CMiniportTopologyICH::BuildTopology
 *****************************************************************************
 * Builds the topology descriptors based on hardware configuration info
 * obtained from the adapter.
 */
NTSTATUS CMiniportTopologyICH::BuildTopology (void)
{
    PAGED_CODE ();

    NTSTATUS ntStatus = STATUS_SUCCESS;

    DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildTopology]"));

    // allocate our filter descriptor
    FilterDescriptor = (PPCFILTER_DESCRIPTOR) ExAllocatePool (PagedPool,
                        sizeof(PCFILTER_DESCRIPTOR));
    if (FilterDescriptor)
    {
        // clear out the filter descriptor
        RtlZeroMemory (FilterDescriptor, sizeof(PCFILTER_DESCRIPTOR));

#ifdef INCLUDE_PRIVATE_PROPERTY
        // Set the Filter automation table.
        FilterDescriptor->AutomationTable = &FilterAutomationPrivate;
#endif

        // build the pin list
        ntStatus = BuildPinDescriptors ();
        if (NT_SUCCESS (ntStatus))
        {
            // build the node list
            ntStatus = BuildNodeDescriptors ();
            if (NT_SUCCESS (ntStatus))
            {
                // build the connection list
                ntStatus = BuildConnectionDescriptors ();
            }
        }
    }
    else
    {
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    // that's whatever one of these build... functions returned.
    return ntStatus;
}

/*****************************************************************************
 * CMiniportTopologyICH::BuildPinDescriptors
 *****************************************************************************
 * Builds the topology pin descriptors.
 */
NTSTATUS CMiniportTopologyICH::BuildPinDescriptors (void)
{
// Improvement would be to not use a Macro, use (inline) function instead.
#define INIT_PIN( pin, pinptr, category, name, index )      \
    pinptr->KsPinDescriptor.Category = (GUID*) category;    \
    pinptr->KsPinDescriptor.Name = (GUID*) name;            \
    SetPinTranslation (index++, pin);                       \
    pinptr++   

    PAGED_CODE ();

    ULONG               Index;
    PPCPIN_DESCRIPTOR   CurrentPin;

    DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildPinDescriptors]"));

    // allocate our descriptor memory
    PinDescriptors = PPCPIN_DESCRIPTOR (ExAllocatePool (PagedPool,
                                PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR)));
    if (!PinDescriptors)
        return STATUS_INSUFFICIENT_RESOURCES;

    //
    // set default pin descriptor parameters
    //
    RtlZeroMemory (PinDescriptors, PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR));
    
    // spend some more time and set the pin descriptors to expected values.
    for (CurrentPin = PinDescriptors, Index = 0; Index < PIN_TOP_ELEMENT;
         CurrentPin++, Index++)
    {
        CurrentPin->KsPinDescriptor.DataRangesCount = SIZEOF_ARRAY(PinDataRangePointersAnalogBridge);
        CurrentPin->KsPinDescriptor.DataRanges      = PinDataRangePointersAnalogBridge;
        CurrentPin->KsPinDescriptor.DataFlow        = KSPIN_DATAFLOW_IN;
        CurrentPin->KsPinDescriptor.Communication   = KSPIN_COMMUNICATION_NONE;
    }

    //
    // modify the individual pin descriptors

⌨️ 快捷键说明

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