📄 mpu.cpp
字号:
IN PUCHAR PortBase
)
{
BOOLEAN success;
USHORT numPolls;
UCHAR status;
_DbgPrintF(DEBUGLVL_BLAB, ("TryMPU"));
numPolls = 0;
while (numPolls < kMPUPollTimeout)
{
status = READ_PORT_UCHAR(PortBase + MPU401_REG_STATUS);
if (UartFifoOkForWrite(status)) // Is this a good time to write data?
{
break;
}
numPolls++;
}
if (numPolls >= kMPUPollTimeout)
{
success = FALSE;
_DbgPrintF(DEBUGLVL_BLAB, ("TryMPU failed"));
}
else
{
success = TRUE;
}
return success;
}
#pragma code_seg()
/*****************************************************************************
* WriteMPU()
*****************************************************************************
* Write a byte out to the MPU401.
*/
NTSTATUS
WriteMPU
(
IN PUCHAR PortBase,
IN BOOLEAN IsCommand,
IN UCHAR Value
)
{
_DbgPrintF(DEBUGLVL_BLAB, ("WriteMPU"));
NTSTATUS ntStatus = STATUS_IO_DEVICE_ERROR;
if (!PortBase)
{
_DbgPrintF(DEBUGLVL_TERSE, ("O: PortBase is zero\n"));
return ntStatus;
}
PUCHAR deviceAddr = PortBase + MPU401_REG_DATA;
if (IsCommand)
{
deviceAddr = PortBase + MPU401_REG_COMMAND;
}
ULONGLONG startTime = PcGetTimeInterval(0);
while (PcGetTimeInterval(startTime) < GTI_MILLISECONDS(50))
{
UCHAR status
= READ_PORT_UCHAR(PortBase + MPU401_REG_STATUS);
if (UartFifoOkForWrite(status)) // Is this a good time to write data?
{ // yep (Jon comment)
WRITE_PORT_UCHAR(deviceAddr,Value);
_DbgPrintF(DEBUGLVL_BLAB, ("WriteMPU emitted 0x%02x",Value));
ntStatus = STATUS_SUCCESS;
break;
}
}
return ntStatus;
}
#pragma code_seg()
/*****************************************************************************
* SnapTimeStamp()
*****************************************************************************
*
* At synchronized execution to ISR, copy miniport's volatile m_InputTimeStamp
* to stream's m_SnapshotTimeStamp and zero m_InputTimeStamp.
*
*/
STDMETHODIMP_(NTSTATUS)
SnapTimeStamp(PINTERRUPTSYNC InterruptSync,PVOID pStream)
{
CMiniportDMusUARTStream *pMPStream = (CMiniportDMusUARTStream *)pStream;
// cache the timestamp
pMPStream->m_SnapshotTimeStamp = pMPStream->m_pMiniport->m_InputTimeStamp;
// if the window is closed, zero the timestamp
if (pMPStream->m_pMiniport->m_MPUInputBufferHead ==
pMPStream->m_pMiniport->m_MPUInputBufferTail)
{
pMPStream->m_pMiniport->m_InputTimeStamp = 0;
}
return STATUS_SUCCESS;
}
/*****************************************************************************
* CMiniportDMusUARTStream::SourceEvtsToPort()
*****************************************************************************
*
* Reads incoming MIDI data, feeds into DMus events.
* No need to touch the hardware, just read from our SW FIFO.
*
*/
STDMETHODIMP_(NTSTATUS)
CMiniportDMusUARTStream::SourceEvtsToPort()
{
NTSTATUS ntStatus;
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
_DbgPrintF(DEBUGLVL_BLAB, ("SourceEvtsToPort"));
if (m_fCapture)
{
ntStatus = STATUS_SUCCESS;
if (m_pMiniport->m_MPUInputBufferHead != m_pMiniport->m_MPUInputBufferTail)
{
PDMUS_KERNEL_EVENT aDMKEvt,eventTail,eventHead = NULL;
while (m_pMiniport->m_MPUInputBufferHead != m_pMiniport->m_MPUInputBufferTail)
{
(void) m_AllocatorMXF->GetMessage(&aDMKEvt);
if (!aDMKEvt)
{
_DbgPrintF(DEBUGLVL_TERSE, ("SourceEvtsToPort can't allocate DMKEvt"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// put this event at the end of the list
if (!eventHead)
{
eventHead = aDMKEvt;
}
else
{
eventTail = eventHead;
while (eventTail->pNextEvt)
{
eventTail = eventTail->pNextEvt;
}
eventTail->pNextEvt = aDMKEvt;
}
// read all the bytes out of the buffer, into event(s)
for (aDMKEvt->cbEvent = 0; aDMKEvt->cbEvent < sizeof(PBYTE); aDMKEvt->cbEvent++)
{
if (m_pMiniport->m_MPUInputBufferHead == m_pMiniport->m_MPUInputBufferTail)
{
// _DbgPrintF(DEBUGLVL_TERSE, ("SourceEvtsToPort m_MPUInputBufferHead met m_MPUInputBufferTail, overrun"));
break;
}
aDMKEvt->uData.abData[aDMKEvt->cbEvent] = m_pMiniport->m_MPUInputBuffer[m_pMiniport->m_MPUInputBufferHead];
m_pMiniport->m_MPUInputBufferHead++;
if (m_pMiniport->m_MPUInputBufferHead >= kMPUInputBufferSize)
{
m_pMiniport->m_MPUInputBufferHead = 0;
}
}
}
if (m_pMiniport->m_UseIRQ)
{
ntStatus = m_pMiniport->m_pInterruptSync->CallSynchronizedRoutine(SnapTimeStamp,PVOID(this));
}
else // !m_UseIRQ
{
ntStatus = SnapTimeStamp(NULL,PVOID(this));
} // !m_UseIRQ
aDMKEvt = eventHead;
while (aDMKEvt)
{
aDMKEvt->ullPresTime100ns = m_SnapshotTimeStamp;
aDMKEvt->usChannelGroup = 1;
aDMKEvt->usFlags = DMUS_KEF_EVENT_INCOMPLETE;
aDMKEvt = aDMKEvt->pNextEvt;
}
(void)m_sinkMXF->PutMessage(eventHead);
}
}
else // render stream
{
_DbgPrintF(DEBUGLVL_TERSE, ("SourceEvtsToPort called on render stream"));
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}
return ntStatus;
}
#pragma code_seg()
/*****************************************************************************
* DMusMPUInterruptServiceRoutine()
*****************************************************************************
* ISR.
*/
NTSTATUS
DMusMPUInterruptServiceRoutine
(
IN PINTERRUPTSYNC InterruptSync,
IN PVOID DynamicContext
)
{
_DbgPrintF(DEBUGLVL_BLAB, ("DMusMPUInterruptServiceRoutine"));
ULONGLONG startTime;
ASSERT(DynamicContext);
NTSTATUS ntStatus;
BOOL newBytesAvailable;
CMiniportDMusUART *that;
NTSTATUS clockStatus;
that = (CMiniportDMusUART *) DynamicContext;
newBytesAvailable = FALSE;
ntStatus = STATUS_UNSUCCESSFUL;
UCHAR portStatus = 0xff;
//
// Read the MPU status byte.
//
if (that->m_pPortBase)
{
portStatus =
READ_PORT_UCHAR(that->m_pPortBase + MPU401_REG_STATUS);
//
// If there is outstanding work to do and there is a port-driver for
// the MPU miniport...
//
if (UartFifoOkForRead(portStatus) && that->m_pPort)
{
startTime = PcGetTimeInterval(0);
while ( (PcGetTimeInterval(startTime) < GTI_MILLISECONDS(50))
&& (UartFifoOkForRead(portStatus)) )
{
UCHAR uDest = READ_PORT_UCHAR(that->m_pPortBase + MPU401_REG_DATA);
if ( (that->m_KSStateInput == KSSTATE_RUN)
&& (that->m_NumCaptureStreams)
)
{
LONG buffHead = that->m_MPUInputBufferHead;
if ( (that->m_MPUInputBufferTail + 1 == buffHead)
|| (that->m_MPUInputBufferTail + 1 - kMPUInputBufferSize == buffHead))
{
_DbgPrintF(DEBUGLVL_TERSE,("*****MPU Input Buffer Overflow*****"));
}
else
{
if (!that->m_InputTimeStamp)
{
clockStatus = that->m_MasterClock->GetTime(&that->m_InputTimeStamp);
if (STATUS_SUCCESS != clockStatus)
{
_DbgPrintF(DEBUGLVL_TERSE,("GetTime failed for clock 0x%08x",that->m_MasterClock));
}
}
newBytesAvailable = TRUE;
// ...place the data in our FIFO...
that->m_MPUInputBuffer[that->m_MPUInputBufferTail] = uDest;
ASSERT(that->m_MPUInputBufferTail < kMPUInputBufferSize);
that->m_MPUInputBufferTail++;
if (that->m_MPUInputBufferTail >= kMPUInputBufferSize)
{
that->m_MPUInputBufferTail = 0;
}
}
}
//
// Look for more MIDI data.
//
portStatus =
READ_PORT_UCHAR(that->m_pPortBase + MPU401_REG_STATUS);
} // either there's no data or we ran too long
if (newBytesAvailable)
{
//
// ...notify the MPU port driver that we have bytes.
//
that->m_pPort->Notify(that->m_pServiceGroup);
}
ntStatus = STATUS_SUCCESS;
}
}
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -