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

📄 miniport.cpp

📁 提供了一个对mpu401芯片的接口的midi uart miniport的wdm驱动程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    ASSERT(ServiceGroup);

    _DbgPrintF(DEBUGLVL_BLAB,("Init"));

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

    for (ULONG bufferCount = 0;bufferCount < kMPUInputBufferSize;bufferCount++)
    {
        m_MPUInputBuffer[bufferCount] = 0;
    }
    m_MPUInputBufferHead = 0;
    m_MPUInputBufferTail = 0;
    m_KSStateInput = KSSTATE_STOP;

    NTSTATUS ntStatus = STATUS_SUCCESS;

    m_NumRenderStreams = 0;
    m_NumCaptureStreams = 0;
    _DbgPrintF(DEBUGLVL_VERBOSE,("Init: resetting m_NumRenderStreams and m_NumCaptureStreams"));

    m_UseIRQ = TRUE;
    if (ResourceList->NumberOfInterrupts() == 0)
    {
        m_UseIRQ = FALSE;
    }

    ntStatus = PcNewServiceGroup(&m_pServiceGroup,NULL);
    if (NT_SUCCESS(ntStatus) && !m_pServiceGroup)   //  keep any error
    {
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    if (NT_SUCCESS(ntStatus))
    {
        *ServiceGroup = m_pServiceGroup;
        m_pServiceGroup->AddRef();

		//
		// Register the service group with the port early so the port is
		// prepared to handle interrupts.
		//
		m_pPort->RegisterServiceGroup(m_pServiceGroup);
    }

    if (NT_SUCCESS(ntStatus) && m_UseIRQ)
    {
/*
        //
        //  Due to a bug in the InterruptSync design, we shouldn't share
        //  the interrupt sync object.  Whoever goes away first 
        //  will disconnect it, and the other points off into nowhere.
        //  
        //  Instead we generate our own interrupt sync object.
        //
        UnknownInterruptSync = NULL;
*/
        if (UnknownInterruptSync)
        {
            ntStatus = 
                UnknownInterruptSync->QueryInterface
                (
                    IID_IInterruptSync,
                    (PVOID *) &m_pInterruptSync
                );

            if (!m_pInterruptSync && NT_SUCCESS(ntStatus))  //  keep any error
            {
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
            if (NT_SUCCESS(ntStatus))
            {                                                                           //  run this ISR first
                ntStatus = m_pInterruptSync->
                    RegisterServiceRoutine(MPUInterruptServiceRoutine,PVOID(this),TRUE);
            }
        }
        else
        {   // create our own interruptsync mechanism.
            ntStatus = 
                PcNewInterruptSync
                (
                    &m_pInterruptSync,
                    NULL,
                    ResourceList,
                    0,                          // Resource Index
                    InterruptSyncModeNormal     // Run ISRs once until we get SUCCESS
                );

            if (!m_pInterruptSync && NT_SUCCESS(ntStatus))  //  keep any error
            {
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
            if (NT_SUCCESS(ntStatus))
            {
                ntStatus = m_pInterruptSync->RegisterServiceRoutine(
                    MPUInterruptServiceRoutine,
                    PVOID(this),
                    TRUE);                //  run this ISR first
            }
            if (NT_SUCCESS(ntStatus))
            {
                ntStatus = m_pInterruptSync->Connect();
            }
        }
    }

    if (NT_SUCCESS(ntStatus))
    {
        ntStatus = ProcessResources(ResourceList);
    }

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

        // clean up the interrupt sync
        if( m_pInterruptSync )
        {
//            m_pInterruptSync->Disconnect();
            m_pInterruptSync->Release();
            m_pInterruptSync = NULL;
        }

        // clean up the service group
        if( m_pServiceGroup )
        {
            m_pServiceGroup->Release();
            m_pServiceGroup = NULL;
        }
        (*ServiceGroup) = NULL;

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

    return ntStatus;
}

#pragma code_seg("PAGE")
/*****************************************************************************
 * CMiniportMidiUart::NewStream()
 *****************************************************************************
 * Gets the topology.
 */
STDMETHODIMP 
CMiniportMidiUart::
NewStream
(
    OUT     PMINIPORTMIDISTREAM *   Stream,
    IN      PUNKNOWN                OuterUnknown    OPTIONAL,
    IN      POOL_TYPE               PoolType,
    IN      ULONG                   PinID,
    IN      BOOLEAN                 Capture,
    IN      PKSDATAFORMAT           DataFormat,
    OUT     PSERVICEGROUP *         ServiceGroup
)
{
    PAGED_CODE();

    _DbgPrintF(DEBUGLVL_BLAB, ("NewStream"));
    NTSTATUS ntStatus = STATUS_SUCCESS;

    // if we don't have any streams already open, get the hardware ready.
    if ((!m_NumCaptureStreams) && (!m_NumRenderStreams))
    {
        _DbgPrintF(DEBUGLVL_VERBOSE,("NewStream: m_NumRenderStreams and m_NumCaptureStreams are both 0, so ResetMPUHardware"));
        (void) ResetMPUHardware(m_pPortBase);
    }
    else
    {
        _DbgPrintF(DEBUGLVL_VERBOSE,("NewStream: m_NumRenderStreams %d, m_NumCaptureStreams %d, no ResetMPUHardware",
                                     m_NumRenderStreams,m_NumCaptureStreams));
    }

    if  (   (   (m_NumCaptureStreams < kMaxNumCaptureStreams)
            &&  (Capture)  )
        ||  (   (m_NumRenderStreams < kMaxNumRenderStreams) 
            &&  (!Capture) )
        )
    {
        CMiniportMidiStreamUart *pStream =
            new(PoolType) CMiniportMidiStreamUart(OuterUnknown);

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

            ntStatus = 
                pStream->Init(this,m_pPortBase,Capture);

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

                if (Capture)
                {
                    m_NumCaptureStreams++;
                    *ServiceGroup = m_pServiceGroup;
                    (*ServiceGroup)->AddRef();
                }
                else
                {
                    m_NumRenderStreams++;
                    *ServiceGroup = NULL;
                }
                _DbgPrintF(DEBUGLVL_VERBOSE,("NewStream: succeeded, m_NumRenderStreams %d, m_NumCaptureStreams %d",
                                              m_NumRenderStreams,m_NumCaptureStreams));
            }

            pStream->Release();
        }
        else
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }
    else
    {
        ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        if (Capture)
        {
            _DbgPrintF(DEBUGLVL_TERSE,("NewStream failed, too many capture streams"));
        }
        else
        {
            _DbgPrintF(DEBUGLVL_TERSE,("NewStream failed, too many render streams"));
        }
    }

    return ntStatus;
}

#pragma code_seg("PAGE")
/*****************************************************************************
 * CMiniportMidiStreamUart::NonDelegatingQueryInterface()
 *****************************************************************************
 * Obtains an interface.  This function works just like a COM QueryInterface
 * call and is used if the object is not being aggregated.
 */
STDMETHODIMP
CMiniportMidiStreamUart::
NonDelegatingQueryInterface
(
    REFIID  Interface,
    PVOID * Object
)
{
    PAGED_CODE();

    _DbgPrintF(DEBUGLVL_BLAB,("Stream::NonDelegatingQueryInterface"));
    ASSERT(Object);

    if (IsEqualGUIDAligned(Interface,IID_IUnknown))
    {
        *Object = PVOID(PUNKNOWN(this));
    }
    else
    if (IsEqualGUIDAligned(Interface,IID_IMiniportMidiStream))
    {
        *Object = PVOID(PMINIPORTMIDISTREAM(this));
    }
    else
    {
        *Object = NULL;
    }

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

    return STATUS_INVALID_PARAMETER;
}

#pragma code_seg("PAGE")
/*****************************************************************************
 * CMiniportMidiStreamUart::SetFormat()
 *****************************************************************************
 * Sets the format.
 */
STDMETHODIMP
CMiniportMidiStreamUart::
SetFormat
(
    IN      PKSDATAFORMAT   Format
)
{
    PAGED_CODE();

    ASSERT(Format);

    _DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiStreamUart::SetFormat"));

    return STATUS_SUCCESS;
}

#pragma code_seg("PAGE")
/*****************************************************************************
 * CMiniportMidiStreamUart::~CMiniportMidiStreamUart()
 *****************************************************************************
 * Destructs a stream.
 */
CMiniportMidiStreamUart::~CMiniportMidiStreamUart(void)
{
    PAGED_CODE();

    _DbgPrintF(DEBUGLVL_BLAB,("~CMiniportMidiStreamUart"));

    if (m_pMiniport)
    {
        if (m_fCapture)
        {
            m_pMiniport->m_NumCaptureStreams--;
        }
        else
        {
            m_pMiniport->m_NumRenderStreams--;
        }
        _DbgPrintF(DEBUGLVL_VERBOSE,("~CMiniportMidiStreamUart: m_NumRenderStreams %d, m_NumCaptureStreams %d",
                                      m_pMiniport->m_NumRenderStreams,m_pMiniport->m_NumCaptureStreams));

        m_pMiniport->Release();
    }
    else
    {
        _DbgPrintF(DEBUGLVL_VERBOSE,("~CMiniportMidiStreamUart, no miniport!!!: m_NumRenderStreams %d, m_NumCaptureStreams %d",
                                      m_pMiniport->m_NumRenderStreams,m_pMiniport->m_NumCaptureStreams));
    }
}

#pragma code_seg("PAGE")
/*****************************************************************************
 * CMiniportMidiStreamUart::Init()
 *****************************************************************************
 * Initializes a stream.
 */
STDMETHODIMP 
CMiniportMidiStreamUart::
Init
(
    IN      CMiniportMidiUart * pMiniport,
    IN      PUCHAR              pPortBase,
    IN      BOOLEAN             fCapture
)
{
    PAGED_CODE();

    ASSERT(pMiniport);
    ASSERT(pPortBase);

    _DbgPrintF(DEBUGLVL_VERBOSE,("Init"));

    m_NumFailedMPUTries = 0;
    m_pMiniport = pMiniport;
    m_pMiniport->AddRef();

    m_pPortBase = pPortBase;
    m_fCapture = fCapture;

    return STATUS_SUCCESS;
}

#pragma code_seg()
/*****************************************************************************
 * CMiniportMidiStreamUart::SetState()
 *****************************************************************************
 * Sets the state of the channel.
 */
STDMETHODIMP
CMiniportMidiStreamUart::
SetState
(
    IN      KSSTATE     NewState
)
{
    _DbgPrintF(DEBUGLVL_VERBOSE,("SetState %d",NewState));

    if (m_fCapture)
    {
        m_pMiniport->m_KSStateInput = NewState;
        if (NewState == KSSTATE_STOP)   // STOPping
        {
            m_pMiniport->m_MPUInputBufferHead = 0;   // Previously read bytes are discarded.
            m_pMiniport->m_MPUInputBufferTail = 0;   // The entire FIFO is available.
        }
    }
    return STATUS_SUCCESS;
}

#pragma code_seg()
/*****************************************************************************
 * CMiniportMidiUart::Service()
 *****************************************************************************
 * DPC-mode service call from the port.
 */
STDMETHODIMP_(void) 
CMiniportMidiUart::
Service
(   void
)
{
    _DbgPrintF(DEBUGLVL_BLAB, ("Service"));
    _DbgPrintF(DEBUGLVL_VERBOSE,("Service: m_NumRenderStreams %d, m_NumCaptureStreams %d",
                                  m_NumRenderStreams,m_NumCaptureStreams));
    if (!m_NumCaptureStreams)
    {
        //  we should never get here....
        //  if we do, we must have read some trash,
        //  so just reset the input FIFO
        m_MPUInputBufferTail = m_MPUInputBufferHead = 0;
    }
}

#pragma code_seg()

⌨️ 快捷键说明

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