miniport.cpp
来自「winddk src目录下的WDM源码压缩!」· C++ 代码 · 共 1,744 行 · 第 1/4 页
CPP
1,744 行
m_pPortBase =
PUCHAR(ResourceList->FindTranslatedPort(0)->u.Port.Start.QuadPart);
ntStatus = InitializeHardware(m_pInterruptSync,m_pPortBase);
}
return ntStatus;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUART::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)
CMiniportDMusUART::
NonDelegatingQueryInterface
(
REFIID Interface,
PVOID * Object
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_BLAB, ("Miniport::NonDelegatingQueryInterface"));
ASSERT(Object);
if (IsEqualGUIDAligned(Interface,IID_IUnknown))
{
*Object = PVOID(PUNKNOWN(PMINIPORTDMUS(this)));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMiniport))
{
*Object = PVOID(PMINIPORT(this));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMiniportDMus))
{
*Object = PVOID(PMINIPORTDMUS(this));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMusicTechnology))
{
*Object = PVOID(PMUSICTECHNOLOGY(this));
}
else
if (IsEqualGUIDAligned(Interface,IID_IPowerNotify))
{
*Object = PVOID(PPOWERNOTIFY(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")
/*****************************************************************************
* CMiniportDMusUART::~CMiniportDMusUART()
*****************************************************************************
* Destructor.
*/
CMiniportDMusUART::~CMiniportDMusUART(void)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_BLAB,("~CMiniportDMusUART"));
ASSERT(0 == m_NumCaptureStreams);
ASSERT(0 == m_NumRenderStreams);
// reset the HW so we don't get anymore interrupts
if (m_UseIRQ && m_pInterruptSync)
{
(void) m_pInterruptSync->CallSynchronizedRoutine(InitMPU,PVOID(m_pPortBase));
}
else
{
(void) InitMPU(NULL,PVOID(m_pPortBase));
}
if (m_pInterruptSync)
{
m_pInterruptSync->Release();
m_pInterruptSync = NULL;
}
if (m_pServiceGroup)
{
m_pServiceGroup->Release();
m_pServiceGroup = NULL;
}
if (m_pPort)
{
m_pPort->Release();
m_pPort = NULL;
}
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUART::Init()
*****************************************************************************
* Initializes a the miniport.
*/
STDMETHODIMP_(NTSTATUS)
CMiniportDMusUART::
Init
(
IN PUNKNOWN UnknownInterruptSync OPTIONAL,
IN PRESOURCELIST ResourceList,
IN PPORTDMUS Port_,
OUT PSERVICEGROUP * ServiceGroup
)
{
PAGED_CODE();
ASSERT(ResourceList);
if (!ResourceList)
{
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
ASSERT(Port_);
ASSERT(ServiceGroup);
_DbgPrintF(DEBUGLVL_BLAB,("Init"));
*ServiceGroup = NULL;
m_pPortBase = 0;
m_fMPUInitialized = FALSE;
// This will remain unspecified if the miniport does not get any power
// messages.
//
m_PowerState.DeviceState = PowerDeviceUnspecified;
//
// AddRef() is required because we are keeping this pointer.
//
m_pPort = Port_;
m_pPort->AddRef();
// Set dataformat.
//
if (IsEqualGUIDAligned(m_MusicFormatTechnology, GUID_NULL))
{
RtlCopyMemory( &m_MusicFormatTechnology,
&KSMUSIC_TECHNOLOGY_PORT,
sizeof(GUID));
}
RtlCopyMemory( &PinDataRangesStreamLegacy.Technology,
&m_MusicFormatTechnology,
sizeof(GUID));
RtlCopyMemory( &PinDataRangesStreamDMusic.Technology,
&m_MusicFormatTechnology,
sizeof(GUID));
for (ULONG bufferCount = 0;bufferCount < kMPUInputBufferSize;bufferCount++)
{
m_MPUInputBuffer[bufferCount] = 0;
}
m_MPUInputBufferHead = 0;
m_MPUInputBufferTail = 0;
m_InputTimeStamp = 0;
m_KSStateInput = KSSTATE_STOP;
NTSTATUS ntStatus = STATUS_SUCCESS;
m_NumRenderStreams = 0;
m_NumCaptureStreams = 0;
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(DMusMPUInterruptServiceRoutine,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(
DMusMPUInterruptServiceRoutine,
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->Release();
m_pInterruptSync = NULL;
}
// clean up the service group
if( m_pServiceGroup )
{
m_pServiceGroup->Release();
m_pServiceGroup = NULL;
}
// clean up the out param service group.
if (*ServiceGroup)
{
(*ServiceGroup)->Release();
(*ServiceGroup) = NULL;
}
// release the port
m_pPort->Release();
m_pPort = NULL;
}
return ntStatus;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUART::NewStream()
*****************************************************************************
* Gets the topology.
*/
STDMETHODIMP_(NTSTATUS)
CMiniportDMusUART::
NewStream
(
OUT PMXF * MXF,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN ULONG PinID,
IN DMUS_STREAM_TYPE StreamType,
IN PKSDATAFORMAT DataFormat,
OUT PSERVICEGROUP * ServiceGroup,
IN PAllocatorMXF AllocatorMXF,
IN PMASTERCLOCK MasterClock,
OUT PULONGLONG SchedulePreFetch
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_BLAB, ("NewStream"));
NTSTATUS ntStatus = STATUS_SUCCESS;
// In 100 ns, we want stuff as soon as it comes in
//
*SchedulePreFetch = 0;
// if we don't have any streams already open, get the hardware ready.
if ((!m_NumCaptureStreams) && (!m_NumRenderStreams))
{
ntStatus = ResetHardware(m_pPortBase);
if (!NT_SUCCESS(ntStatus))
{
_DbgPrintF(DEBUGLVL_TERSE, ("CMiniportDMusUART::NewStream ResetHardware failed"));
return ntStatus;
}
}
if ( ((m_NumCaptureStreams < kMaxNumCaptureStreams)
&& (StreamType == DMUS_STREAM_MIDI_CAPTURE))
|| ((m_NumRenderStreams < kMaxNumLegacyRenderStreams + kMaxNumDMusicRenderStreams)
&& (StreamType == DMUS_STREAM_MIDI_RENDER))
)
{
CMiniportDMusUARTStream *pStream =
new(PoolType) CMiniportDMusUARTStream(OuterUnknown);
if (pStream)
{
pStream->AddRef();
ntStatus =
pStream->Init(this,m_pPortBase,(StreamType == DMUS_STREAM_MIDI_CAPTURE),AllocatorMXF,MasterClock);
if (NT_SUCCESS(ntStatus))
{
*MXF = PMXF(pStream);
(*MXF)->AddRef();
if (StreamType == DMUS_STREAM_MIDI_CAPTURE)
{
m_NumCaptureStreams++;
*ServiceGroup = m_pServiceGroup;
(*ServiceGroup)->AddRef();
}
else
{
m_NumRenderStreams++;
*ServiceGroup = NULL;
}
}
pStream->Release();
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else
{
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
if (StreamType == DMUS_STREAM_MIDI_CAPTURE)
{
_DbgPrintF(DEBUGLVL_TERSE,("NewStream failed, too many capture streams"));
}
else if (StreamType == DMUS_STREAM_MIDI_RENDER)
{
_DbgPrintF(DEBUGLVL_TERSE,("NewStream failed, too many render streams"));
}
else
{
_DbgPrintF(DEBUGLVL_TERSE,("NewStream invalid stream type"));
}
}
return ntStatus;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportDMusUART::SetTechnology()
*****************************************************************************
* Sets pindatarange technology.
*/
STDMETHODIMP_(NTSTATUS)
CMiniportDMusUART::
SetTechnology
(
IN const GUID * Technology
)
{
PAGED_CODE();
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
// Fail if miniport has already been initialized.
//
if (NULL == m_pPort)
{
RtlCopyMemory(&m_MusicFormatTechnology, Technology, sizeof(GUID));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?