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

📄 miniport.cpp

📁 winddk src目录下的WDM源码压缩!
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ==============================================================================
//
// miniport.cpp - miniport driver implementation for FM synth.
// Copyright (c) 1996-2000 Microsoft Corporation.  All rights reserved.
//
// ==============================================================================

#include "private.h"    // contains class definitions.

#define STR_MODULENAME "FMSynth: "


#pragma code_seg("PAGE")
// ==============================================================================
// CreateMiniportMidiFM()
// Creates a MIDI FM miniport driver.  This uses a
// macro from STDUNK.H to do all the work.
// ==============================================================================
NTSTATUS CreateMiniportMidiFM
(
OUT     PUNKNOWN *  Unknown,
IN      REFCLSID    ClassID,
IN      PUNKNOWN    UnknownOuter    OPTIONAL,
IN      POOL_TYPE   PoolType
)
{
    PAGED_CODE();

    ASSERT(Unknown);

    _DbgPrintF(DEBUGLVL_VERBOSE, ("CreateMiniportMidiFM"));

//  expand STD_CREATE_BODY_ to take constructor(boolean) for whether to include volume
    NTSTATUS ntStatus;
    CMiniportMidiFM *p =  
        new(PoolType,'MFcP') CMiniportMidiFM(
                                 UnknownOuter,
                                 (IsEqualGUIDAligned(ClassID,CLSID_MiniportDriverFmSynthWithVol))
                             );

#ifdef DEBUG
    if (IsEqualGUIDAligned(ClassID,CLSID_MiniportDriverFmSynthWithVol))
    {
        _DbgPrintF(DEBUGLVL_VERBOSE, ("Creating new FM miniport with volume node"));
    }
#endif
    if (p)
    {
        *Unknown = PUNKNOWN((PMINIPORTMIDI)(p));
        (*Unknown)->AddRef();
        ntStatus = STATUS_SUCCESS;
    }
    else
    {
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }
    return ntStatus;
}

#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiFM::ProcessResources()
// Processes the resource list.
// ==============================================================================
NTSTATUS
CMiniportMidiFM::
ProcessResources
(
IN  PRESOURCELIST   ResourceList
)
{
    PAGED_CODE();

    ASSERT(ResourceList);
    if (!ResourceList)
    {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::ProcessResources"));

    //
    // Get counts for the types of resources.
    //
    ULONG       countIO     = ResourceList->NumberOfPorts();
    ULONG       countIRQ    = ResourceList->NumberOfInterrupts();
    ULONG       countDMA    = ResourceList->NumberOfDmas();

    NTSTATUS ntStatus = STATUS_SUCCESS;

    //
    // Make sure we have the expected number of resources.
    //
    if  (   (countIO != 1)
        ||  (countIRQ != 0)
        ||  (countDMA != 0)
        )
    {
        ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    if (NT_SUCCESS(ntStatus))
    {
        //
        // Get the port address.
        //
        m_PortBase = PUCHAR(ResourceList->FindTranslatedPort(0)->u.Port.Start.QuadPart);
        _DbgPrintF(DEBUGLVL_VERBOSE, ("Port Address = 0x%X", m_PortBase));
    }

    return ntStatus;
}

#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiFM::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) CMiniportMidiFM::NonDelegatingQueryInterface
(
REFIID  Interface,
PVOID * Object
)
{
    PAGED_CODE();

    ASSERT(Object);

    _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::NonDelegatingQueryInterface"));

    if (IsEqualGUIDAligned(Interface,IID_IUnknown))
    {
        *Object = PVOID(PUNKNOWN(PMINIPORT(this)));
    }
    else if (IsEqualGUIDAligned(Interface,IID_IMiniport))
    {
        *Object = PVOID(PMINIPORT(this));
    }
    else if (IsEqualGUIDAligned(Interface,IID_IMiniportMidi))
    {
        *Object = PVOID(PMINIPORTMIDI(this));
    }
    else if (IsEqualGUIDAligned(Interface, IID_IPowerNotify))
    {
        *Object = PVOID(PPOWERNOTIFY(this));
    }
    else
    {
        *Object = NULL;
    }

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

    return STATUS_INVALID_PARAMETER;
}

#pragma code_seg()
// ==============================================================================
// CMiniportMidiFM::~CMiniportMidiFM()
// Destructor.
// ==============================================================================
CMiniportMidiFM::~CMiniportMidiFM
(
void
)
{
    KIRQL   oldIrql;
    _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::~CMiniportMidiFM"));

    KeAcquireSpinLock(&m_SpinLock,&oldIrql);
    // Set silence on the device
    Opl3_BoardReset();

    KeReleaseSpinLock(&m_SpinLock,oldIrql);

    if (m_Port)
    {
        m_Port->Release();
    }
}

#pragma code_seg()
// ==============================================================================
// CMiniportMidiFM::Init()
// Initializes a the miniport.
// ==============================================================================
STDMETHODIMP_(NTSTATUS)
CMiniportMidiFM::
Init
(
    IN      PUNKNOWN        UnknownAdapter  OPTIONAL,
    IN      PRESOURCELIST   ResourceList,
    IN      PPORTMIDI       Port_,
    OUT     PSERVICEGROUP * ServiceGroup
)
{
    PAGED_CODE();

    ASSERT(ResourceList);
    if (!ResourceList)
    {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    ASSERT(Port_);
    ASSERT(ServiceGroup);

    int i;
    
    _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::init"));

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

    //
    // m_fStreamExists is not explicitly set to FALSE because C++ zeros 
    // them out on a 'new'
    //

    KeInitializeSpinLock(&m_SpinLock);
    //
    // We want the IAdapterCommon interface on the adapter common object,
    // which is given to us as a IUnknown.  The QueryInterface call gives us
    // an AddRefed pointer to the interface we want.
    //
    NTSTATUS ntStatus = ProcessResources(ResourceList);

    if (NT_SUCCESS(ntStatus))
    {
        KIRQL oldIrql;
        KeAcquireSpinLock(&m_SpinLock,&oldIrql);

        for (i = 0; i < 0x200; i++)    // initialize the shadow registers, used
           m_SavedRegValues[i] = 0x00; // in case of power-down during playback

        // Initialize the hardware.
        // 1. First check to see if an opl device is present.
        // 2. Then determine if it is an opl2 or opl3. Bail if opl2.
        // 3. Call Opl3_BoardReset to silence and reset the device.
        if (SoundSynthPresent(m_PortBase, m_PortBase))
        {
            // Now check if the device is an opl2 or opl3 type.
            // The patches are already declared for opl3. So Init() is not defined.
            // For opl2 we have to go through an init and load the patches structure.
            if (SoundMidiIsOpl3())
            {
                _DbgPrintF(DEBUGLVL_VERBOSE, ("CMiniportMidiFM::Init Type = OPL3"));
                // now silence the device and reset the board.
                Opl3_BoardReset();

                *ServiceGroup = NULL;
            }
            else
            {
                _DbgPrintF(DEBUGLVL_TERSE, ("CMiniportMidiFM::Init Type = OPL2"));
                ntStatus = STATUS_NOT_IMPLEMENTED;                
            }

        }
        else
        {
            _DbgPrintF(DEBUGLVL_TERSE, ("CMiniportMidiFM::Init SoundSynthPresent failed"));
            ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
        }
        KeReleaseSpinLock(&m_SpinLock,oldIrql);
    }
    else
    {
        _DbgPrintF(DEBUGLVL_TERSE, ("CMiniportMidiFM::Init ProcessResources failed"));
    }

    _DbgPrintF(DEBUGLVL_VERBOSE, ("CMiniportMidiFM::Init returning 0x%X", ntStatus));

    if (!NT_SUCCESS(ntStatus))
    {
        //
        // clean up our mess
        //

        // release the port
        m_Port->Release();
        m_Port = NULL;
    }

    return ntStatus;
}

#pragma code_seg("PAGE")
// ==============================================================================
// NewStream()
// Creates a new stream.
// ==============================================================================
STDMETHODIMP_(NTSTATUS) 
CMiniportMidiFM::
NewStream
(
    OUT     PMINIPORTMIDISTREAM *   Stream,
    IN      PUNKNOWN                OuterUnknown    OPTIONAL,
    IN      POOL_TYPE               PoolType,
    IN      ULONG                   Pin,
    IN      BOOLEAN                 Capture,
    IN      PKSDATAFORMAT           DataFormat,
    OUT     PSERVICEGROUP *         ServiceGroup
)
{
    PAGED_CODE();

    NTSTATUS ntStatus = STATUS_SUCCESS;

    if (m_fStreamExists)
    {
        _DbgPrintF(DEBUGLVL_TERSE,("CMiniportMidiFM::NewStream stream already exists"));
        ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    }
    else
    {
        _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::NewStream"));
        CMiniportMidiStreamFM *pStream =
            new(PoolType) CMiniportMidiStreamFM(OuterUnknown);

        if (pStream)
        {
            pStream->AddRef();

            ntStatus = pStream->Init(this,m_PortBase);

            if (NT_SUCCESS(ntStatus))
            {
                *Stream = PMINIPORTMIDISTREAM(pStream);
                (*Stream)->AddRef();

                *ServiceGroup = NULL;
                m_fStreamExists = TRUE;
            }

            pStream->Release();
        }
        else
        {
            _DbgPrintF(DEBUGLVL_TERSE,("CMiniportMidiFM::NewStream failed, no memory"));
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    return ntStatus;
}

#pragma code_seg("PAGE")
/*----------------------------------------------------------------------------
 FUNCTION NAME- CMiniportMidiFM::PowerChangeNotify()
 ENTRY      --- IN  POWER_STATE     NewState
                        power management status
 RETURN     --- void
 *------------------------------------------------------------------------- */
STDMETHODIMP_(void) CMiniportMidiFM::PowerChangeNotify(
    IN  POWER_STATE     PowerState
) 
{
    PAGED_CODE();
    _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::PowerChangeNotify(%d)",PowerState));

    switch (PowerState.DeviceState)
    {
        case PowerDeviceD0:
            if (m_PowerState.DeviceState != PowerDeviceD0) // check for power state delta
            {
                MiniportMidiFMResume();
            }
            break;

        case PowerDeviceD1:
        case PowerDeviceD2:
        case PowerDeviceD3:
        default:
            //  Don't need to do anything special, we always remember where we are.
            break;
    }
    m_PowerState.DeviceState = PowerState.DeviceState;
}

#pragma code_seg()
// ==========================================================================
// ==========================================================================
void
CMiniportMidiFM::
MiniportMidiFMResume()
{
    KIRQL   oldIrql;
    BYTE    i;
    

⌨️ 快捷键说明

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