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

📄 prophnd.cpp

📁 AC97 Sample Driver and Related Code Samples. This directory contains a sample AC97 adapter driver a
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/********************************************************************************
**    Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
**
**       Portions Copyright (c) 1998-1999 Intel Corporation
**
********************************************************************************/

// Every debug output has "Modulname text".
static char STR_MODULENAME[] = "prophnd: ";

#include <limits.h>
#include "mintopo.h"

// These are the values passed to the property handler in the instance
// parameter that normally represents the channel.
const LONG CHAN_LEFT   = 0;
const LONG CHAN_RIGHT  = 1;
const LONG CHAN_MASTER = -1;


// paged code goes here.
#pragma code_seg("PAGE")


/*****************************************************************************
 * CMiniportTopologyICH::SetMultichannelMute
 *****************************************************************************
 * This function is used to set one of the multichannel mutes.
 * It takes the master mono into account when calculating the mute.
 * Make sure that you updated the stNodeCache before calling this function.
 */
NTSTATUS CMiniportTopologyICH::SetMultichannelMute
(
    IN CMiniportTopologyICH *that,
    IN TopoNodes             Mute
)
{
    NTSTATUS    ntStatus = STATUS_SUCCESS;
    BOOL        bMute;

    // The first calls to SetMultichannelMute could be without valid
    // cache information because WDMAUD might currently query the nodes
    // (this is at system startup). When WDMAUD queried all nodes then
    // all cache information will be valid.
    if (that->stNodeCache[NODE_VIRT_MASTERMONO_MUTE].bLeftValid &&
        that->stNodeCache[Mute].bLeftValid)
    {
        // We get the master mono mute and the mute that is to change.
        // Then we "or" them and write the value to the register.
        bMute = that->stNodeCache[NODE_VIRT_MASTERMONO_MUTE].lLeft ||
                that->stNodeCache[Mute].lLeft;

        ntStatus = that->AdapterCommon->WriteCodecRegister (
                that->AdapterCommon->GetNodeReg (Mute),
                bMute ? -1 : 0,
                that->AdapterCommon->GetNodeMask (Mute));

        DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x", NodeStrings[Mute], (int)bMute));
    }

    return ntStatus;
}

/*****************************************************************************
 * CMiniportTopologyICH::SetMultichannelVolume
 *****************************************************************************
 * This function is used to set one of the multichannel volumes.
 * It takes the master mono into account when calculating the volume.
 * Make sure that you updated the stNodeCache before calling this function.
 */
NTSTATUS CMiniportTopologyICH::SetMultichannelVolume
(
    IN CMiniportTopologyICH *that,
    IN TopoNodes             Volume
)
{
    NTSTATUS        ntStatus = STATUS_SUCCESS;
    LONG            lMinimum, lMaximum;
    ULONG           uStep;
    LONG            lLevel;
    WORD            wRegister;
    
    // The first calls to SetMultichannelMute could be without valid
    // cache information because WDMAUD might currently query the nodes
    // (this is at system startup). When WDMAUD queried all nodes then
    // all cache information will be valid.
    if (that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].bLeftValid &&
        that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].bRightValid &&
        that->stNodeCache[Volume].bLeftValid &&
        that->stNodeCache[Volume].bRightValid)
    {
        // We get the master mono volume and the volume that is to change.
        // Then we substract master mono from it and write the value to the
        // register.
        lLevel = that->stNodeCache[Volume].lLeft +
                 that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].lLeft;

        // Translate the dB value into a register value.

        // Get the registered DB values
        ntStatus = GetDBValues (that->AdapterCommon, Volume,
                                &lMinimum, &lMaximum, &uStep);
        if (!NT_SUCCESS(ntStatus))
            return ntStatus;

        // Check borders.
        if (lLevel < lMinimum) lLevel = lMinimum;
        if (lLevel > lMaximum) lLevel = lMaximum;

        // Calculate the register value
        wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep) << 8;

        // Get the right value too.
        lLevel = that->stNodeCache[Volume].lRight +
                 that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].lRight;

        // Check borders.
        if (lLevel < lMinimum) lLevel = lMinimum;
        if (lLevel > lMaximum) lLevel = lMaximum;

        // Add it to the register value.
        wRegister += (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);

        // Write it.
        ntStatus = that->AdapterCommon->WriteCodecRegister (
                that->AdapterCommon->GetNodeReg (Volume),
                wRegister,
                that->AdapterCommon->GetNodeMask (Volume));

        DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x/0x%x", NodeStrings[Volume],
                             that->stNodeCache[Volume].lLeft +
                             that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].lLeft,
                             lLevel));
    }

    return ntStatus;
}

/*****************************************************************************
 * CMiniportTopologyICH::GetDBValues
 *****************************************************************************
 * This function is used internally and does no parameter checking. The only
 * parameter that could be invalid is the node.
 * It returns the dB values (means minimum, maximum, step) of the node control,
 * mainly for the property call "basic support". Sure, the node must be a
 * volume or tone control node, not a mute or mux node.
 */
NTSTATUS CMiniportTopologyICH::GetDBValues
(
    IN PADAPTERCOMMON AdapterCommon,
    IN TopoNodes Node,
    OUT LONG *plMinimum,
    OUT LONG *plMaximum,
    OUT ULONG *puStep
)
{
    DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetDBValues]"));
    
    // This is going to be simple. Check the node and return the parameters.
    switch (Node)
    {
        // These nodes could have 5bit or 6bit controls, so we first
        // have to check this.
        case NODE_MASTEROUT_VOLUME:
        case NODE_FRONT_VOLUME:
        case NODE_HPOUT_VOLUME:
        case NODE_SURROUND_VOLUME:
        case NODE_CENTER_VOLUME:
        case NODE_LFE_VOLUME:
        case NODE_VIRT_MONOOUT_VOLUME1:
        case NODE_VIRT_MONOOUT_VOLUME2:
            // needed for the config query
            TopoNodeConfig  config;

            // which node to query?
            config = NODEC_6BIT_MONOOUT_VOLUME;
            if ((Node == NODE_MASTEROUT_VOLUME) || (Node == NODE_FRONT_VOLUME))
                config = NODEC_6BIT_MASTER_VOLUME;
            if (Node == NODE_HPOUT_VOLUME)
                config = NODEC_6BIT_HPOUT_VOLUME;
            if (Node == NODE_SURROUND_VOLUME)
                config = NODEC_6BIT_SURROUND_VOLUME;
            if ((Node == NODE_CENTER_VOLUME) || (Node == NODE_LFE_VOLUME))
                config = NODEC_6BIT_CENTER_LFE_VOLUME;

            // check if we have 6th bit support.
            if (AdapterCommon->GetNodeConfig (config))
            {
                // 6bit control
                *plMaximum = 0;            // 0 dB
                *plMinimum = 0xFFA18000;   // -94.5 dB
                *puStep    = 0x00018000;   // 1.5 dB
            }
            else
            {
                // 5bit control
                *plMaximum = 0;            // 0 dB
                *plMinimum = 0xFFD18000;   // -46.5 dB
                *puStep    = 0x00018000;   // 1.5 dB
            }
            break;

        case NODE_VIRT_MASTERMONO_VOLUME:
            // This virtual control gets added to the speaker volumes.
            // We assume 5-bit volumes.
            *plMaximum = 0;            // 0 dB
            *plMinimum = 0xFFD18000;   // -46.5 dB
            *puStep    = 0x00018000;   // 1.5 dB
            break;

        case NODE_PCBEEP_VOLUME:
            *plMaximum = 0;            // 0 dB
            *plMinimum = 0xFFD30000;   // -45 dB
            *puStep    = 0x00030000;   // 3 dB
            break;

        case NODE_PHONE_VOLUME:
        case NODE_MICIN_VOLUME:
        case NODE_LINEIN_VOLUME:
        case NODE_CD_VOLUME:
        case NODE_VIDEO_VOLUME:
        case NODE_AUX_VOLUME:
        case NODE_WAVEOUT_VOLUME:
            *plMaximum = 0x000C0000;   // 12 dB
            *plMinimum = 0xFFDD8000;   // -34.5 dB
            *puStep    = 0x00018000;   // 1.5 dB
            break;

    
        case NODE_VIRT_MASTER_INPUT_VOLUME1:
        case NODE_VIRT_MASTER_INPUT_VOLUME2:
        case NODE_VIRT_MASTER_INPUT_VOLUME3:
        case NODE_VIRT_MASTER_INPUT_VOLUME4:
        case NODE_VIRT_MASTER_INPUT_VOLUME5:
        case NODE_VIRT_MASTER_INPUT_VOLUME6:
        case NODE_VIRT_MASTER_INPUT_VOLUME7:
        case NODE_VIRT_MASTER_INPUT_VOLUME8:
        case NODE_MIC_VOLUME:
            *plMaximum = 0x00168000;   // 22.5 dB
            *plMinimum = 0;            // 0 dB
            *puStep    = 0x00018000;   // 1.5 dB
            break;

        case NODE_BASS:
        case NODE_TREBLE:
            *plMaximum = 0x000A8000;   // 10.5 dB
            *plMinimum = 0xFFF58000;   // -10.5 dB
            *puStep    = 0x00018000;   // 1.5 dB
            break;

        // These nodes can be fixed or variable.
        // Normally we won't display a fixed volume slider, but if 3D is
        // supported and both sliders are fixed, we have to display one fixed
        // slider for the advanced control panel.
        case NODE_VIRT_3D_CENTER:
        case NODE_VIRT_3D_DEPTH:
            if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
               (Node == NODE_VIRT_3D_CENTER))
            {
                *plMaximum = 0x000F0000;   // +15 dB
                *plMinimum = 0x00000000;   // 0 dB
                *puStep    = 0x00010000;   // 1 dB
            }
            else
            if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
               (Node == NODE_VIRT_3D_DEPTH))
            {
                *plMaximum = 0x000F0000;   // +15 dB
                *plMinimum = 0x00000000;   // 0 dB
                *puStep    = 0x00010000;   // 1 dB
            }
            else
            {
                // In case it is fixed, read the value and return it.
                WORD wRegister;

                // read the register
                if (!NT_SUCCESS (AdapterCommon->ReadCodecRegister (
                            AdapterCommon->GetNodeReg (Node), &wRegister)))
                    wRegister = 0;      // in case we fail.

                // mask out the control
                wRegister &= AdapterCommon->GetNodeMask (Node);
                if (Node == NODE_VIRT_3D_CENTER)
                {
                    wRegister >>= 8;
                }
                // calculate the dB value.
                *plMaximum = (DWORD)(-wRegister) << 16;    // fixed value
                *plMinimum = (DWORD)(-wRegister) << 16;    // fixed value
                *puStep    = 0x00010000;   // 1 dB
            }
            break;

        case NODE_INVALID:
        default:
            // poeser pupe, tu.
            DOUT (DBG_ERROR, ("GetDBValues: Invalid node requested."));
            return STATUS_INVALID_PARAMETER;
    }

    return STATUS_SUCCESS;
}
 
/*****************************************************************************
 * CMiniportTopologyICH::PropertyHandler_OnOff
 *****************************************************************************
 * Accesses a KSAUDIO_ONOFF value property.
 * This function (property handler) is called by portcls every time there is a
 * get or a set request for the node. The connection between the node type and

⌨️ 快捷键说明

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