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

📄 common.cpp

📁 AC97 Sample Driver and Related Code Samples. This directory contains a sample AC97 adapter driver a
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        SetPinConfig (PINC_VIDEO_PRESENT, FALSE);

    //
    // Test for Aux support.
    //
    ntStatus = ReadCodecRegister (AC97REG_AUX_VOLUME, &wCodecReg);
    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    // Default is 0x8808.
    SetPinConfig (PINC_AUX_PRESENT, (wCodecReg == 0x8808));

    // Check if OEM wants to disable aux input.
    if (DisableAC97Pin (PINC_AUX_PRESENT))
        SetPinConfig (PINC_AUX_PRESENT, FALSE);

    //
    // Test for Mic2 source.
    //
    ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    // Test for Mic2 select bit.
    if (wCodecReg & 0x0100)
        SetPinConfig (PINC_MIC2_PRESENT, TRUE);
    else
    {
        // Select Mic2 as source.
        ntStatus = WriteCodecRegister (AC97REG_GENERAL, 0x0100, 0x0100);
        if (!NT_SUCCESS (ntStatus))
            return ntStatus;

        // Read back.
        ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
        if (!NT_SUCCESS (ntStatus))
            return ntStatus;

        if (wCodecReg & 0x0100)
        {
            // Yep, we have support so set it to the default value.
            SetPinConfig (PINC_MIC2_PRESENT, TRUE);
            // reset to default value.
            WriteCodecRegister (AC97REG_GENERAL, 0, 0x0100);
        }
        else
            SetPinConfig (PINC_MIC2_PRESENT, FALSE);
    }

    // Check if OEM wants to disable mic2 input.
    if (DisableAC97Pin (PINC_MIC2_PRESENT))
        SetPinConfig (PINC_MIC2_PRESENT, FALSE);

    //
    // Test the 3D controls.
    //
    if (GetNodeConfig (NODEC_3D_PRESENT))
    {
        //
        // First test for fixed 3D controls. Write default value ...
        //
        ntStatus = WriteCodecRegister (AC97REG_3D_CONTROL, 0, -1);
        if (!NT_SUCCESS (ntStatus))
            return ntStatus;

        // Read 3D register. Default is 0 when adjustable, otherwise it is
        // a fixed value.
        ntStatus = ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
        if (!NT_SUCCESS (ntStatus))
            return ntStatus;

        //
        // Check center and depth separately.
        //

        // For center
        SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, !(wCodecReg & 0x0F00));

        // For depth
        SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, !(wCodecReg & 0x000F));

        //
        // Test for adjustable controls.
        //
        WriteCodecRegister (AC97REG_3D_CONTROL, 0x0A0A, -1);

        // Read 3D register. Now it should be 0x0A0A for adjustable controls,
        // otherwise it is a fixed control or simply not there.
        ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);

        // Restore the default value
        WriteCodecRegister (AC97REG_3D_CONTROL, 0, -1);

        // Check the center control for beeing adjustable
        if (GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
            (wCodecReg & 0x0F00) != 0x0A00)
        {
            SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, FALSE);
        }
        
        // Check the depth control for beeing adjustable
        if (GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
            (wCodecReg & 0x000F) != 0x000A)
        {
            SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, FALSE);
        }
    }

    //
    // Check for 6th bit support in volume controls.  To check the 6th bit, 
    // we first have to write a value (with 6th bit set) and then read it 
    // back.  After that, we should restore the register to its default value.
    //

    //
    // Start with the master volume.
    //
    Check6thBitSupport (AC97REG_MASTER_VOLUME, NODEC_6BIT_MASTER_VOLUME);

    //
    // Check for a headphone volume control.
    //
    if (GetPinConfig (PINC_HPOUT_PRESENT))
    {
        Check6thBitSupport (AC97REG_HPHONE_VOLUME, NODEC_6BIT_HPOUT_VOLUME);
    }

    //
    // Mono out there?
    //
    if (GetPinConfig (PINC_MONOOUT_PRESENT))
    {
        Check6thBitSupport (AC97REG_MMONO_VOLUME, NODEC_6BIT_MONOOUT_VOLUME);
    }

    //
    // Get extended AC97 V2.0 information
    //
    ntStatus = ReadCodecRegister (AC97REG_EXT_AUDIO_ID, &wCodecReg);
    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    //
    // Store the information
    //
    SetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED, wCodecReg & 0x0001);
    SetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED, wCodecReg & 0x0002);
    SetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED, wCodecReg & 0x0008);
    SetNodeConfig (NODEC_CENTER_DAC_PRESENT, wCodecReg & 0x0040);
    SetNodeConfig (NODEC_SURROUND_DAC_PRESENT, wCodecReg & 0x0080);
    SetNodeConfig (NODEC_LFE_DAC_PRESENT, wCodecReg & 0x0100);

    //
    // In case we have some features get some more information and program
    // the codec.
    //
    if (wCodecReg)
    {
        //
        // Enable variable sample rate in the control register and disable
        // double rate. Also enable all DACs.
        //
        WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, wCodecReg & 0x0009, 0x380B);

        //
        // Check for codecs that have only one sample rate converter. These
        // codecs will stick registers AC97REG_FRONT_SAMPLERATE and
        // AC97REG_RECORD_SAMPLERATE together.
        //
        if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
        {
            // The default of the sample rate registers should be 0xBB80.
            WriteCodecRegister (AC97REG_FRONT_SAMPLERATE, 0xBB80, 0xFFFF);

            // Write 44.1KHz into record VSR, then check playback again.
            WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xAC44, 0xFFFF);
            ntStatus = ReadCodecRegister (AC97REG_FRONT_SAMPLERATE, &wCodecReg);
            WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xBB80, 0xFFFF);
            if (!NT_SUCCESS (ntStatus))
                return ntStatus;

            //
            // Set the flag accordingly
            //
            SetNodeConfig (NODEC_PCM_VSR_INDEPENDENT_RATES, (wCodecReg == 0xBB80));
        }

        //
        // Check multichanel support on the ICH.
        //
        if (GetNodeConfig (NODEC_SURROUND_DAC_PRESENT))
        {
            dwGlobalStatus = ReadBMControlRegister32 (GLOB_STA);
            
            //
            // Codec supports >2 chanel, does ICH too?
            //
            if ((GetNodeConfig (NODEC_CENTER_DAC_PRESENT) ||
                GetNodeConfig (NODEC_LFE_DAC_PRESENT)) &&
                (dwGlobalStatus & GLOB_STA_MC6))
            {
                SetPinConfig (PINC_CENTER_LFE_PRESENT, TRUE);
            }
            else
            {
                SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
            }

            //
            // Do we support at least 4 channels?
            //
            SetPinConfig (PINC_SURROUND_PRESENT, (dwGlobalStatus & GLOB_STA_MC4));
        }
        else
        {
            //
            // Only 2 channel (stereo) support.
            //
            SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
            SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
        }
    }

    // Check if OEM wants to disable surround output.
    if (DisableAC97Pin (PINC_SURROUND_PRESENT))
        SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
    
    // Check if OEM wants to disable center and LFE output.
    if (DisableAC97Pin (PINC_CENTER_LFE_PRESENT))
        SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);

    //
    // Check the 6th bit support for the additional channels.
    //
    if (GetPinConfig (PINC_SURROUND_PRESENT))
        Check6thBitSupport (AC97REG_SURROUND_VOLUME, NODEC_6BIT_SURROUND_VOLUME);
    
    if (GetPinConfig (PINC_CENTER_LFE_PRESENT))
        Check6thBitSupport (AC97REG_CENTER_LFE_VOLUME, NODEC_6BIT_CENTER_LFE_VOLUME);

    //
    // We read these registers because they are dependent on the codec.
    //
    ReadCodecRegister (AC97REG_VENDOR_ID1, &wCodecReg);
    ReadCodecRegister (AC97REG_VENDOR_ID2, &wCodecReg);

    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CAdapterCommon::AcquireCodecSemiphore
 *****************************************************************************
 * Acquires the AC97 semiphore.  This can not be called at dispatch level
 * because it can timeout if a lower IRQL thread has the semaphore.
 */
NTSTATUS CAdapterCommon::AcquireCodecSemiphore ()
{
    PAGED_CODE ();

    DOUT (DBG_PRINT, ("[CAdapterCommon::AcquireCodecSemiphore]"));

    ULONG ulCount = 0;
    while (READ_PORT_UCHAR (m_pBusMasterBase + CAS) & CAS_CAS)
    {
        //
        // Do we want to give up??
        //
        if (ulCount++ > 100)
        {
            DOUT (DBG_ERROR, ("Cannot acquire semaphore."));
            return STATUS_IO_TIMEOUT;
        }

        //
        // Let's wait a little, 40us and then try again.
        //
        KeStallExecutionProcessor (40L);
    }

    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CAdapterCommon::ReadCodecRegister
 *****************************************************************************
 * Reads a AC97 register. Don't call at PASSIVE_LEVEL.
 */
STDMETHODIMP_(NTSTATUS) CAdapterCommon::ReadCodecRegister
(
    IN  AC97Register reg,
    OUT PWORD wData
)
{
    PAGED_CODE ();
    
    ASSERT (wData);
    ASSERT (reg < AC97REG_INVALID);    // audio can only be in the primary codec

    NTSTATUS ntStatus;
    ULONG    Status;

    DOUT (DBG_PRINT, ("[CAdapterCommon::ReadCodecRegister]"));
    
    //
    // Check if we have to access the HW directly.
    //
    if (m_bDirectRead || (m_stAC97Registers[reg].wFlags & SHREG_INVALID) ||
        (m_stAC97Registers[reg].wFlags & SHREG_NOCACHE))
    {
        //
        // Grab the codec access semiphore.
        //
        ntStatus = AcquireCodecSemiphore ();
        if (!NT_SUCCESS (ntStatus))
        {
            DOUT (DBG_ERROR, ("ReadCodecRegister couldn't acquire the semiphore"
                " for reg. %s", reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
                                reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
                                reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
                                "REG_INVALID"));
            return ntStatus;
        }

        //
        // Read the data.
        //
        *wData = READ_PORT_USHORT (m_pCodecBase + reg);

        //
        // Check to see if the read was successful.
        //
        Status = READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA));
        if (Status & GLOB_STA_RCS)
        {
            //
            // clear the timeout bit
            //
            WRITE_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA), Status);
            *wData = 0;
            DOUT (DBG_ERROR, ("ReadCodecRegister timed out for register %s",
                    reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
                    reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
                    reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
                    "REG_INVALID"));
            return STATUS_IO_TIMEOUT;
        } 
        
        //
        // Clear invalid flag
        //
        m_stAC97Registers[reg].wCache = *wData;
        m_stAC97Registers[reg].wFlags &= ~SHREG_INVALID;
        
        DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (HW)",
                reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
                reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
                reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" : 
                "REG_INVALID", *wData));
    }
    else
    {
        //
        // Otherwise, use the value in the cache.
        //
        *wData = m_stAC97Registers[reg].wCache;
        DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (C)",
                reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
                reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
                reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" : 
                "REG_INVALID", *wData));
    }

    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CAdapterCommon::WriteCodecRegister
 *****************************************************************************
 * Writes to a AC97 register.  This can only be done at passive level because
 * the AcquireCodecSemiphore call could fail!
 */
STDMETHODIMP_(NTSTATUS) CAdapterCommon::WriteCodecRegister
(
    IN  AC97Register reg,
    IN  WORD wData,
    IN  WORD wMask
)
{
    PAGED_CODE ();
    
    ASSERT (reg < AC97REG_INVALID);    // audio can only be in the primary codec

    WORD TempData = 0;
    NTSTATUS ntStatus = STATUS_SUCCESS;

    DOUT (DBG_PRINT, ("[CAdapterCommon::WriteCodecRegister]"));

    //

⌨️ 快捷键说明

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