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

📄 common.cpp

📁 AC97 Sample Driver and Related Code Samples. This directory contains a sample AC97 adapter driver a
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            WriteCodecRegister (AC97REG_POWERDOWN, 0x0700, -1);
            break;

        case PowerDeviceD2:
        case PowerDeviceD3:
            //
            // This is a full hibernation state and is the longest latency sleep
            // state. In this modes the power could be removed or reduced that
            // much that the AC97 controller looses information, so we save
            // whatever we have to save.
            //

            //
            // Powerdown ADC, DAC, Mixer, Vref, HP amp, and Exernal Amp but not
            // AC-link and Clk
            //
            WriteCodecRegister (AC97REG_POWERDOWN, 0xCF00, -1);

            //
            // Only in D3 mode we set the AD3 bit and evtl. shut off the AC link.
            //
            if (NewState.DeviceState == PowerDeviceD3)
            {
                //
                // Set the AD3 bit.
                //
                ULONG ulReg = ReadBMControlRegister32 (GLOB_STA);
                WriteBMControlRegister (GLOB_STA, ulReg | GLOB_STA_AD3);
                
                //
                // We check if the modem is sleeping. If it is, we can shut off the
                // AC link also. We shut off the AC link also if the modem is not
                // there.
                //
                if ((ulReg & GLOB_STA_MD3) || !(ulReg & GLOB_STA_SCR))
                {
                    // Set Codec to super sleep
                    WriteCodecRegister (AC97REG_POWERDOWN, 0xFF00, -1);
    
                    // Disable the AC-link signals
                    ulReg = ReadBMControlRegister32 (GLOB_CNT);
                    WriteBMControlRegister (GLOB_CNT, (ulReg | GLOB_CNT_ACLOFF) & ~GLOB_CNT_COLD);
                }
            }
            break;
    }
    
    //
    // Save the new state.  This local value is used to determine when to 
    // cache property accesses and when to permit the driver from accessing 
    // the hardware.
    //
    m_PowerState = NewState.DeviceState;
    DOUT (DBG_POWER, ("Entering D%d", (ULONG)m_PowerState -
                      (ULONG)PowerDeviceD0));
}


/*****************************************************************************
 * CAdapterCommon::QueryPowerChangeState
 *****************************************************************************
 * Query to see if the device can change to this power state
 */
STDMETHODIMP_(NTSTATUS) CAdapterCommon::QueryPowerChangeState
(
    IN  POWER_STATE NewState
)
{
    PAGED_CODE ();

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

    // Check here to see of a legitimate state is being requested
    // based on the device state and fail the call if the device/driver
    // cannot support the change requested.  Otherwise, return STATUS_SUCCESS.
    // Note: A QueryPowerChangeState() call is not guaranteed to always preceed
    // a PowerChangeState() call.

    // check the new state being requested
    switch (NewState.DeviceState)
    {
        case PowerDeviceD0:
        case PowerDeviceD1:
        case PowerDeviceD2:
        case PowerDeviceD3:
            return STATUS_SUCCESS;
        
        default:
            DOUT (DBG_ERROR, ("Unknown device state: D%d.", 
                 (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
            return STATUS_NOT_IMPLEMENTED;
    }
}


/*****************************************************************************
 * CAdapterCommon::QueryDeviceCapabilities
 *****************************************************************************
 * Called at startup to get the caps for the device.  This structure provides
 * the system with the mappings between system power state and device power
 * state.  This typically will not need modification by the driver.
 * If the driver modifies these mappings then the driver is not allowed to
 * change the mapping to a weaker power state (e.g. from S1->D3 to S1->D1).
 * 
 */
STDMETHODIMP_(NTSTATUS) CAdapterCommon::QueryDeviceCapabilities
(
    IN  PDEVICE_CAPABILITIES PowerDeviceCaps
)
{
    PAGED_CODE ();

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

    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CAdapterCommon::RestoreAC97Registers
 *****************************************************************************
 * Preset the AC97 registers with default values. The routine first checks if
 * There are registry entries for the default values. If not, we have hard
 * coded values too ;)
 */
NTSTATUS CAdapterCommon::SetAC97Default (void)
{
    PAGED_CODE ();
    
    PREGISTRYKEY    DriverKey;
    PREGISTRYKEY    SettingsKey;
    UNICODE_STRING  sKeyName;
    ULONG           ulDisposition;
    ULONG           ulResultLength;
    PVOID           KeyInfo = NULL;

    DOUT (DBG_PRINT, ("[CAdapterCommon::SetAC97Default]"));
    
    // open the driver registry key
    NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey,        // IRegistryKey
                                          NULL,              // OuterUnknown
                                          DriverRegistryKey, // Registry key type
                                          KEY_READ,          // Access flags
                                          m_pDeviceObject,   // Device object
                                          NULL,              // Subdevice
                                          NULL,              // ObjectAttributes
                                          0,                 // Create options
                                          NULL);             // Disposition
    if (NT_SUCCESS (ntStatus))
    {
        // make a unicode string for the subkey name
        RtlInitUnicodeString (&sKeyName, L"Settings");

        // open the settings subkey
        ntStatus = DriverKey->NewSubKey (&SettingsKey,            // Subkey
                                         NULL,                    // OuterUnknown
                                         KEY_READ,                // Access flags
                                         &sKeyName,               // Subkey name
                                         REG_OPTION_NON_VOLATILE, // Create options
                                         &ulDisposition);

        if (NT_SUCCESS (ntStatus))
        {
            // allocate data to hold key info
            KeyInfo = ExAllocatePool (PagedPool,
                                      sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
                                      sizeof(WORD));
            if (NULL != KeyInfo)
            {
                // loop through all mixer settings
                for (AC97Register i = AC97REG_RESET; i <= AC97REG_RESERVED2;
                    i = (AC97Register)(i + 1))
                {
                    if (m_stAC97Registers[i].wFlags & SHREG_INIT)
                    {
                        // init key name
                        RtlInitUnicodeString (&sKeyName,
                                              m_stAC97Registers[i].sRegistryName);
    
                        // query the value key
                        ntStatus = SettingsKey->QueryValueKey (&sKeyName,
                                        KeyValuePartialInformation,
                                        KeyInfo,
                                        sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
                                            sizeof(WORD),
                                        &ulResultLength);
                        if (NT_SUCCESS (ntStatus))
                        {
                            PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
                                        (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;

                            if (PartialInfo->DataLength == sizeof(WORD))
                            {
                                // set mixer register to registry value
                                WriteCodecRegister
                                    (i, *(PWORD)PartialInfo->Data, -1);
                            }
                            else    // write the hard coded default
                            {
                                // if key access failed, set to default
                                WriteCodecRegister
                                    (i, m_stAC97Registers[i].wWantedDefault, -1);
                            }
                        }
                        else  // write the hard coded default
                        {
                            // if key access failed, set to default
                            WriteCodecRegister
                                (i, m_stAC97Registers[i].wWantedDefault, -1);
                        }
                    }
                }

                // we want to return status success even if the last QueryValueKey
                // failed.
                ntStatus = STATUS_SUCCESS;

                // free the key info
                ExFreePool (KeyInfo);
            }

            // release the settings key
            SettingsKey->Release ();
        }

        // release the driver key
        DriverKey->Release ();
    }


    // in case we did not query the registry (cause of lack of resources)
    // restore default values and return insufficient resources.
    if (!NT_SUCCESS (ntStatus) || !KeyInfo)
    {
        // copy hard coded default settings
        for (AC97Register i = AC97REG_RESET; i < AC97REG_RESERVED2;
             i = (AC97Register)(i + 1))
        {
            if (m_stAC97Registers[i].wFlags & SHREG_INIT)
            {
                WriteCodecRegister (i, m_stAC97Registers[i].wWantedDefault, -1);
            }
        }

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    return ntStatus;
}


/*****************************************************************************
 * CAdapterCommon::DisableAC97Pin
 *****************************************************************************
 * Returns TRUE when the HW vendor wants to disable the pin. A disabled pin is
 * not shown to the user (means it is not included in the topology). The
 * reason for doing this could be that some of the input lines like Aux or
 * Video are not available to the user (to plug in something) but the codec
 * can handle those lines.
 */
BOOL CAdapterCommon::DisableAC97Pin
(
    IN  TopoPinConfig pin
)
{
    PAGED_CODE ();

    PREGISTRYKEY    DriverKey;
    PREGISTRYKEY    SettingsKey;
    UNICODE_STRING  sKeyName;
    ULONG           ulDisposition;
    ULONG           ulResultLength;
    PVOID           KeyInfo = NULL;
    BOOL            bDisable = FALSE;

    DOUT (DBG_PRINT, ("[CAdapterCommon::DisableAC97Pin]"));
    
    // open the driver registry key
    NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey,        // IRegistryKey
                                          NULL,              // OuterUnknown
                                          DriverRegistryKey, // Registry key type
                                          KEY_READ,          // Access flags
                                          m_pDeviceObject,   // Device object
                                          NULL,              // Subdevice
                                          NULL,              // ObjectAttributes
                                          0,                 // Create options
                                          NULL);             // Disposition
    if (NT_SUCCESS (ntStatus))
    {
        // make a unicode string for the subkey name
        RtlInitUnicodeString (&sKeyName, L"Settings");

        // open the settings subkey
        ntStatus = DriverKey->NewSubKey (&SettingsKey,            // Subkey
                                         NULL,                    // OuterUnknown
                                         KEY_READ,                // Access flags
                                         &sKeyName,               // Subkey name
                                         REG_OPTION_NON_VOLATILE, // Create options
                                         &ulDisposition);

        if (NT_SUCCESS (ntStatus))
        {
            // allocate data to hold key info
            KeyInfo = ExAllocatePool (PagedPool,
                                      sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
                                      sizeof(BYTE));
            if (NULL != KeyInfo)
            {
                // init key name
                RtlInitUnicodeString (&sKeyName, m_stHardwareConfig.
                                            Pins[pin].sRegistryName);
    
                // query the value key
                ntStatus = SettingsKey->QueryValueKey (&sKeyName,
                                   KeyValuePartialInformation,
                                   KeyInfo,
                                   sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
                                        sizeof(BYTE),
                                   &ulResultLength );
                if (NT_SUCCESS (ntStatus))
                {
                    PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
                                (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;

                    if (PartialInfo->DataLength == sizeof(BYTE))
                    {
                        // store the value
                        if (*(PBYTE)PartialInfo->Data)
                            bDisable = TRUE;
                        else
                            bDisable = FALSE;
                    }
                }

                // free the key info
                ExFreePool (KeyInfo);
            }

            // release the settings key
            SettingsKey->Release ();
        }

        // release the driver key
        DriverKey->Release ();
    }

    // if one of the stuff above fails we return the default, which is FALSE.
    return bDisable;
}


/*****************************************************************************
 * CAdapterCommon::RestoreCodecRegisters
 *****************************************************************************
 * write back cached mixer values to codec registers
 */
NTSTATUS CAdapterCommon::RestoreCodecRegisters (void)
{
    PAGED_CODE ();

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

    //
    // Initialize the AC97 codec.
    //
    NTSTATUS ntStatus = InitAC97 ();
    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    //
    // Restore all codec registers.  Failure is not critical.
    //
    for (AC97Register i = AC97REG_MASTER_VOLUME; i < AC97REG_RESERVED2; 
        i = (AC97Register)(i + 1))
    {
        WriteCodecRegister (i, m_stAC97Registers[i].wCache, -1);
    }

    return STATUS_SUCCESS;
}

/*****************************************************************************
 * CAdapterCommon::ReadChannelConfigDefault
 *****************************************************************************
 * This function reads the default channel config from the registry. The
 * registry entry "ChannelConfig" is set every every time we get a
 * KSPROPERTY_AUDIO_CHANNEL_CONFIG for the DAC node.
 * In case the key doesn't exist we assume a channel config of stereo speakers,
 * cause that is the default of DSOUND.
 */
STDMETHODIMP_(void) CAdapterCommon::ReadChannelConfigDefault
(
    PDWORD  pdwChannelConfig,
    PWORD   pwChannels
)
{
    PAG

⌨️ 快捷键说明

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