📄 miniport.cpp
字号:
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 + -