17#define kOneMillisec (10 * 1000)
22#define MPU401_REG_STATUS 0x01
23#define MPU401_DRR 0x40
25#define MPU401_DSR 0x80
28#define MPU401_REG_DATA 0x00
29#define MPU401_REG_COMMAND 0x01
30#define MPU401_CMD_RESET 0xFF
31#define MPU401_CMD_UART 0x3F
250#define STR_MODULENAME "DMusUART:Miniport: "
253#pragma code_seg("PAGE")
256#define UartFifoOkForWrite(status) ((status & MPU401_DRR) == 0)
257#define UartFifoOkForRead(status) ((status & MPU401_DSR) == 0)
413#define kMaxNumCaptureStreams 1
414#define kMaxNumLegacyRenderStreams 1
415#define kMaxNumDMusicRenderStreams 1
517#define CONST_PCNODE_DESCRIPTOR(n) { 0, NULL, &n, NULL }
518#define CONST_PCNODE_DESCRIPTOR_AUTO(n,a) { 0, &a, &n, NULL }
591#pragma code_seg("PAGE")
598#pragma code_seg("PAGE")
610#pragma code_seg("PAGE")
624 ntStatus = interruptSync->CallSynchronizedRoutine(
InitMPU,
PVOID(portBase));
640 DPRINT(
"*** InitMPU returned with ntStatus 0x%08x ***", ntStatus);
704 DPRINT(
"First attempt to reset the MPU didn't get ACKed.\n");
730 if ((0xFE != dataByte) || !
success)
732 DPRINT(
"Second attempt to reset the MPU didn't get ACKed.\n");
733 DPRINT(
"Init Reset failure error. Ack = %X",
ULONG(dataByte));
751CMiniportDMusUARTStream::
781 context.BufferAddress = pMidiData;
865 DPRINT(
"SynchronizedDMusMPUWrite failed (0x%08x)",ntStatus);
873#define kMPUPollTimeout 2
942 DPRINT(
"O: PortBase is zero\n");
1009CMiniportDMusUARTStream::SourceEvtsToPort()
1014 DPRINT(
"SourceEvtsToPort");
1028 DPRINT(
"SourceEvtsToPort can't allocate DMKEvt");
1035 eventHead = aDMKEvt;
1039 eventTail = eventHead;
1071 aDMKEvt = eventHead;
1084 DPRINT(
"SourceEvtsToPort called on render stream");
1107 DPRINT(
"DMusMPUInterruptServiceRoutine");
1113 BOOL newBytesAvailable;
1118 newBytesAvailable =
FALSE;
1121 UCHAR portStatus = 0xff;
1150 DPRINT(
"*****MPU Input Buffer Overflow*****");
1162 newBytesAvailable =
TRUE;
1180 if (newBytesAvailable)
1208 ASSERT(OutFilterDescriptor);
1210 DPRINT(
"GetDescription");
1218#pragma code_seg("PAGE")
1240 DPRINT(
"NewMiniportDMusUART %p Status %x\n", *OutMiniport,
Status);
1246#pragma code_seg("PAGE")
1263 DPRINT(
"ProcessResources");
1279 DPRINT(
"Starting MPU401 Port 0x%lx",
ResourceList->FindTranslatedPort(0)->u.Port.Start.LowPart);
1293 DPRINT(
"Unknown ResourceList configuration");
1312#pragma code_seg("PAGE")
1329 DPRINT(
"Miniport::NonDelegatingQueryInterface");
1374#pragma code_seg("PAGE")
1385 DPRINT(
"~CMiniportDMusUART");
1418#pragma code_seg("PAGE")
1525 UnknownInterruptSync =
NULL;
1527 if (UnknownInterruptSync)
1530 UnknownInterruptSync->QueryInterface
1606 (*ServiceGroup)->Release();
1607 (*ServiceGroup) =
NULL;
1619#pragma code_seg("PAGE")
1657 DPRINT(
"CMiniportDMusUART::NewStream ResetHardware failed");
1687 (*ServiceGroup)->AddRef();
1708 DPRINT(
"NewStream failed, too many capture streams");
1712 DPRINT(
"NewStream failed, too many render streams");
1716 DPRINT(
"NewStream invalid stream type");
1724#pragma code_seg("PAGE")
1735 IN const GUID * Technology
1759#pragma code_seg("PAGE")
1780 DPRINT(
"InitializeHardware failed when resuming");
1795#pragma code_seg("PAGE")
1812 DPRINT(
"Stream::NonDelegatingQueryInterface");
1842#pragma code_seg("PAGE")
1853 DPRINT(
"~CMiniportDMusUARTStream");
1865 DPRINT(
"~CMiniportDMusUARTStream, no allocator, can't flush DMKEvts");
1891#pragma code_seg("PAGE")
1899CMiniportDMusUARTStream::
1956#pragma code_seg("PAGE")
1964CMiniportDMusUARTStream::
1972 DPRINT(
"SetState %d",NewState);
1984 DPRINT(
"CMiniportDMusUARTStream::SetState KSSTATE_RUN failed due to uninitialized MPU");
2028#pragma code_seg("PAGE")
2037CMiniportDMusUARTStream::
2038ConnectOutput(
PMXF sinkMXF)
2052 DPRINT(
"ConnectOutput failed");
2057 DPRINT(
"ConnectOutput called on renderer; failed");
2063#pragma code_seg("PAGE")
2072CMiniportDMusUARTStream::
2073DisconnectOutput(
PMXF sinkMXF)
2079 if ((
m_sinkMXF == sinkMXF) || (!sinkMXF))
2081 DPRINT(
"DisconnectOutput");
2087 DPRINT(
"DisconnectOutput failed");
2092 DPRINT(
"DisconnectOutput called on renderer; failed");
2121 DPRINT(
"PutMessage to render stream");
2150 (
void) ConsumeEvents();
2155 DPRINT(
"PutMessage to capture stream");
2184 DPRINT(
"PutMessage to render stream");
2213 (
void) ConsumeEvents();
2218 DPRINT(
"PutMessage to capture stream");
2241NTSTATUS CMiniportDMusUARTStream::ConsumeEvents(
void)
2260 ASSERT(bytesRemaining > 0);
2261 if (bytesRemaining <= 0)
2263 bytesRemaining = aDMKEvt->
cbEvent;
2275 DPRINT(
"ConsumeEvents(Package)");
2293 DPRINT(
"ConsumeEvents: Write returned 0x%08x", ntStatus);
2311 ASSERT(m_DMKEvtOffset < aDMKEvt->cbEvent);
2364 Params->ChannelGroups = 1;
2366 else if (
Params->ChannelGroups != 1)
2368 Params->ChannelGroups = 1;
2404 DPRINT(
"DMusUARTTimerDPC");
2407 (
void) aStream->ConsumeEvents();
2447 switch (
pRequest->PropertyItem->Id)
2453 switch (
pRequest->PropertyItem->Id)
2461 switch (
pRequest->PropertyItem->Id)
2482 DPRINT(
"PropertyHandler_Synth:KSPROPERTY_SYNTH_CAPS");
2504 caps->
Guid = CLSID_MiniportDriverDMusUART;
2510 caps->
Guid = CLSID_MiniportDriverDMusUARTCapture;
2528 cLen *=
sizeof(
WCHAR);
2541 DPRINT(
"PropertyHandler_Synth:KSPROPERTY_SYNTH_PORTPARAMETERS");
2558 DPRINT(
"PropertyHandler_Synth:KSPROPERTY_SYNTH_CHANNELGROUPS");
2569 DPRINT(
"PropertyHandler_Synth:KSPROPERTY_SYNTH_LATENCYCLOCK");
2599 DPRINT(
"Unhandled property in PropertyHandler_Synth");
2625 if (
pRequest->ValueSize >= ulValueSize)
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID BufferAddress
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
STDMETHODIMP_(NTSTATUS) ConsumeEvents()
friend VOID NTAPI DMusUARTTimerDPC(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
friend NTSTATUS NTAPI PropertyHandler_Synth(IN PPCPROPERTY_REQUEST)
STDMETHODIMP_(NTSTATUS) Write(IN PVOID BufferAddress
IN PUCHAR IN BOOLEAN fCapture
IN PUCHAR IN BOOLEAN IN PAllocatorMXF IN PMASTERCLOCK masterClock
IN PUCHAR IN BOOLEAN IN PAllocatorMXF allocatorMXF
CMiniportDMusUART * m_pMiniport
STDMETHODIMP_(NTSTATUS) SourceEvtsToPort()
PAllocatorMXF m_AllocatorMXF
NTSTATUS HandlePortParams(IN PPCPROPERTY_REQUEST Request)
PDMUS_KERNEL_EVENT m_DMKEvtQueue
virtual ~CMiniportDMusUARTStream()
STDMETHODIMP_(NTSTATUS) Init(IN CMiniportDMusUART *pMiniport
STDMETHODIMP_(NTSTATUS) PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt)
REFERENCE_TIME m_SnapshotTimeStamp
IN PUNKNOWN OuterUnknown IN POOL_TYPE IN ULONG IN DMUS_STREAM_TYPE IN PKSDATAFORMAT OUT PSERVICEGROUP IN PAllocatorMXF IN PMASTERCLOCK MasterClock
IN PUNKNOWN OuterUnknown IN POOL_TYPE IN ULONG IN DMUS_STREAM_TYPE StreamType
UCHAR m_MPUInputBuffer[kMPUInputBufferSize]
NTSTATUS InitializeHardware(PINTERRUPTSYNC interruptSync, PUCHAR portBase)
REFERENCE_TIME m_InputTimeStamp
IN PUNKNOWN OuterUnknown IN POOL_TYPE PoolType
IN PUNKNOWN OuterUnknown IN POOL_TYPE IN ULONG IN DMUS_STREAM_TYPE IN PKSDATAFORMAT OUT PSERVICEGROUP IN PAllocatorMXF IN PMASTERCLOCK OUT PULONGLONG SchedulePreFetch
IN PRESOURCELIST IN PPORTDMUS Port
DataRangeIntersection(IN ULONG PinId, IN PKSDATARANGE DataRange, IN PKSDATARANGE MatchingDataRange, IN ULONG OutputBufferLength, OUT PVOID ResultantFormat, OUT PULONG ResultantFormatLength)
STDMETHODIMP_(NTSTATUS) NewStream(OUT PMXF *Stream
PMASTERCLOCK m_MasterClock
GetDescription(OUT PPCFILTER_DESCRIPTOR *OutFilterDescriptor)
ULONG m_MPUInputBufferTail
friend NTSTATUS NTAPI SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync, PVOID syncWriteContext)
PINTERRUPTSYNC m_pInterruptSync
NTSTATUS ProcessResources(IN PRESOURCELIST ResourceList)
friend NTSTATUS NTAPI PropertyHandler_Synth(IN PPCPROPERTY_REQUEST PropertyRequest)
CMiniportDMusUART(IUnknown *Unknown)
friend VOID NTAPI DMusUARTTimerDPC(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
BOOLEAN m_fMPUInitialized
virtual ~CMiniportDMusUART()
STDMETHODIMP_(void) Service(void)
ULONG m_MPUInputBufferHead
IN PRESOURCELIST IN PPORTDMUS OUT PSERVICEGROUP * ServiceGroup
friend NTSTATUS NTAPI DMusMPUInterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID DynamicContext)
STDMETHODIMP_(NTSTATUS) Init(IN PUNKNOWN UnknownAdapter
IN PUNKNOWN OuterUnknown IN POOL_TYPE IN ULONG PinID
USHORT m_NumCaptureStreams
USHORT m_NumRenderStreams
friend class CMiniportDMusUARTStream
GUID m_MusicFormatTechnology
PSERVICEGROUP m_pServiceGroup
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
IN PUNKNOWN OuterUnknown IN POOL_TYPE IN ULONG IN DMUS_STREAM_TYPE IN PKSDATAFORMAT OUT PSERVICEGROUP IN PAllocatorMXF AllocatorMXF
#define STATUS_NOT_IMPLEMENTED
#define NT_SUCCESS(StatCode)
static ULONGLONG startTime
#define KSAUDFNAME_DMUSIC_MPU_OUT
struct IAllocatorMXF * PAllocatorMXF
IMiniportDMus * PMINIPORTDMUS
IMasterClock * PMASTERCLOCK
@ DMUS_STREAM_MIDI_RENDER
@ DMUS_STREAM_MIDI_CAPTURE
#define DMUS_KEF_EVENT_INCOMPLETE
#define KSAUDFNAME_DMUSIC_MPU_IN
@ KSPROPERTY_SYNTH_PORTPARAMETERS
@ KSPROPERTY_SYNTH_CHANNELGROUPS
@ KSPROPERTY_SYNTH_LATENCYCLOCK
#define SYNTH_PORTPARAMS_CHANNELGROUPS
#define SYNTH_PC_EXTERNAL
struct _SYNTH_PORTPARAMS * PSYNTH_PORTPARAMS
#define KSDATAFORMAT_SUBTYPE_DIRECTMUSIC
#define KSPROPSETID_Synth
struct _SYNTHCAPS SYNTHCAPS
struct _SYNTH_PORTPARAMS SYNTH_PORTPARAMS
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
struct _MINIPORT * PMINIPORT
ULONGLONG NTAPI PcGetTimeInterval(IN ULONGLONG Since)
#define KSPROPERTY_TYPE_SET
#define STATICGUIDOF(guid)
#define KSPROPERTY_TYPE_BASICSUPPORT
#define KSPROPERTY_TYPE_GET
#define KeGetCurrentIrql()
#define KeInitializeSpinLock(sl)
GLuint GLuint GLsizei count
GLenum GLsizei GLuint GLint * bytesWritten
NTSTATUS NTAPI PcNewInterruptSync(OUT PINTERRUPTSYNC *OutInterruptSync, IN PUNKNOWN OuterUnknown OPTIONAL, IN PRESOURCELIST ResourceList, IN ULONG ResourceIndex, IN INTERRUPTSYNCMODE Mode)
#define KSDATAFORMAT_SPECIFIER_NONE
union KSDATAFORMAT KSDATARANGE
@ KSPIN_COMMUNICATION_NONE
@ KSPIN_COMMUNICATION_SINK
#define KSCATEGORY_CAPTURE
#define KSCATEGORY_RENDER
union KSDATAFORMAT * PKSDATARANGE
struct SYNCWRITECONTEXT * PSYNCWRITECONTEXT
NTSTATUS WriteMPU(IN PUCHAR PortBase, IN BOOLEAN IsCommand, IN UCHAR Value)
static PCPROPERTY_ITEM SynthProperties[]
NTSTATUS NTAPI InitMPU(IN PINTERRUPTSYNC InterruptSync, IN PVOID DynamicContext)
static KSDATARANGE PinDataRangesBridge[]
static KSDATARANGE_MUSIC PinDataRangesStreamDMusic
static PKSDATARANGE PinDataRangePointersStreamDMusic[]
static PKSDATARANGE PinDataRangePointersBridge[]
NTSTATUS NewMiniportDMusUART(OUT PMINIPORT *OutMiniport, IN REFCLSID ClassId)
NTSTATUS NTAPI SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync, PVOID syncWriteContext)
static PKSDATARANGE PinDataRangePointersStreamCombined[]
static PCPIN_DESCRIPTOR MiniportPins[]
NTSTATUS NTAPI PropertyHandler_Synth(IN PPCPROPERTY_REQUEST PropertyRequest)
#define MPU401_REG_COMMAND
static GUID MiniportCategories[]
VOID NTAPI DMusUARTTimerDPC(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
static KSDATARANGE_MUSIC PinDataRangesStreamLegacy
#define kMaxNumCaptureStreams
NTSTATUS NTAPI DMusMPUInterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID DynamicContext)
#define CONST_PCNODE_DESCRIPTOR_AUTO(n, a)
#define kMaxNumDMusicRenderStreams
static PKSDATARANGE PinDataRangePointersStreamLegacy[]
BOOLEAN TryMPU(IN PUCHAR PortBase)
SnapTimeStamp(PINTERRUPTSYNC InterruptSync, PVOID pStream)
#define kMaxNumLegacyRenderStreams
NTSTATUS ResetHardware(PUCHAR portBase)
const ULONG kMPUInputBufferSize
NTSTATUS ValidatePropertyRequest(IN PPCPROPERTY_REQUEST pRequest, IN ULONG ulValueSize, IN BOOLEAN fValueRequired)
#define UartFifoOkForWrite(status)
#define MPU401_REG_STATUS
#define UartFifoOkForRead(status)
static PCNODE_DESCRIPTOR MiniportNodes[]
static PCCONNECTION_DESCRIPTOR MiniportConnections[]
static PCFILTER_DESCRIPTOR MiniportFilterDescriptor
#define KeStallExecutionProcessor(MicroSeconds)
static HRESULT QueryInterface(REFIID, void **)
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
_In_ ULONG _In_ ULONG _In_ ULONG Length
#define STATUS_INVALID_PARAMETER_2
#define STATUS_DEVICE_CONFIGURATION_ERROR
#define READ_PORT_UCHAR(p)
#define WRITE_PORT_UCHAR(p, d)
static PHARDWARE_TIMER MasterClock
IInterruptSync * PINTERRUPTSYNC
IResourceList * PRESOURCELIST
IMusicTechnology * PMUSICTECHNOLOGY
#define GTI_MILLISECONDS(t)
#define DEFINE_PCAUTOMATION_TABLE_PROP(AutomationTable, PropertyTable)
NTSTATUS(NTAPI * PINTERRUPTSYNCROUTINE)(IN struct IInterruptSync *InterruptSync, IN PVOID DynamicContext)
IServiceGroup * PSERVICEGROUP
@ InterruptSyncModeNormal
IPowerNotify * PPOWERNOTIFY
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
NTSTATUS NTAPI PcNewServiceGroup(OUT PSERVICEGROUP *OutServiceGroup, IN PUNKNOWN OuterUnknown OPTIONAL)
#define STATUS_BUFFER_TOO_SMALL
#define STATUS_BUFFER_OVERFLOW
PULONG MinorVersion OPTIONAL
CMiniportDMusUART * Miniport
struct _DMUS_KERNEL_EVENT * pPackageEvt
struct _DMUS_KERNEL_EVENT * pNextEvt
union _DMUS_KERNEL_EVENT::@1938 uData
BYTE abData[sizeof(PBYTE)]
REFERENCE_TIME ullPresTime100ns
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define STATUS_IO_DEVICE_ERROR
#define STATUS_INVALID_DEVICE_REQUEST
#define STATUS_INVALID_PARAMETER
#define STATUS_UNSUCCESSFUL
#define STATUS_INVALID_DEVICE_STATE
#define STATUS_INSUFFICIENT_RESOURCES
DEVICE_POWER_STATE DeviceState
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE Interface
_In_ WDFREQUEST _In_ size_t OutputBufferLength
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesWritten
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
_Must_inspect_result_ _In_ WDFIORESREQLIST _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFIORESLIST * ResourceList
#define IsEqualGUIDAligned(guid1, guid2)
#define success(from, fromstr, to, tostr)
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
_In_opt_ PVOID DeferredContext
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2