miniport.cpp
来自「winddk src目录下的WDM源码压缩!」· C++ 代码 · 共 1,744 行 · 第 1/4 页
CPP
1,744 行
ntStatus = STATUS_SUCCESS;
}
return ntStatus;
} // SetTechnology
/*****************************************************************************
* CMiniportDMusUART::PowerChangeNotify()
*****************************************************************************
* Handle power state change for the miniport.
*/
#pragma code_seg("PAGE")
STDMETHODIMP_(void)
CMiniportDMusUART::
PowerChangeNotify
(
IN POWER_STATE PowerState
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE, ("CMiniportDMusUART::PoweChangeNotify D%d", PowerState.DeviceState));
switch (PowerState.DeviceState)
{
case PowerDeviceD0:
if (m_PowerState.DeviceState != PowerDeviceD0)
{
if (!NT_SUCCESS(InitializeHardware(m_pInterruptSync,m_pPortBase)))
{
_DbgPrintF(DEBUGLVL_TERSE, ("InitializeHardware failed when resuming"));
}
}
break;
case PowerDeviceD1:
case PowerDeviceD2:
case PowerDeviceD3:
default:
break;
}
m_PowerState.DeviceState = PowerState.DeviceState;
} // PowerChangeNotify
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUARTStream::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)
CMiniportDMusUARTStream::
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_IMXF))
{
*Object = PVOID(PMXF(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")
/*****************************************************************************
* CMiniportDMusUARTStream::~CMiniportDMusUARTStream()
*****************************************************************************
* Destructs a stream.
*/
CMiniportDMusUARTStream::~CMiniportDMusUARTStream(void)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_BLAB,("~CMiniportDMusUARTStream"));
KeCancelTimer(&m_TimerEvent);
if (m_DMKEvtQueue)
{
if (m_AllocatorMXF)
{
m_AllocatorMXF->PutMessage(m_DMKEvtQueue);
}
else
{
_DbgPrintF(DEBUGLVL_ERROR,("~CMiniportDMusUARTStream, no allocator, can't flush DMKEvts"));
}
m_DMKEvtQueue = NULL;
}
if (m_AllocatorMXF)
{
m_AllocatorMXF->Release();
m_AllocatorMXF = NULL;
}
if (m_pMiniport)
{
if (m_fCapture)
{
m_pMiniport->m_NumCaptureStreams--;
}
else
{
m_pMiniport->m_NumRenderStreams--;
}
m_pMiniport->Release();
}
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUARTStream::Init()
*****************************************************************************
* Initializes a stream.
*/
STDMETHODIMP_(NTSTATUS)
CMiniportDMusUARTStream::
Init
(
IN CMiniportDMusUART * pMiniport,
IN PUCHAR pPortBase,
IN BOOLEAN fCapture,
IN PAllocatorMXF allocatorMXF,
IN PMASTERCLOCK masterClock
)
{
PAGED_CODE();
ASSERT(pMiniport);
ASSERT(pPortBase);
_DbgPrintF(DEBUGLVL_BLAB,("Init"));
m_NumFailedMPUTries = 0;
m_TimerQueued = FALSE;
KeInitializeSpinLock(&m_DpcSpinLock);
m_pMiniport = pMiniport;
m_pMiniport->AddRef();
pMiniport->m_MasterClock = masterClock;
m_pPortBase = pPortBase;
m_fCapture = fCapture;
m_SnapshotTimeStamp = 0;
m_DMKEvtQueue = NULL;
m_DMKEvtOffset = 0;
m_NumberOfRetries = 0;
if (allocatorMXF)
{
allocatorMXF->AddRef();
m_AllocatorMXF = allocatorMXF;
m_sinkMXF = m_AllocatorMXF;
}
else
{
return STATUS_INVALID_PARAMETER;
}
KeInitializeDpc
(
&m_Dpc,
&::DMusUARTTimerDPC,
PVOID(this)
);
KeInitializeTimer(&m_TimerEvent);
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUARTStream::SetState()
*****************************************************************************
* Sets the state of the channel.
*/
STDMETHODIMP_(NTSTATUS)
CMiniportDMusUARTStream::
SetState
(
IN KSSTATE NewState
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("SetState %d",NewState));
if (NewState == KSSTATE_RUN)
{
if (m_pMiniport->m_fMPUInitialized)
{
LARGE_INTEGER timeDue100ns;
timeDue100ns.QuadPart = 0;
KeSetTimer(&m_TimerEvent,timeDue100ns,&m_Dpc);
}
else
{
_DbgPrintF(DEBUGLVL_TERSE, ("CMiniportDMusUARTStream::SetState KSSTATE_RUN failed due to uninitialized MPU"));
return STATUS_INVALID_DEVICE_STATE;
}
}
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()
/*****************************************************************************
* CMiniportDMusUART::Service()
*****************************************************************************
* DPC-mode service call from the port.
*/
STDMETHODIMP_(void)
CMiniportDMusUART::
Service
( void
)
{
_DbgPrintF(DEBUGLVL_BLAB, ("Service"));
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("PAGE")
/*****************************************************************************
* CMiniportDMusUARTStream::ConnectOutput()
*****************************************************************************
* Writes outgoing MIDI data.
*/
NTSTATUS
CMiniportDMusUARTStream::
ConnectOutput(PMXF sinkMXF)
{
PAGED_CODE();
if (m_fCapture)
{
if ((sinkMXF) && (m_sinkMXF == m_AllocatorMXF))
{
_DbgPrintF(DEBUGLVL_BLAB, ("ConnectOutput"));
m_sinkMXF = sinkMXF;
return STATUS_SUCCESS;
}
else
{
_DbgPrintF(DEBUGLVL_TERSE, ("ConnectOutput failed"));
}
}
else
{
_DbgPrintF(DEBUGLVL_TERSE, ("ConnectOutput called on renderer; failed"));
}
return STATUS_UNSUCCESSFUL;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUARTStream::DisconnectOutput()
*****************************************************************************
* Writes outgoing MIDI data.
*/
NTSTATUS
CMiniportDMusUARTStream::
DisconnectOutput(PMXF sinkMXF)
{
PAGED_CODE();
if (m_fCapture)
{
if ((m_sinkMXF == sinkMXF) || (!sinkMXF))
{
_DbgPrintF(DEBUGLVL_BLAB, ("DisconnectOutput"));
m_sinkMXF = m_AllocatorMXF;
return STATUS_SUCCESS;
}
else
{
_DbgPrintF(DEBUGLVL_TERSE, ("DisconnectOutput failed"));
}
}
else
{
_DbgPrintF(DEBUGLVL_TERSE, ("DisconnectOutput called on renderer; failed"));
}
return STATUS_UNSUCCESSFUL;
}
#pragma code_seg()
/*****************************************************************************
* CMiniportDMusUARTStream::PutMessageLocked()
*****************************************************************************
* Now that the spinlock is held, add this message to the queue.
*
* Writes an outgoing MIDI message.
* We don't sort a new message into the queue -- we append it.
* This is fine, since the sequencer feeds us sequenced data.
* Timestamps will ascend by design.
*/
NTSTATUS CMiniportDMusUARTStream::PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDMUS_KERNEL_EVENT aDMKEvt;
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
if (!m_fCapture)
{
_DbgPrintF(DEBUGLVL_BLAB, ("PutMessage to render stream"));
if (pDMKEvt)
{
// m_DpcSpinLock already held
if (m_DMKEvtQueue)
{
aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue
while (aDMKEvt->pNextEvt)
{
aDMKEvt = aDMKEvt->pNextEvt;
}
aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue
}
else // currently nothing in queue
{
m_DMKEvtQueue = pDMKEvt;
if (m_DMKEvtOffset)
{
_DbgPrintF(DEBUGLVL_ERROR, ("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d",m_DMKEvtOffset));
m_DMKEvtOffset = 0;
}
}
// m_DpcSpinLock already held
}
if (!m_TimerQueued)
{
(void) ConsumeEvents();
}
}
else // capture
{
_DbgPrintF(DEBUGLVL_BLAB, ("PutMessage to capture stream"));
ASSERT(NULL == pDMKEvt);
SourceEvtsToPort();
}
return ntStatus;
}
#pragma code_seg()
/*****************************************************************************
* CMiniportDMusUARTStream::PutMessage()
*****************************************************************************
* Writes an outgoing MIDI message.
* We don't sort a new message into the queue -- we append it.
* This is fine, since the sequencer feeds us sequenced data.
* Timestamps will ascend by design.
*/
NTSTATUS CMiniportDMusUARTStream::PutMessage(PDMUS_KERNEL_EVENT pDMKEvt)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDMUS_KERNEL_EVENT aDMKEvt;
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
if (!m_fCapture)
{
_DbgPrintF(DEBUGLVL_BLAB, ("PutMessage to render stream"));
if (pDMKEvt)
{
KeAcquireSpinLockAtDpcLevel(&m_DpcSpinLock);
if (m_DMKEvtQueue)
{
aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue
while (aDMKEvt->pNextEvt)
{
aDMKEvt = aDMKEvt->pNextEvt;
}
aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue
}
else // currently nothing in queue
{
m_DMKEvtQueue = pDMKEvt;
if (m_DMKEvtOffset)
{
_DbgPrintF(DEBUGLVL_ERROR, ("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d",m_DMKEvtOffset));
m_DMKEvtOffset = 0;
}
}
KeReleaseSpinLockFromDpcLevel(&m_DpcSpinLock);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?