ReactOS 0.4.16-dev-297-gc569aee
miniport_dmus.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 * miniport_dmus.cpp - UART miniport implementation
3 *****************************************************************************
4 * Copyright (c) 1997-2000 Microsoft Corporation. All Rights Reserved.
5 *
6 * Feb 98 MartinP -- based on UART, began deltas for DirectMusic.
7 *
8 */
9
10#include "private.hpp"
11
12#define NDEBUG
13#include <debug.h>
14
15// + for absolute / - for relative
16
17#define kOneMillisec (10 * 1000)
18
19//
20// MPU401 ports
21//
22#define MPU401_REG_STATUS 0x01 // Status register
23#define MPU401_DRR 0x40 // Output ready (for command or data)
24 // if this bit is set, the output FIFO is FULL
25#define MPU401_DSR 0x80 // Input ready (for data)
26 // if this bit is set, the input FIFO is empty
27
28#define MPU401_REG_DATA 0x00 // Data in
29#define MPU401_REG_COMMAND 0x01 // Commands
30#define MPU401_CMD_RESET 0xFF // Reset command
31#define MPU401_CMD_UART 0x3F // Switch to UART mod
32
33
34/*****************************************************************************
35 * Prototypes
36 */
37
38NTSTATUS NTAPI InitMPU(IN PINTERRUPTSYNC InterruptSync,IN PVOID DynamicContext);
45/*****************************************************************************
46 * Constants
47 */
48
52
53
54/*****************************************************************************
55 * Classes
56 */
57
58/*****************************************************************************
59 * CMiniportDMusUART
60 *****************************************************************************
61 * MPU-401 miniport. This object is associated with the device and is
62 * created when the device is started. The class inherits IMiniportDMus
63 * so it can expose this interface and CUnknown so it automatically gets
64 * reference counting and aggregation support.
65 */
66class CMiniportDMusUART : public CUnknownImpl<IMiniportDMus, IMusicTechnology, IPowerNotify>
67{
68private:
69 KSSTATE m_KSStateInput; // Miniport state (RUN/PAUSE/ACQUIRE/STOP)
70 PPORTDMUS m_pPort; // Callback interface.
71 PUCHAR m_pPortBase; // Base port address.
72 PINTERRUPTSYNC m_pInterruptSync; // Interrupt synchronization object.
73 PSERVICEGROUP m_pServiceGroup; // Service group for capture.
74 PMASTERCLOCK m_MasterClock; // for input data
75 REFERENCE_TIME m_InputTimeStamp; // capture data timestamp
76 USHORT m_NumRenderStreams; // Num active render streams.
77 USHORT m_NumCaptureStreams; // Num active capture streams.
78 ULONG m_MPUInputBufferHead; // Index of the newest byte in the FIFO.
79 ULONG m_MPUInputBufferTail; // Index of the oldest empty space in the FIFO.
81 POWER_STATE m_PowerState; // Saved power state (D0 = full power, D3 = off)
82 BOOLEAN m_fMPUInitialized; // Is the MPU HW initialized.
83 BOOLEAN m_UseIRQ; // FALSE if no IRQ is used for MIDI.
85
86 /*************************************************************************
87 * CMiniportDMusUART methods
88 *
89 * These are private member functions used internally by the object.
90 * See MINIPORT.CPP for specific descriptions.
91 */
93 (
95 );
96 NTSTATUS InitializeHardware(PINTERRUPTSYNC interruptSync,PUCHAR portBase);
97
98public:
100
102 virtual ~CMiniportDMusUART();
103
104 /*************************************************************************
105 * IMiniport methods
106 */
109 ( OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
110 );
113 ( IN ULONG PinId
114 , IN PKSDATARANGE DataRange
115 , IN PKSDATARANGE MatchingDataRange
117 , OUT PVOID ResultantFormat
118 , OUT PULONG ResultantFormatLength
119 )
120 {
122 }
123
124 /*************************************************************************
125 * IMiniportDMus methods
126 */
128 (
129 IN PUNKNOWN UnknownAdapter,
133 );
135 (
136 OUT PMXF * Stream,
137 IN PUNKNOWN OuterUnknown OPTIONAL,
146 );
148 ( void
149 );
150
151 /*************************************************************************
152 * IMusicTechnology methods
153 */
155
156 /*************************************************************************
157 * IPowerNotify methods
158 */
160
161 /*************************************************************************
162 * Friends
163 */
165 friend NTSTATUS NTAPI
167 friend NTSTATUS NTAPI
168 SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync,PVOID syncWriteContext);
169 friend VOID NTAPI
173};
174
175/*****************************************************************************
176 * CMiniportDMusUARTStream
177 *****************************************************************************
178 * MPU-401 miniport stream. This object is associated with the pin and is
179 * created when the pin is instantiated. It inherits IMXF
180 * so it can expose this interface and CUnknown so it automatically gets
181 * reference counting and aggregation support.
182 */
184{
185private:
187 REFERENCE_TIME m_SnapshotTimeStamp; // Current snapshot of miniport's input timestamp.
188 PUCHAR m_pPortBase; // Base port address.
189 BOOLEAN m_fCapture; // Whether this is capture.
190 long m_NumFailedMPUTries; // Deadman timeout for MPU hardware.
191 PAllocatorMXF m_AllocatorMXF; // source/sink for DMus structs
192 PMXF m_sinkMXF; // sink for DMus capture
193 PDMUS_KERNEL_EVENT m_DMKEvtQueue; // queue of waiting events
194 ULONG m_NumberOfRetries; // Number of consecutive times the h/w was busy/full
195 ULONG m_DMKEvtOffset; // offset into the event
196 KDPC m_Dpc; // DPC for timer
198 BOOL m_TimerQueued; // whether a timer has been set
199 KSPIN_LOCK m_DpcSpinLock; // protects the ConsumeEvents DPC
200
201 STDMETHODIMP_(NTSTATUS) SourceEvtsToPort();
202 STDMETHODIMP_(NTSTATUS) ConsumeEvents();
203 STDMETHODIMP_(NTSTATUS) PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt);
204
205public:
207
208 virtual ~CMiniportDMusUARTStream();
209
211 (
212 IN CMiniportDMusUART * pMiniport,
217 );
218
220 (
222 );
223
224 /*************************************************************************
225 * IMiniportStreamDMusUART methods
226 */
228
230 (
234 );
235
236 friend VOID NTAPI
238 (
239 IN PKDPC Dpc,
243 );
246};
247
248
249
250#define STR_MODULENAME "DMusUART:Miniport: "
251
252#ifdef _MSC_VER
253#pragma code_seg("PAGE")
254#endif
255
256#define UartFifoOkForWrite(status) ((status & MPU401_DRR) == 0)
257#define UartFifoOkForRead(status) ((status & MPU401_DSR) == 0)
258
259typedef struct
260{
266}
268
269/*****************************************************************************
270 * PinDataRangesStreamLegacy
271 * PinDataRangesStreamDMusic
272 *****************************************************************************
273 * Structures indicating range of valid format values for live pins.
274 */
275static
277{
278 {
279 {
280 sizeof(KSDATARANGE_MUSIC),
281 0,
282 0,
283 0,
287 }
288 },
290 0,
291 0,
292 0xFFFF
293};
294static
296{
297 {
298 {
299 sizeof(KSDATARANGE_MUSIC),
300 0,
301 0,
302 0,
306 }
307 },
309 0,
310 0,
311 0xFFFF
312};
313
314/*****************************************************************************
315 * PinDataRangePointersStreamLegacy
316 * PinDataRangePointersStreamDMusic
317 * PinDataRangePointersStreamCombined
318 *****************************************************************************
319 * List of pointers to structures indicating range of valid format values
320 * for live pins.
321 */
322static
324{
326};
327static
329{
331};
332static
334{
337};
338
339/*****************************************************************************
340 * PinDataRangesBridge
341 *****************************************************************************
342 * Structures indicating range of valid format values for bridge pins.
343 */
344static
346{
347 {
348 {
349 sizeof(KSDATARANGE),
350 0,
351 0,
352 0,
356 }
357 }
358};
359
360/*****************************************************************************
361 * PinDataRangePointersBridge
362 *****************************************************************************
363 * List of pointers to structures indicating range of valid format values
364 * for bridge pins.
365 */
366static
368{
370};
371
372/*****************************************************************************
373 * SynthProperties
374 *****************************************************************************
375 * List of properties in the Synth set.
376 */
377static
380{
381 // Global: S/Get synthesizer caps
382 {
387 },
388 // Global: S/Get port parameters
389 {
394 },
395 // Per stream: S/Get channel groups
396 {
401 },
402 // Per stream: Get current latency time
403 {
408 }
409};
412
413#define kMaxNumCaptureStreams 1
414#define kMaxNumLegacyRenderStreams 1
415#define kMaxNumDMusicRenderStreams 1
416
417/*****************************************************************************
418 * MiniportPins
419 *****************************************************************************
420 * List of pins.
421 */
422static
424{
425 {
427 NULL, // AutomationTable
428 { // KsPinDescriptor
429 0, // InterfacesCount
430 NULL, // Interfaces
431 0, // MediumsCount
432 NULL, // Mediums
435 KSPIN_DATAFLOW_IN, // DataFlow
436 KSPIN_COMMUNICATION_SINK, // Communication
437 (GUID *) &KSCATEGORY_AUDIO, // Category
438 &KSAUDFNAME_MIDI, // Name
439 {0} // Reserved
440 }
441 },
442 {
444 NULL, // AutomationTable
445 { // KsPinDescriptor
446 0, // InterfacesCount
447 NULL, // Interfaces
448 0, // MediumsCount
449 NULL, // Mediums
452 KSPIN_DATAFLOW_IN, // DataFlow
453 KSPIN_COMMUNICATION_SINK, // Communication
454 (GUID *) &KSCATEGORY_AUDIO, // Category
456 {0} // Reserved
457 }
458 },
459 {
460 0,0,0, // InstanceCount
461 NULL, // AutomationTable
462 { // KsPinDescriptor
463 0, // InterfacesCount
464 NULL, // Interfaces
465 0, // MediumsCount
466 NULL, // Mediums
467 SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount
468 PinDataRangePointersBridge, // DataRanges
469 KSPIN_DATAFLOW_OUT, // DataFlow
470 KSPIN_COMMUNICATION_NONE, // Communication
471 (GUID *) &KSCATEGORY_AUDIO, // Category
472 NULL, // Name
473 {0} // Reserved
474 }
475 },
476 {
477 0,0,0, // InstanceCount
478 NULL, // AutomationTable
479 { // KsPinDescriptor
480 0, // InterfacesCount
481 NULL, // Interfaces
482 0, // MediumsCount
483 NULL, // Mediums
484 SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount
485 PinDataRangePointersBridge, // DataRanges
486 KSPIN_DATAFLOW_IN, // DataFlow
487 KSPIN_COMMUNICATION_NONE, // Communication
488 (GUID *) &KSCATEGORY_AUDIO, // Category
489 NULL, // Name
490 {0} // Reserved
491 }
492 },
493 {
495 NULL, // AutomationTable
496 { // KsPinDescriptor
497 0, // InterfacesCount
498 NULL, // Interfaces
499 0, // MediumsCount
500 NULL, // Mediums
503 KSPIN_DATAFLOW_OUT, // DataFlow
504 KSPIN_COMMUNICATION_SINK, // Communication
505 (GUID *) &KSCATEGORY_AUDIO, // Category
507 {0} // Reserved
508 }
509 }
510};
511
512/*****************************************************************************
513 * MiniportNodes
514 *****************************************************************************
515 * List of nodes.
516 */
517#define CONST_PCNODE_DESCRIPTOR(n) { 0, NULL, &n, NULL }
518#define CONST_PCNODE_DESCRIPTOR_AUTO(n,a) { 0, &a, &n, NULL }
519static
521{
524};
525
526/*****************************************************************************
527 * MiniportConnections
528 *****************************************************************************
529 * List of connections.
530 */
531enum {
532 eSynthNode = 0
535
536enum {
543
544static
546{ // From To
547 // Node pin Node pin
548 { PCFILTER_NODE, eFilterInputPinLeg, PCFILTER_NODE, eBridgeOutputPin } // Legacy Stream in to synth.
549 , { PCFILTER_NODE, eFilterInputPinDM, eSynthNode, KSNODEPIN_STANDARD_IN } // DM Stream in to synth.
550 , { eSynthNode, KSNODEPIN_STANDARD_OUT, PCFILTER_NODE, eBridgeOutputPin } // Synth to bridge out.
551 , { PCFILTER_NODE, eBridgeInputPin, eInputNode, KSNODEPIN_STANDARD_IN } // Bridge in to input.
552 , { eInputNode, KSNODEPIN_STANDARD_OUT, PCFILTER_NODE, eFilterOutputPin } // Input to DM/Legacy Stream out.
553};
554
555/*****************************************************************************
556 * MiniportCategories
557 *****************************************************************************
558 * List of categories.
559 */
560static
562{
566};
567
568/*****************************************************************************
569 * MiniportFilterDescriptor
570 *****************************************************************************
571 * Complete miniport filter description.
572 */
573static
575{
576 0, // Version
577 NULL, // AutomationTable
578 sizeof(PCPIN_DESCRIPTOR), // PinSize
579 SIZEOF_ARRAY(MiniportPins), // PinCount
580 MiniportPins, // Pins
581 sizeof(PCNODE_DESCRIPTOR), // NodeSize
582 SIZEOF_ARRAY(MiniportNodes), // NodeCount
583 MiniportNodes, // Nodes
584 SIZEOF_ARRAY(MiniportConnections), // ConnectionCount
585 MiniportConnections, // Connections
586 SIZEOF_ARRAY(MiniportCategories), // CategoryCount
587 MiniportCategories // Categories
588};
589
590#ifdef _MSC_VER
591#pragma code_seg("PAGE")
592#endif
593
594BOOLEAN TryMPU(IN PUCHAR PortBase);
595NTSTATUS WriteMPU(IN PUCHAR PortBase,IN BOOLEAN IsCommand,IN UCHAR Value);
596
597#ifdef _MSC_VER
598#pragma code_seg("PAGE")
599#endif
600
601// make sure we're in UART mode
603{
604 PAGED_CODE();
605
606 return WriteMPU(portBase,COMMAND,MPU401_CMD_UART);
607}
608
609#ifdef _MSC_VER
610#pragma code_seg("PAGE")
611#endif
612
613//
614// We initialize the UART with interrupts suppressed so we don't
615// try to service the chip prematurely.
616//
618{
619 PAGED_CODE();
620
621 NTSTATUS ntStatus;
622 if (m_UseIRQ)
623 {
624 ntStatus = interruptSync->CallSynchronizedRoutine(InitMPU,PVOID(portBase));
625 }
626 else
627 {
628 ntStatus = InitMPU(NULL,PVOID(portBase));
629 }
630
631 if (NT_SUCCESS(ntStatus))
632 {
633 //
634 // Start the UART (this should trigger an interrupt).
635 //
636 ntStatus = ResetHardware(portBase);
637 }
638 else
639 {
640 DPRINT("*** InitMPU returned with ntStatus 0x%08x ***", ntStatus);
641 }
642
643 m_fMPUInitialized = NT_SUCCESS(ntStatus);
644
645 return ntStatus;
646}
647
648#ifdef _MSC_VER
649#pragma code_seg()
650#endif
651
652/*****************************************************************************
653 * InitMPU()
654 *****************************************************************************
655 * Synchronized routine to initialize the MPU401.
656 */
658NTAPI
660(
661 IN PINTERRUPTSYNC InterruptSync,
662 IN PVOID DynamicContext
663)
664{
665 DPRINT("InitMPU");
666 if (!DynamicContext)
667 {
669 }
670
671 PUCHAR portBase = PUCHAR(DynamicContext);
675 NTSTATUS ntStatus = STATUS_SUCCESS;
676
677 //
678 // Reset the card (puts it into "smart mode")
679 //
680 ntStatus = WriteMPU(portBase,COMMAND,MPU401_CMD_RESET);
681
682 // wait for the acknowledgement
683 // NOTE: When the Ack arrives, it will trigger an interrupt.
684 // Normally the DPC routine would read in the ack byte and we
685 // would never see it, however since we have the hardware locked (HwEnter),
686 // we can read the port before the DPC can and thus we receive the Ack.
688 success = FALSE;
690 {
692
693 if (UartFifoOkForRead(status)) // Is data waiting?
694 {
695 READ_PORT_UCHAR(portBase + MPU401_REG_DATA); // yep.. read ACK
696 success = TRUE; // don't need to do more
697 break;
698 }
699 KeStallExecutionProcessor(25); // microseconds
700 }
701#if (DBG)
702 if (!success)
703 {
704 DPRINT("First attempt to reset the MPU didn't get ACKed.\n");
705 }
706#endif // (DBG)
707
708 // NOTE: We cannot check the ACK byte because if the card was already in
709 // UART mode it will not send an ACK but it will reset.
710
711 // reset the card again
713
714 // wait for ack (again)
715 startTime = PcGetTimeInterval(0); // This might take a while
716 BYTE dataByte = 0;
717 success = FALSE;
719 {
721 if (UartFifoOkForRead(status)) // Is data waiting?
722 {
723 dataByte = READ_PORT_UCHAR(portBase + MPU401_REG_DATA); // yep.. read ACK
724 success = TRUE; // don't need to do more
725 break;
726 }
728 }
729
730 if ((0xFE != dataByte) || !success) // Did we succeed? If no second ACK, something is hosed
731 {
732 DPRINT("Second attempt to reset the MPU didn't get ACKed.\n");
733 DPRINT("Init Reset failure error. Ack = %X", ULONG(dataByte));
734
735 ntStatus = STATUS_IO_DEVICE_ERROR;
736 }
737
738 return ntStatus;
739}
740
741#ifdef _MSC_VER
742#pragma code_seg()
743#endif
744
745/*****************************************************************************
746 * CMiniportDMusUARTStream::Write()
747 *****************************************************************************
748 * Writes outgoing MIDI data.
749 */
751CMiniportDMusUARTStream::
752Write
753(
757)
758{
759 DPRINT("Write\n");
761 if (!BufferAddress)
762 {
763 Length = 0;
764 }
765
766 NTSTATUS ntStatus = STATUS_SUCCESS;
767
768 if (!m_fCapture)
769 {
770 PUCHAR pMidiData;
771 ULONG count;
772
773 count = 0;
774 pMidiData = PUCHAR(BufferAddress);
775
776 if (Length)
777 {
779 context.Miniport = (m_pMiniport);
780 context.PortBase = m_pPortBase;
781 context.BufferAddress = pMidiData;
782 context.Length = Length;
783 context.BytesRead = &count;
784
786 {
787 ntStatus = m_pMiniport->m_pInterruptSync->
788 CallSynchronizedRoutine(SynchronizedDMusMPUWrite,PVOID(&context));
789 }
790 else // !m_UseIRQ
791 {
793 } // !m_UseIRQ
794
795 if (count == 0)
796 {
798 if (m_NumFailedMPUTries >= 100)
799 {
800 ntStatus = STATUS_IO_DEVICE_ERROR;
802 }
803 }
804 else
805 {
807 }
808 } // if we have data at all
810 }
811 else // called write on the read stream
812 {
814 }
815 return ntStatus;
816}
817
818#ifdef _MSC_VER
819#pragma code_seg()
820#endif
821
822/*****************************************************************************
823 * SynchronizedDMusMPUWrite()
824 *****************************************************************************
825 * Writes outgoing MIDI data.
826 */
828NTAPI
830(
831 IN PINTERRUPTSYNC InterruptSync,
832 IN PVOID syncWriteContext
833)
834{
836 context = (PSYNCWRITECONTEXT)syncWriteContext;
837 ASSERT(context->Miniport);
838 ASSERT(context->PortBase);
839 ASSERT(context->BufferAddress);
840 ASSERT(context->Length);
841 ASSERT(context->BytesRead);
842
843 PUCHAR pChar = PUCHAR(context->BufferAddress);
844 NTSTATUS ntStatus; // , readStatus
845 ntStatus = STATUS_SUCCESS;
846 //
847 // while we're not there yet, and
848 // while we don't have to wait on an aligned byte (including 0)
849 // (we never wait on a byte. Better to come back later)
850 /*readStatus = */ DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport));
851 while ( (*(context->BytesRead) < context->Length)
852 && ( TryMPU(context->PortBase)
853 || (*(context->BytesRead)%3)
854 ) )
855 {
856 ntStatus = WriteMPU(context->PortBase,DATA,*pChar);
857 if (NT_SUCCESS(ntStatus))
858 {
859 pChar++;
860 *(context->BytesRead) = *(context->BytesRead) + 1;
861// readStatus = DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport));
862 }
863 else
864 {
865 DPRINT("SynchronizedDMusMPUWrite failed (0x%08x)",ntStatus);
866 break;
867 }
868 }
869 /*readStatus = */ DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport));
870 return ntStatus;
871}
872
873#define kMPUPollTimeout 2
874
875#ifdef _MSC_VER
876#pragma code_seg()
877#endif
878
879/*****************************************************************************
880 * TryMPU()
881 *****************************************************************************
882 * See if the MPU401 is free.
883 */
886(
887 IN PUCHAR PortBase
888)
889{
891 USHORT numPolls;
893
894 DPRINT("TryMPU");
895 numPolls = 0;
896
897 while (numPolls < kMPUPollTimeout)
898 {
900
901 if (UartFifoOkForWrite(status)) // Is this a good time to write data?
902 {
903 break;
904 }
905 numPolls++;
906 }
907 if (numPolls >= kMPUPollTimeout)
908 {
909 success = FALSE;
910 DPRINT("TryMPU failed");
911 }
912 else
913 {
914 success = TRUE;
915 }
916
917 return success;
918}
919
920#ifdef _MSC_VER
921#pragma code_seg()
922#endif
923
924/*****************************************************************************
925 * WriteMPU()
926 *****************************************************************************
927 * Write a byte out to the MPU401.
928 */
931(
932 IN PUCHAR PortBase,
933 IN BOOLEAN IsCommand,
935)
936{
937 DPRINT("WriteMPU");
939
940 if (!PortBase)
941 {
942 DPRINT("O: PortBase is zero\n");
943 return ntStatus;
944 }
945 PUCHAR deviceAddr = PortBase + MPU401_REG_DATA;
946
947 if (IsCommand)
948 {
949 deviceAddr = PortBase + MPU401_REG_COMMAND;
950 }
951
953
955 {
958
959 if (UartFifoOkForWrite(status)) // Is this a good time to write data?
960 { // yep (Jon comment)
961 WRITE_PORT_UCHAR(deviceAddr,Value);
962 DPRINT("WriteMPU emitted 0x%02x",Value);
963 ntStatus = STATUS_SUCCESS;
964 break;
965 }
966 }
967 return ntStatus;
968}
969
970#ifdef _MSC_VER
971#pragma code_seg()
972#endif
973
974/*****************************************************************************
975 * SnapTimeStamp()
976 *****************************************************************************
977 *
978 * At synchronized execution to ISR, copy miniport's volatile m_InputTimeStamp
979 * to stream's m_SnapshotTimeStamp and zero m_InputTimeStamp.
980 *
981 */
983SnapTimeStamp(PINTERRUPTSYNC InterruptSync,PVOID pStream)
984{
985 CMiniportDMusUARTStream *pMPStream = (CMiniportDMusUARTStream *)pStream;
986
987 // cache the timestamp
988 pMPStream->m_SnapshotTimeStamp = pMPStream->m_pMiniport->m_InputTimeStamp;
989
990 // if the window is closed, zero the timestamp
991 if (pMPStream->m_pMiniport->m_MPUInputBufferHead ==
993 {
994 pMPStream->m_pMiniport->m_InputTimeStamp = 0;
995 }
996
997 return STATUS_SUCCESS;
998}
999
1000/*****************************************************************************
1001 * CMiniportDMusUARTStream::SourceEvtsToPort()
1002 *****************************************************************************
1003 *
1004 * Reads incoming MIDI data, feeds into DMus events.
1005 * No need to touch the hardware, just read from our SW FIFO.
1006 *
1007 */
1009CMiniportDMusUARTStream::SourceEvtsToPort()
1010{
1011 NTSTATUS ntStatus;
1012
1014 DPRINT("SourceEvtsToPort");
1015
1016 if (m_fCapture)
1017 {
1018 ntStatus = STATUS_SUCCESS;
1020 {
1021 PDMUS_KERNEL_EVENT aDMKEvt,eventTail,eventHead = NULL;
1022
1024 {
1025 (void) m_AllocatorMXF->GetMessage(&aDMKEvt);
1026 if (!aDMKEvt)
1027 {
1028 DPRINT("SourceEvtsToPort can't allocate DMKEvt");
1030 }
1031
1032 // put this event at the end of the list
1033 if (!eventHead)
1034 {
1035 eventHead = aDMKEvt;
1036 }
1037 else
1038 {
1039 eventTail = eventHead;
1040 while (eventTail->pNextEvt)
1041 {
1042 eventTail = eventTail->pNextEvt;
1043 }
1044 eventTail->pNextEvt = aDMKEvt;
1045 }
1046 // read all the bytes out of the buffer, into event(s)
1047 for (aDMKEvt->cbEvent = 0; aDMKEvt->cbEvent < sizeof(PBYTE); aDMKEvt->cbEvent++)
1048 {
1050 {
1051// _DbgPrintF(DEBUGLVL_TERSE, ("SourceEvtsToPort m_MPUInputBufferHead met m_MPUInputBufferTail, overrun"));
1052 break;
1053 }
1057 {
1059 }
1060 }
1061 }
1062
1063 if (m_pMiniport->m_UseIRQ)
1064 {
1065 ntStatus = m_pMiniport->m_pInterruptSync->CallSynchronizedRoutine(SnapTimeStamp,PVOID(this));
1066 }
1067 else // !m_UseIRQ
1068 {
1069 ntStatus = SnapTimeStamp(NULL,PVOID(this));
1070 } // !m_UseIRQ
1071 aDMKEvt = eventHead;
1072 while (aDMKEvt)
1073 {
1075 aDMKEvt->usChannelGroup = 1;
1077 aDMKEvt = aDMKEvt->pNextEvt;
1078 }
1079 (void)m_sinkMXF->PutMessage(eventHead);
1080 }
1081 }
1082 else // render stream
1083 {
1084 DPRINT("SourceEvtsToPort called on render stream");
1086 }
1087 return ntStatus;
1088}
1089
1090#ifdef _MSC_VER
1091#pragma code_seg()
1092#endif
1093
1094/*****************************************************************************
1095 * DMusMPUInterruptServiceRoutine()
1096 *****************************************************************************
1097 * ISR.
1098 */
1100NTAPI
1102(
1103 IN PINTERRUPTSYNC InterruptSync,
1104 IN PVOID DynamicContext
1105)
1106{
1107 DPRINT("DMusMPUInterruptServiceRoutine");
1109
1110 ASSERT(DynamicContext);
1111
1112 NTSTATUS ntStatus;
1113 BOOL newBytesAvailable;
1114 CMiniportDMusUART *that;
1115 NTSTATUS clockStatus;
1116
1117 that = (CMiniportDMusUART *) DynamicContext;
1118 newBytesAvailable = FALSE;
1119 ntStatus = STATUS_UNSUCCESSFUL;
1120
1121 UCHAR portStatus = 0xff;
1122
1123 //
1124 // Read the MPU status byte.
1125 //
1126 if (that->m_pPortBase)
1127 {
1128 portStatus =
1130
1131 //
1132 // If there is outstanding work to do and there is a port-driver for
1133 // the MPU miniport...
1134 //
1135 if (UartFifoOkForRead(portStatus) && that->m_pPort)
1136 {
1139 && (UartFifoOkForRead(portStatus)) )
1140 {
1142 if ( (that->m_KSStateInput == KSSTATE_RUN)
1143 && (that->m_NumCaptureStreams)
1144 )
1145 {
1146 ULONG buffHead = that->m_MPUInputBufferHead;
1147 if ( (that->m_MPUInputBufferTail + 1 == buffHead)
1148 || (that->m_MPUInputBufferTail + 1 - kMPUInputBufferSize == buffHead))
1149 {
1150 DPRINT("*****MPU Input Buffer Overflow*****");
1151 }
1152 else
1153 {
1154 if (!that->m_InputTimeStamp)
1155 {
1156 clockStatus = that->m_MasterClock->GetTime(&that->m_InputTimeStamp);
1157 if (STATUS_SUCCESS != clockStatus)
1158 {
1159 DPRINT("GetTime failed for clock 0x%08x",that->m_MasterClock);
1160 }
1161 }
1162 newBytesAvailable = TRUE;
1163 // ...place the data in our FIFO...
1164 that->m_MPUInputBuffer[that->m_MPUInputBufferTail] = uDest;
1166
1167 that->m_MPUInputBufferTail++;
1169 {
1170 that->m_MPUInputBufferTail = 0;
1171 }
1172 }
1173 }
1174 //
1175 // Look for more MIDI data.
1176 //
1177 portStatus =
1179 } // either there's no data or we ran too long
1180 if (newBytesAvailable)
1181 {
1182 //
1183 // ...notify the MPU port driver that we have bytes.
1184 //
1185 that->m_pPort->Notify(that->m_pServiceGroup);
1186 }
1187 ntStatus = STATUS_SUCCESS;
1188 }
1189 }
1190
1191 return ntStatus;
1192}
1193
1194/*****************************************************************************
1195 * CMiniportDMusUART::GetDescription()
1196 *****************************************************************************
1197 * Gets the topology.
1198 */
1201GetDescription
1202(
1203 OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
1204)
1205{
1206 PAGED_CODE();
1207
1208 ASSERT(OutFilterDescriptor);
1209
1210 DPRINT("GetDescription");
1211
1212 *OutFilterDescriptor = &MiniportFilterDescriptor;
1213
1214 return STATUS_SUCCESS;
1215}
1216
1217#ifdef _MSC_VER
1218#pragma code_seg("PAGE")
1219#endif
1220
1223 OUT PMINIPORT* OutMiniport,
1224 IN REFCLSID ClassId)
1225{
1228
1230 if (!This)
1232
1233 Status = This->QueryInterface(IID_IMiniport, (PVOID*)OutMiniport);
1234
1235 if (!NT_SUCCESS(Status))
1236 {
1237 delete This;
1238 }
1239
1240 DPRINT("NewMiniportDMusUART %p Status %x\n", *OutMiniport, Status);
1241 return Status;
1242}
1243
1244
1245#ifdef _MSC_VER
1246#pragma code_seg("PAGE")
1247#endif
1248
1249/*****************************************************************************
1250 * CMiniportDMusUART::ProcessResources()
1251 *****************************************************************************
1252 * Processes the resource list, setting up helper objects accordingly.
1253 */
1257(
1259)
1260{
1261 PAGED_CODE();
1262
1263 DPRINT("ProcessResources");
1264
1266 if (!ResourceList)
1267 {
1269 }
1270 //
1271 // Get counts for the types of resources.
1272 //
1273 ULONG countIO = ResourceList->NumberOfPorts();
1274 ULONG countIRQ = ResourceList->NumberOfInterrupts();
1275 ULONG countDMA = ResourceList->NumberOfDmas();
1276 ULONG lengthIO = ResourceList->FindTranslatedPort(0)->u.Port.Length;
1277
1278#if DBG
1279 DPRINT("Starting MPU401 Port 0x%lx", ResourceList->FindTranslatedPort(0)->u.Port.Start.LowPart);
1280#endif
1281
1282 NTSTATUS ntStatus = STATUS_SUCCESS;
1283
1284 //
1285 // Make sure we have the expected number of resources.
1286 //
1287 if ( (countIO != 1)
1288 || (countIRQ > 1)
1289 || (countDMA != 0)
1290 || (lengthIO == 0)
1291 )
1292 {
1293 DPRINT("Unknown ResourceList configuration");
1295 }
1296
1297 if (NT_SUCCESS(ntStatus))
1298 {
1299 //
1300 // Get the port address.
1301 //
1302 m_pPortBase =
1303 PUCHAR(ResourceList->FindTranslatedPort(0)->u.Port.Start.QuadPart);
1304
1306 }
1307
1308 return ntStatus;
1309}
1310
1311#ifdef _MSC_VER
1312#pragma code_seg("PAGE")
1313#endif
1314/*****************************************************************************
1315 * CMiniportDMusUART::NonDelegatingQueryInterface()
1316 *****************************************************************************
1317 * Obtains an interface. This function works just like a COM QueryInterface
1318 * call and is used if the object is not being aggregated.
1319 */
1322(
1324 PVOID * Object
1325)
1326{
1327 PAGED_CODE();
1328
1329 DPRINT("Miniport::NonDelegatingQueryInterface");
1330 ASSERT(Object);
1331
1333 {
1335 }
1336 else
1337 if (IsEqualGUIDAligned(Interface,IID_IMiniport))
1338 {
1339 *Object = PVOID(PMINIPORT(this));
1340 }
1341 else
1342 if (IsEqualGUIDAligned(Interface,IID_IMiniportDMus))
1343 {
1344 *Object = PVOID(PMINIPORTDMUS(this));
1345 }
1346 else
1347 if (IsEqualGUIDAligned(Interface,IID_IMusicTechnology))
1348 {
1349 *Object = PVOID(PMUSICTECHNOLOGY(this));
1350 }
1351 else
1352 if (IsEqualGUIDAligned(Interface,IID_IPowerNotify))
1353 {
1354 *Object = PVOID(PPOWERNOTIFY(this));
1355 }
1356 else
1357 {
1358 *Object = NULL;
1359 }
1360
1361 if (*Object)
1362 {
1363 //
1364 // We reference the interface for the caller.
1365 //
1366 PUNKNOWN(*Object)->AddRef();
1367 return STATUS_SUCCESS;
1368 }
1369
1371}
1372
1373#ifdef _MSC_VER
1374#pragma code_seg("PAGE")
1375#endif
1376/*****************************************************************************
1377 * CMiniportDMusUART::~CMiniportDMusUART()
1378 *****************************************************************************
1379 * Destructor.
1380 */
1382{
1383 PAGED_CODE();
1384
1385 DPRINT("~CMiniportDMusUART");
1386
1389
1390 // reset the HW so we don't get anymore interrupts
1392 {
1394 }
1395 else
1396 {
1398 }
1399
1400 if (m_pInterruptSync)
1401 {
1402 m_pInterruptSync->Release();
1404 }
1405 if (m_pServiceGroup)
1406 {
1407 m_pServiceGroup->Release();
1409 }
1410 if (m_pPort)
1411 {
1412 m_pPort->Release();
1413 m_pPort = NULL;
1414 }
1415}
1416
1417#ifdef _MSC_VER
1418#pragma code_seg("PAGE")
1419#endif
1420/*****************************************************************************
1421 * CMiniportDMusUART::Init()
1422 *****************************************************************************
1423 * Initializes a the miniport.
1424 */
1426CMiniportDMusUART::
1427Init
1428(
1429 IN PUNKNOWN UnknownInterruptSync OPTIONAL,
1431 IN PPORTDMUS Port_,
1432 OUT PSERVICEGROUP * ServiceGroup
1433)
1434{
1435 PAGED_CODE();
1436
1438 if (!ResourceList)
1439 {
1441 }
1442
1443 ASSERT(Port_);
1445
1446 DPRINT("Init");
1447
1448 *ServiceGroup = NULL;
1449 m_pPortBase = 0;
1451
1452 // This will remain unspecified if the miniport does not get any power
1453 // messages.
1454 //
1456
1457 //
1458 // AddRef() is required because we are keeping this pointer.
1459 //
1460 m_pPort = Port_;
1461 m_pPort->AddRef();
1462
1463 // Set dataformat.
1464 //
1466 {
1469 sizeof(GUID));
1470 }
1473 sizeof(GUID));
1476 sizeof(GUID));
1477
1478 for (ULONG bufferCount = 0;bufferCount < kMPUInputBufferSize;bufferCount++)
1479 {
1480 m_MPUInputBuffer[bufferCount] = 0;
1481 }
1484 m_InputTimeStamp = 0;
1486
1487 NTSTATUS ntStatus = STATUS_SUCCESS;
1488
1491
1492 m_UseIRQ = TRUE;
1493 if (ResourceList->NumberOfInterrupts() == 0)
1494 {
1495 m_UseIRQ = FALSE;
1496 }
1497
1499 if (NT_SUCCESS(ntStatus) && !m_pServiceGroup) // keep any error
1500 {
1502 }
1503
1504 if (NT_SUCCESS(ntStatus))
1505 {
1507 m_pServiceGroup->AddRef();
1508
1509 //
1510 // Register the service group with the port early so the port is
1511 // prepared to handle interrupts.
1512 //
1513 m_pPort->RegisterServiceGroup(m_pServiceGroup);
1514 }
1515
1516 if (NT_SUCCESS(ntStatus) && m_UseIRQ)
1517 {
1518 //
1519 // Due to a bug in the InterruptSync design, we shouldn't share
1520 // the interrupt sync object. Whoever goes away first
1521 // will disconnect it, and the other points off into nowhere.
1522 //
1523 // Instead we generate our own interrupt sync object.
1524 //
1525 UnknownInterruptSync = NULL;
1526
1527 if (UnknownInterruptSync)
1528 {
1529 ntStatus =
1530 UnknownInterruptSync->QueryInterface
1531 (
1532 IID_IInterruptSync,
1534 );
1535
1536 if (!m_pInterruptSync && NT_SUCCESS(ntStatus)) // keep any error
1537 {
1539 }
1540 if (NT_SUCCESS(ntStatus))
1541 { // run this ISR first
1542 ntStatus = m_pInterruptSync->
1543 RegisterServiceRoutine(DMusMPUInterruptServiceRoutine,PVOID(this),TRUE);
1544 }
1545
1546 }
1547 else
1548 { // create our own interruptsync mechanism.
1549 ntStatus =
1551 (
1553 NULL,
1555 0, // Resource Index
1556 InterruptSyncModeNormal // Run ISRs once until we get SUCCESS
1557 );
1558
1559 if (!m_pInterruptSync && NT_SUCCESS(ntStatus)) // keep any error
1560 {
1562 }
1563
1564 if (NT_SUCCESS(ntStatus))
1565 {
1566 ntStatus = m_pInterruptSync->RegisterServiceRoutine(
1568 PVOID(this),
1569 TRUE); // run this ISR first
1570 }
1571 if (NT_SUCCESS(ntStatus))
1572 {
1573 ntStatus = m_pInterruptSync->Connect();
1574 }
1575 }
1576 }
1577
1578 if (NT_SUCCESS(ntStatus))
1579 {
1580 ntStatus = ProcessResources(ResourceList);
1581 }
1582
1583 if (!NT_SUCCESS(ntStatus))
1584 {
1585 //
1586 // clean up our mess
1587 //
1588
1589 // clean up the interrupt sync
1590 if( m_pInterruptSync )
1591 {
1592 m_pInterruptSync->Release();
1594 }
1595
1596 // clean up the service group
1597 if( m_pServiceGroup )
1598 {
1599 m_pServiceGroup->Release();
1601 }
1602
1603 // clean up the out param service group.
1604 if (*ServiceGroup)
1605 {
1606 (*ServiceGroup)->Release();
1607 (*ServiceGroup) = NULL;
1608 }
1609
1610 // release the port
1611 m_pPort->Release();
1612 m_pPort = NULL;
1613 }
1614
1615 return ntStatus;
1616}
1617
1618#ifdef _MSC_VER
1619#pragma code_seg("PAGE")
1620#endif
1621/*****************************************************************************
1622 * CMiniportDMusUART::NewStream()
1623 *****************************************************************************
1624 * Gets the topology.
1625 */
1627CMiniportDMusUART::
1628NewStream
1629(
1630 OUT PMXF * MXF,
1631 IN PUNKNOWN OuterUnknown OPTIONAL,
1633 IN ULONG PinID,
1634 IN DMUS_STREAM_TYPE StreamType,
1636 OUT PSERVICEGROUP * ServiceGroup,
1637 IN PAllocatorMXF AllocatorMXF,
1639 OUT PULONGLONG SchedulePreFetch
1640)
1641{
1642 PAGED_CODE();
1643
1644 DPRINT("NewStream");
1645 NTSTATUS ntStatus = STATUS_SUCCESS;
1646
1647 // In 100 ns, we want stuff as soon as it comes in
1648 //
1649 *SchedulePreFetch = 0;
1650
1651 // if we don't have any streams already open, get the hardware ready.
1653 {
1654 ntStatus = ResetHardware(m_pPortBase);
1655 if (!NT_SUCCESS(ntStatus))
1656 {
1657 DPRINT("CMiniportDMusUART::NewStream ResetHardware failed");
1658 return ntStatus;
1659 }
1660 }
1661
1666 )
1667 {
1669 new(PoolType, 'wNcP') CMiniportDMusUARTStream();
1670
1671 if (pStream)
1672 {
1673 pStream->AddRef();
1674
1675 ntStatus =
1677
1678 if (NT_SUCCESS(ntStatus))
1679 {
1680 *MXF = PMXF(pStream);
1681 (*MXF)->AddRef();
1682
1684 {
1687 (*ServiceGroup)->AddRef();
1688 }
1689 else
1690 {
1692 *ServiceGroup = NULL;
1693 }
1694 }
1695
1696 pStream->Release();
1697 }
1698 else
1699 {
1701 }
1702 }
1703 else
1704 {
1707 {
1708 DPRINT("NewStream failed, too many capture streams");
1709 }
1711 {
1712 DPRINT("NewStream failed, too many render streams");
1713 }
1714 else
1715 {
1716 DPRINT("NewStream invalid stream type");
1717 }
1718 }
1719
1720 return ntStatus;
1721}
1722
1723#ifdef _MSC_VER
1724#pragma code_seg("PAGE")
1725#endif
1726/*****************************************************************************
1727 * CMiniportDMusUART::SetTechnology()
1728 *****************************************************************************
1729 * Sets pindatarange technology.
1730 */
1732CMiniportDMusUART::
1733SetTechnology
1734(
1735 IN const GUID * Technology
1736)
1737{
1738 PAGED_CODE();
1739
1740 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1741
1742 // Fail if miniport has already been initialized.
1743 //
1744 if (NULL == m_pPort)
1745 {
1746 RtlCopyMemory(&m_MusicFormatTechnology, Technology, sizeof(GUID));
1747 ntStatus = STATUS_SUCCESS;
1748 }
1749
1750 return ntStatus;
1751} // SetTechnology
1752
1753/*****************************************************************************
1754 * CMiniportDMusUART::PowerChangeNotify()
1755 *****************************************************************************
1756 * Handle power state change for the miniport.
1757 */
1758#ifdef _MSC_VER
1759#pragma code_seg("PAGE")
1760#endif
1761
1762STDMETHODIMP_(void)
1763CMiniportDMusUART::
1764PowerChangeNotify
1765(
1767)
1768{
1769 PAGED_CODE();
1770
1771 DPRINT("CMiniportDMusUART::PoweChangeNotify D%d", PowerState.DeviceState);
1772
1773 switch (PowerState.DeviceState)
1774 {
1775 case PowerDeviceD0:
1777 {
1779 {
1780 DPRINT("InitializeHardware failed when resuming");
1781 }
1782 }
1783 break;
1784
1785 case PowerDeviceD1:
1786 case PowerDeviceD2:
1787 case PowerDeviceD3:
1788 default:
1789 break;
1790 }
1791 m_PowerState.DeviceState = PowerState.DeviceState;
1792} // PowerChangeNotify
1793
1794#ifdef _MSC_VER
1795#pragma code_seg("PAGE")
1796#endif
1797/*****************************************************************************
1798 * CMiniportDMusUARTStream::NonDelegatingQueryInterface()
1799 *****************************************************************************
1800 * Obtains an interface. This function works just like a COM QueryInterface
1801 * call and is used if the object is not being aggregated.
1802 */
1805(
1807 PVOID * Object
1808)
1809{
1810 PAGED_CODE();
1811
1812 DPRINT("Stream::NonDelegatingQueryInterface");
1813 ASSERT(Object);
1814
1816 {
1817 *Object = PVOID(PUNKNOWN(this));
1818 }
1819 else
1821 {
1822 *Object = PVOID(PMXF(this));
1823 }
1824 else
1825 {
1826 *Object = NULL;
1827 }
1828
1829 if (*Object)
1830 {
1831 //
1832 // We reference the interface for the caller.
1833 //
1834 PUNKNOWN(*Object)->AddRef();
1835 return STATUS_SUCCESS;
1836 }
1837
1839}
1840
1841#ifdef _MSC_VER
1842#pragma code_seg("PAGE")
1843#endif
1844/*****************************************************************************
1845 * CMiniportDMusUARTStream::~CMiniportDMusUARTStream()
1846 *****************************************************************************
1847 * Destructs a stream.
1848 */
1850{
1851 PAGED_CODE();
1852
1853 DPRINT("~CMiniportDMusUARTStream");
1854
1856
1857 if (m_DMKEvtQueue)
1858 {
1859 if (m_AllocatorMXF)
1860 {
1861 m_AllocatorMXF->PutMessage(m_DMKEvtQueue);
1862 }
1863 else
1864 {
1865 DPRINT("~CMiniportDMusUARTStream, no allocator, can't flush DMKEvts");
1866 }
1868 }
1869 if (m_AllocatorMXF)
1870 {
1871 m_AllocatorMXF->Release();
1873 }
1874
1875 if (m_pMiniport)
1876 {
1877 if (m_fCapture)
1878 {
1880 }
1881 else
1882 {
1884 }
1885
1886 m_pMiniport->Release();
1887 }
1888}
1889
1890#ifdef _MSC_VER
1891#pragma code_seg("PAGE")
1892#endif
1893/*****************************************************************************
1894 * CMiniportDMusUARTStream::Init()
1895 *****************************************************************************
1896 * Initializes a stream.
1897 */
1899CMiniportDMusUARTStream::
1900Init
1901(
1902 IN CMiniportDMusUART * pMiniport,
1903 IN PUCHAR pPortBase,
1904 IN BOOLEAN fCapture,
1905 IN PAllocatorMXF allocatorMXF,
1906 IN PMASTERCLOCK masterClock
1907)
1908{
1909 PAGED_CODE();
1910
1911 ASSERT(pMiniport);
1913
1914 DPRINT("Init");
1915
1919 m_pMiniport = pMiniport;
1920 m_pMiniport->AddRef();
1921
1922 pMiniport->m_MasterClock = masterClock;
1923
1926
1929 m_DMKEvtOffset = 0;
1930
1932
1933 if (allocatorMXF)
1934 {
1935 allocatorMXF->AddRef();
1938 }
1939 else
1940 {
1942 }
1943
1945 (
1946 &m_Dpc,
1948 PVOID(this)
1949 );
1951
1952 return STATUS_SUCCESS;
1953}
1954
1955#ifdef _MSC_VER
1956#pragma code_seg("PAGE")
1957#endif
1958/*****************************************************************************
1959 * CMiniportDMusUARTStream::SetState()
1960 *****************************************************************************
1961 * Sets the state of the channel.
1962 */
1964CMiniportDMusUARTStream::
1965SetState
1966(
1967 IN KSSTATE NewState
1968)
1969{
1970 PAGED_CODE();
1971
1972 DPRINT("SetState %d",NewState);
1973
1974 if (NewState == KSSTATE_RUN)
1975 {
1977 {
1978 LARGE_INTEGER timeDue100ns;
1979 timeDue100ns.QuadPart = 0;
1980 KeSetTimer(&m_TimerEvent,timeDue100ns,&m_Dpc);
1981 }
1982 else
1983 {
1984 DPRINT("CMiniportDMusUARTStream::SetState KSSTATE_RUN failed due to uninitialized MPU");
1986 }
1987 }
1988
1989 if (m_fCapture)
1990 {
1991 m_pMiniport->m_KSStateInput = NewState;
1992 if (NewState == KSSTATE_STOP) // STOPping
1993 {
1994 m_pMiniport->m_MPUInputBufferHead = 0; // Previously read bytes are discarded.
1995 m_pMiniport->m_MPUInputBufferTail = 0; // The entire FIFO is available.
1996 }
1997 }
1998 return STATUS_SUCCESS;
1999}
2000
2001#ifdef _MSC_VER
2002#pragma code_seg()
2003#endif
2004
2005
2006/*****************************************************************************
2007 * CMiniportDMusUART::Service()
2008 *****************************************************************************
2009 * DPC-mode service call from the port.
2010 */
2011STDMETHODIMP_(void)
2012CMiniportDMusUART::
2013Service
2014( void
2015)
2016{
2017 DPRINT("Service");
2019 {
2020 // we should never get here....
2021 // if we do, we must have read some trash,
2022 // so just reset the input FIFO
2024 }
2025}
2026
2027#ifdef _MSC_VER
2028#pragma code_seg("PAGE")
2029#endif
2030
2031/*****************************************************************************
2032 * CMiniportDMusUARTStream::ConnectOutput()
2033 *****************************************************************************
2034 * Writes outgoing MIDI data.
2035 */
2037CMiniportDMusUARTStream::
2038ConnectOutput(PMXF sinkMXF)
2039{
2040 PAGED_CODE();
2041
2042 if (m_fCapture)
2043 {
2044 if ((sinkMXF) && (m_sinkMXF == m_AllocatorMXF))
2045 {
2046 DPRINT("ConnectOutput");
2047 m_sinkMXF = sinkMXF;
2048 return STATUS_SUCCESS;
2049 }
2050 else
2051 {
2052 DPRINT("ConnectOutput failed");
2053 }
2054 }
2055 else
2056 {
2057 DPRINT("ConnectOutput called on renderer; failed");
2058 }
2059 return STATUS_UNSUCCESSFUL;
2060}
2061
2062#ifdef _MSC_VER
2063#pragma code_seg("PAGE")
2064#endif
2065
2066/*****************************************************************************
2067 * CMiniportDMusUARTStream::DisconnectOutput()
2068 *****************************************************************************
2069 * Writes outgoing MIDI data.
2070 */
2072CMiniportDMusUARTStream::
2073DisconnectOutput(PMXF sinkMXF)
2074{
2075 PAGED_CODE();
2076
2077 if (m_fCapture)
2078 {
2079 if ((m_sinkMXF == sinkMXF) || (!sinkMXF))
2080 {
2081 DPRINT("DisconnectOutput");
2083 return STATUS_SUCCESS;
2084 }
2085 else
2086 {
2087 DPRINT("DisconnectOutput failed");
2088 }
2089 }
2090 else
2091 {
2092 DPRINT("DisconnectOutput called on renderer; failed");
2093 }
2094 return STATUS_UNSUCCESSFUL;
2095}
2096
2097#ifdef _MSC_VER
2098#pragma code_seg()
2099#endif
2100
2101
2102/*****************************************************************************
2103 * CMiniportDMusUARTStream::PutMessageLocked()
2104 *****************************************************************************
2105 * Now that the spinlock is held, add this message to the queue.
2106 *
2107 * Writes an outgoing MIDI message.
2108 * We don't sort a new message into the queue -- we append it.
2109 * This is fine, since the sequencer feeds us sequenced data.
2110 * Timestamps will ascend by design.
2111 */
2112NTSTATUS CMiniportDMusUARTStream::PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt)
2113{
2114 NTSTATUS ntStatus = STATUS_SUCCESS;
2115 PDMUS_KERNEL_EVENT aDMKEvt;
2116
2118
2119 if (!m_fCapture)
2120 {
2121 DPRINT("PutMessage to render stream");
2122 if (pDMKEvt)
2123 {
2124 // m_DpcSpinLock already held
2125
2126 if (m_DMKEvtQueue)
2127 {
2128 aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue
2129
2130 while (aDMKEvt->pNextEvt)
2131 {
2132 aDMKEvt = aDMKEvt->pNextEvt;
2133 }
2134 aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue
2135 }
2136 else // currently nothing in queue
2137 {
2138 m_DMKEvtQueue = pDMKEvt;
2139 if (m_DMKEvtOffset)
2140 {
2141 DPRINT("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d",m_DMKEvtOffset);
2142 m_DMKEvtOffset = 0;
2143 }
2144 }
2145
2146 // m_DpcSpinLock already held
2147 }
2148 if (!m_TimerQueued)
2149 {
2150 (void) ConsumeEvents();
2151 }
2152 }
2153 else // capture
2154 {
2155 DPRINT("PutMessage to capture stream");
2156 ASSERT(NULL == pDMKEvt);
2157
2158 SourceEvtsToPort();
2159 }
2160 return ntStatus;
2161}
2162
2163#ifdef _MSC_VER
2164#pragma code_seg()
2165#endif
2166
2167/*****************************************************************************
2168 * CMiniportDMusUARTStream::PutMessage()
2169 *****************************************************************************
2170 * Writes an outgoing MIDI message.
2171 * We don't sort a new message into the queue -- we append it.
2172 * This is fine, since the sequencer feeds us sequenced data.
2173 * Timestamps will ascend by design.
2174 */
2175NTSTATUS CMiniportDMusUARTStream::PutMessage(PDMUS_KERNEL_EVENT pDMKEvt)
2176{
2177 NTSTATUS ntStatus = STATUS_SUCCESS;
2178 PDMUS_KERNEL_EVENT aDMKEvt;
2179
2181
2182 if (!m_fCapture)
2183 {
2184 DPRINT("PutMessage to render stream");
2185 if (pDMKEvt)
2186 {
2188
2189 if (m_DMKEvtQueue)
2190 {
2191 aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue
2192
2193 while (aDMKEvt->pNextEvt)
2194 {
2195 aDMKEvt = aDMKEvt->pNextEvt;
2196 }
2197 aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue
2198 }
2199 else // currently nothing in queue
2200 {
2201 m_DMKEvtQueue = pDMKEvt;
2202 if (m_DMKEvtOffset)
2203 {
2204 DPRINT("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d", m_DMKEvtOffset);
2205 m_DMKEvtOffset = 0;
2206 }
2207 }
2208
2210 }
2211 if (!m_TimerQueued)
2212 {
2213 (void) ConsumeEvents();
2214 }
2215 }
2216 else // capture
2217 {
2218 DPRINT("PutMessage to capture stream");
2219 ASSERT(NULL == pDMKEvt);
2220
2221 SourceEvtsToPort();
2222 }
2223 return ntStatus;
2224}
2225
2226#ifdef _MSC_VER
2227#pragma code_seg()
2228#endif
2229
2230/*****************************************************************************
2231 * CMiniportDMusUARTStream::ConsumeEvents()
2232 *****************************************************************************
2233 * Attempts to empty the render message queue.
2234 * Called either from DPC timer or upon IRP submittal.
2235// TODO: support packages right
2236// process the package (actually, should do this above.
2237// treat the package as a list fragment that shouldn't be sorted.
2238// better yet, go through each event in the package, and when
2239// an event is exhausted, delete it and decrement m_offset.
2240 */
2241NTSTATUS CMiniportDMusUARTStream::ConsumeEvents(void)
2242{
2243 PDMUS_KERNEL_EVENT aDMKEvt;
2244
2245 NTSTATUS ntStatus = STATUS_SUCCESS;
2246 ULONG bytesRemaining = 0,bytesWritten = 0;
2247 LARGE_INTEGER aMillisecIn100ns;
2248
2251
2253 while (m_DMKEvtQueue) // do we have anything to play at all?
2254 {
2255 aDMKEvt = m_DMKEvtQueue; // event we try to play
2256 if (aDMKEvt->cbEvent)
2257 {
2258 bytesRemaining = aDMKEvt->cbEvent - m_DMKEvtOffset; // number of bytes left in this evt
2259
2260 ASSERT(bytesRemaining > 0);
2261 if (bytesRemaining <= 0)
2262 {
2263 bytesRemaining = aDMKEvt->cbEvent;
2264 }
2265
2266 if (aDMKEvt->cbEvent <= sizeof(PBYTE)) // short message
2267 {
2268 DPRINT("ConsumeEvents(%02x%02x%02x%02x)", aDMKEvt->uData.abData[0], aDMKEvt->uData.abData[1], aDMKEvt->uData.abData[2], aDMKEvt->uData.abData[3]);
2269 ntStatus = Write(aDMKEvt->uData.abData + m_DMKEvtOffset,bytesRemaining,&bytesWritten);
2270 }
2271 else if (PACKAGE_EVT(aDMKEvt))
2272 {
2273 ASSERT(m_DMKEvtOffset == 0);
2274 m_DMKEvtOffset = 0;
2275 DPRINT("ConsumeEvents(Package)");
2276
2277 ntStatus = PutMessageLocked(aDMKEvt->uData.pPackageEvt); // we already own the spinlock
2278
2279 // null this because we are about to throw it in the allocator
2280 aDMKEvt->uData.pPackageEvt = NULL;
2281 aDMKEvt->cbEvent = 0;
2282 bytesWritten = bytesRemaining;
2283 }
2284 else // SysEx message
2285 {
2286 DPRINT("ConsumeEvents(%02x%02x%02x%02x)", aDMKEvt->uData.pbData[0], aDMKEvt->uData.pbData[1], aDMKEvt->uData.pbData[2], aDMKEvt->uData.pbData[3]);
2287
2288 ntStatus = Write(aDMKEvt->uData.pbData + m_DMKEvtOffset,bytesRemaining,&bytesWritten);
2289 }
2290 } // if (aDMKEvt->cbEvent)
2291 if (STATUS_SUCCESS != ntStatus)
2292 {
2293 DPRINT("ConsumeEvents: Write returned 0x%08x", ntStatus);
2294 bytesWritten = bytesRemaining; // just bail on this event and try next time
2295 }
2296
2297 ASSERT(bytesWritten <= bytesRemaining);
2298 if (bytesWritten == bytesRemaining)
2299 {
2301 aDMKEvt->pNextEvt = NULL;
2302
2303 m_AllocatorMXF->PutMessage(aDMKEvt); // throw back in free pool
2304 m_DMKEvtOffset = 0; // start fresh on next evt
2306 } // but wait ... there's more!
2307 else // our FIFO is full for now.
2308 {
2309 // update our offset by that amount we did write
2311 ASSERT(m_DMKEvtOffset < aDMKEvt->cbEvent);
2312
2313 DPRINT("ConsumeEvents tried %d, wrote %d, at offset %d", bytesRemaining,bytesWritten,m_DMKEvtOffset);
2314 aMillisecIn100ns.QuadPart = -(kOneMillisec); // set timer, come back later
2317 ntStatus = KeSetTimer( &m_TimerEvent, aMillisecIn100ns, &m_Dpc );
2318 break;
2319 } // we didn't write it all
2320 } // go back, Jack, do it again (while m_DMKEvtQueue)
2322 return ntStatus;
2323}
2324
2325#ifdef _MSC_VER
2326#pragma code_seg()
2327#endif
2328
2329/*****************************************************************************
2330 * CMiniportDMusUARTStream::HandlePortParams()
2331 *****************************************************************************
2332 * Writes an outgoing MIDI message.
2333 */
2337(
2339)
2340{
2341 PAGED_CODE();
2342
2343 NTSTATUS ntStatus;
2344
2345 if (pRequest->Verb & KSPROPERTY_TYPE_SET)
2346 {
2348 }
2349
2351 if (NT_SUCCESS(ntStatus))
2352 {
2353 RtlCopyMemory(pRequest->Value, pRequest->Instance, sizeof(SYNTH_PORTPARAMS));
2354
2356
2357 if (Params->ValidParams & ~SYNTH_PORTPARAMS_CHANNELGROUPS)
2358 {
2359 Params->ValidParams &= SYNTH_PORTPARAMS_CHANNELGROUPS;
2360 }
2361
2362 if (!(Params->ValidParams & SYNTH_PORTPARAMS_CHANNELGROUPS))
2363 {
2364 Params->ChannelGroups = 1;
2365 }
2366 else if (Params->ChannelGroups != 1)
2367 {
2368 Params->ChannelGroups = 1;
2369 }
2370
2371 pRequest->ValueSize = sizeof(SYNTH_PORTPARAMS);
2372 }
2373
2374 return ntStatus;
2375}
2376
2377#ifdef _MSC_VER
2378#pragma code_seg()
2379#endif
2380
2381/*****************************************************************************
2382 * DMusTimerDPC()
2383 *****************************************************************************
2384 * The timer DPC callback. Thunks to a C++ member function.
2385 * This is called by the OS in response to the DirectMusic pin
2386 * wanting to wakeup later to process more DirectMusic stuff.
2387 */
2388VOID
2389NTAPI
2391(
2392 IN PKDPC Dpc,
2396)
2397{
2399
2400 CMiniportDMusUARTStream *aStream;
2402 if (aStream)
2403 {
2404 DPRINT("DMusUARTTimerDPC");
2405 if (false == aStream->m_fCapture)
2406 {
2407 (void) aStream->ConsumeEvents();
2408 }
2409 // ignores return value!
2410 }
2411}
2412
2413/*****************************************************************************
2414 * DirectMusic properties
2415 ****************************************************************************/
2416
2417#ifdef _MSC_VER
2418#pragma code_seg()
2419#endif
2420
2421/*
2422 * Properties concerning synthesizer functions.
2423 */
2424const WCHAR wszDescOut[] = L"DMusic MPU-401 Out ";
2425const WCHAR wszDescIn[] = L"DMusic MPU-401 In ";
2426
2428NTAPI
2430(
2432)
2433{
2434 NTSTATUS ntStatus;
2435
2436 PAGED_CODE();
2437
2439 {
2440 ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONG), TRUE);
2441 if (NT_SUCCESS(ntStatus))
2442 {
2443 // if return buffer can hold a ULONG, return the access flags
2444 PULONG AccessFlags = PULONG(pRequest->Value);
2445
2446 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT;
2447 switch (pRequest->PropertyItem->Id)
2448 {
2451 *AccessFlags |= KSPROPERTY_TYPE_GET;
2452 }
2453 switch (pRequest->PropertyItem->Id)
2454 {
2456 *AccessFlags |= KSPROPERTY_TYPE_SET;
2457 }
2458 ntStatus = STATUS_SUCCESS;
2459 pRequest->ValueSize = sizeof(ULONG);
2460
2461 switch (pRequest->PropertyItem->Id)
2462 {
2464 if (pRequest->MinorTarget)
2465 {
2466 *AccessFlags |= KSPROPERTY_TYPE_GET;
2467 }
2468 else
2469 {
2470 pRequest->ValueSize = 0;
2472 }
2473 }
2474 }
2475 }
2476 else
2477 {
2478 ntStatus = STATUS_SUCCESS;
2479 switch(pRequest->PropertyItem->Id)
2480 {
2482 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_CAPS");
2483
2484 if (pRequest->Verb & KSPROPERTY_TYPE_SET)
2485 {
2487 }
2488
2489 if (NT_SUCCESS(ntStatus))
2490 {
2491 ntStatus = ValidatePropertyRequest(pRequest, sizeof(SYNTHCAPS), TRUE);
2492
2493 if (NT_SUCCESS(ntStatus))
2494 {
2495 SYNTHCAPS *caps = (SYNTHCAPS*)pRequest->Value;
2496 int increment;
2497 RtlZeroMemory(caps, sizeof(SYNTHCAPS));
2498 // XXX Different guids for different instances!
2499 //
2500 if (pRequest->Node == eSynthNode)
2501 {
2502 increment = sizeof(wszDescOut) - 2;
2503 RtlCopyMemory( caps->Description,wszDescOut,increment);
2504 caps->Guid = CLSID_MiniportDriverDMusUART;
2505 }
2506 else
2507 {
2508 increment = sizeof(wszDescIn) - 2;
2509 RtlCopyMemory( caps->Description,wszDescIn,increment);
2510 caps->Guid = CLSID_MiniportDriverDMusUARTCapture;
2511 }
2512
2513 caps->Flags = SYNTH_PC_EXTERNAL;
2514 caps->MemorySize = 0;
2515 caps->MaxChannelGroups = 1;
2516 caps->MaxVoices = 0xFFFFFFFF;
2517 caps->MaxAudioChannels = 0xFFFFFFFF;
2518
2519 caps->EffectFlags = 0;
2520
2521 CMiniportDMusUART *aMiniport;
2522 ASSERT(pRequest->MajorTarget);
2523 aMiniport = (CMiniportDMusUART *)(PMINIPORTDMUS)(pRequest->MajorTarget);
2524 WCHAR wszDesc2[16];
2525 int cLen;
2526 cLen = swprintf(wszDesc2,L"[%03x]\0",PtrToUlong(aMiniport->m_pPortBase));
2527
2528 cLen *= sizeof(WCHAR);
2529 RtlCopyMemory((WCHAR *)((DWORD_PTR)(caps->Description) + increment),
2530 wszDesc2,
2531 cLen);
2532
2533
2534 pRequest->ValueSize = sizeof(SYNTHCAPS);
2535 }
2536 }
2537
2538 break;
2539
2541 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_PORTPARAMETERS");
2542 {
2543 CMiniportDMusUARTStream *aStream;
2544
2545 aStream = (CMiniportDMusUARTStream*)(pRequest->MinorTarget);
2546 if (aStream)
2547 {
2548 ntStatus = aStream->HandlePortParams(pRequest);
2549 }
2550 else
2551 {
2553 }
2554 }
2555 break;
2556
2558 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_CHANNELGROUPS");
2559
2560 ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONG), TRUE);
2561 if (NT_SUCCESS(ntStatus))
2562 {
2563 *(PULONG)(pRequest->Value) = 1;
2564 pRequest->ValueSize = sizeof(ULONG);
2565 }
2566 break;
2567
2569 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_LATENCYCLOCK");
2570
2571 if(pRequest->Verb & KSPROPERTY_TYPE_SET)
2572 {
2574 }
2575 else
2576 {
2577 ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONGLONG), TRUE);
2578 if(NT_SUCCESS(ntStatus))
2579 {
2580 REFERENCE_TIME rtLatency;
2581 CMiniportDMusUARTStream *aStream;
2582
2583 aStream = (CMiniportDMusUARTStream*)(pRequest->MinorTarget);
2584 if(aStream == NULL)
2585 {
2587 }
2588 else
2589 {
2590 aStream->m_pMiniport->m_MasterClock->GetTime(&rtLatency);
2591 *((PULONGLONG)pRequest->Value) = rtLatency;
2592 pRequest->ValueSize = sizeof(ULONGLONG);
2593 }
2594 }
2595 }
2596 break;
2597
2598 default:
2599 DPRINT("Unhandled property in PropertyHandler_Synth");
2600 break;
2601 }
2602 }
2603 return ntStatus;
2604}
2605
2606/*****************************************************************************
2607 * ValidatePropertyRequest()
2608 *****************************************************************************
2609 * Validates pRequest.
2610 * Checks if the ValueSize is valid
2611 * Checks if the Value is valid
2612 *
2613 * This does not update pRequest->ValueSize if it returns NT_SUCCESS.
2614 * Caller must set pRequest->ValueSize in case of NT_SUCCESS.
2615 */
2617(
2619 IN ULONG ulValueSize,
2620 IN BOOLEAN fValueRequired
2621)
2622{
2623 NTSTATUS ntStatus;
2624
2625 if (pRequest->ValueSize >= ulValueSize)
2626 {
2627 if (fValueRequired && NULL == pRequest->Value)
2628 {
2629 ntStatus = STATUS_INVALID_PARAMETER;
2630 }
2631 else
2632 {
2633 ntStatus = STATUS_SUCCESS;
2634 }
2635 }
2636 else if (0 == pRequest->ValueSize)
2637 {
2638 ntStatus = STATUS_BUFFER_OVERFLOW;
2639 }
2640 else
2641 {
2642 ntStatus = STATUS_BUFFER_TOO_SMALL;
2643 }
2644
2645 if (STATUS_BUFFER_OVERFLOW == ntStatus)
2646 {
2647 pRequest->ValueSize = ulValueSize;
2648 }
2649 else
2650 {
2651 pRequest->ValueSize = 0;
2652 }
2653
2654 return ntStatus;
2655} // ValidatePropertyRequest
2656
2657#ifdef _MSC_VER
2658#pragma code_seg()
2659#endif
2660
2661
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define STDMETHODIMP
Definition: basetyps.h:43
#define STDMETHODIMP_(t)
Definition: basetyps.h:44
const GUID IID_IUnknown
#define SIZEOF_ARRAY(ar)
Definition: cdrom.h:1482
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID BufferAddress
Definition: cdrom.h:990
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
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
friend PVOID pStream
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
POWER_STATE m_PowerState
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)
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)
virtual ~CMiniportDMusUART()
STDMETHODIMP_(void) Service(void)
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
friend class CMiniportDMusUARTStream
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
IUnknown * PUNKNOWN
Definition: com_apitest.h:45
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static ULONGLONG startTime
Definition: main.c:113
#define swprintf
Definition: precomp.h:40
#define IID_IMXF
Definition: dmusicks.h:250
IPortDMus * PPORTDMUS
Definition: dmusicks.h:168
#define KSAUDFNAME_DMUSIC_MPU_OUT
Definition: dmusicks.h:240
struct IAllocatorMXF * PAllocatorMXF
Definition: dmusicks.h:107
LONGLONG REFERENCE_TIME
Definition: dmusicks.h:9
struct IMXF * PMXF
Definition: dmusicks.h:68
IMiniportDMus * PMINIPORTDMUS
Definition: dmusicks.h:211
IMasterClock * PMASTERCLOCK
Definition: dmusicks.h:53
DMUS_STREAM_TYPE
Definition: dmusicks.h:28
@ DMUS_STREAM_MIDI_RENDER
Definition: dmusicks.h:30
@ DMUS_STREAM_MIDI_CAPTURE
Definition: dmusicks.h:31
#define DMUS_KEF_EVENT_INCOMPLETE
Definition: dmusicks.h:253
#define KSAUDFNAME_DMUSIC_MPU_IN
Definition: dmusicks.h:245
#define PACKAGE_EVT(evt)
Definition: dmusicks.h:258
@ KSPROPERTY_SYNTH_PORTPARAMETERS
Definition: dmusprop.h:57
@ KSPROPERTY_SYNTH_CHANNELGROUPS
Definition: dmusprop.h:58
@ KSPROPERTY_SYNTH_CAPS
Definition: dmusprop.h:56
@ KSPROPERTY_SYNTH_LATENCYCLOCK
Definition: dmusprop.h:60
#define SYNTH_PORTPARAMS_CHANNELGROUPS
Definition: dmusprop.h:105
#define SYNTH_PC_EXTERNAL
Definition: dmusprop.h:65
struct _SYNTH_PORTPARAMS * PSYNTH_PORTPARAMS
#define KSDATAFORMAT_SUBTYPE_DIRECTMUSIC
Definition: dmusprop.h:9
#define KSPROPSETID_Synth
Definition: dmusprop.h:50
struct _SYNTHCAPS SYNTHCAPS
struct _SYNTH_PORTPARAMS SYNTH_PORTPARAMS
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
#define PtrToUlong(u)
Definition: config.h:107
struct _MINIPORT * PMINIPORT
ULONGLONG NTAPI PcGetTimeInterval(IN ULONGLONG Since)
Definition: api.cpp:34
#define KSPROPERTY_TYPE_SET
Definition: dmksctrl.h:43
#define STATICGUIDOF(guid)
Definition: dmksctrl.h:25
#define KSPROPERTY_TYPE_BASICSUPPORT
Definition: dmksctrl.h:45
#define KSPROPERTY_TYPE_GET
Definition: dmksctrl.h:42
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
unsigned int BOOL
Definition: ntddk_ex.h:94
FxRequest * pRequest
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum GLsizei GLuint GLint * bytesWritten
Definition: glext.h:11123
@ Unknown
Definition: i8042prt.h:114
ULONG AddRef()
nsrefcnt AddRef()
nsrefcnt Release()
NTSTATUS NTAPI PcNewInterruptSync(OUT PINTERRUPTSYNC *OutInterruptSync, IN PUNKNOWN OuterUnknown OPTIONAL, IN PRESOURCELIST ResourceList, IN ULONG ResourceIndex, IN INTERRUPTSYNCMODE Mode)
Definition: interrupt.cpp:295
#define KSDATAFORMAT_SPECIFIER_NONE
Definition: ks.h:1157
#define GUID_NULL
Definition: ks.h:106
union KSDATAFORMAT KSDATARANGE
KSSTATE
Definition: ks.h:1214
@ KSSTATE_RUN
Definition: ks.h:1218
@ KSSTATE_STOP
Definition: ks.h:1215
@ KSPIN_DATAFLOW_IN
Definition: ks.h:1249
@ KSPIN_DATAFLOW_OUT
Definition: ks.h:1250
@ KSPIN_COMMUNICATION_NONE
Definition: ks.h:1254
@ KSPIN_COMMUNICATION_SINK
Definition: ks.h:1255
#define KSCATEGORY_CAPTURE
Definition: ks.h:160
#define KSCATEGORY_RENDER
Definition: ks.h:165
union KSDATAFORMAT * PKSDATARANGE
#define KSAUDFNAME_MIDI
Definition: ksmedia.h:1301
#define KSDATAFORMAT_SUBTYPE_MIDI_BUS
Definition: ksmedia.h:1296
#define KSDATAFORMAT_TYPE_MUSIC
Definition: ksmedia.h:1005
#define KSNODEPIN_STANDARD_OUT
Definition: ksmedia.h:1270
#define KSNODETYPE_SYNTHESIZER
Definition: ksmedia.h:1306
#define KSMUSIC_TECHNOLOGY_PORT
Definition: ksmedia.h:1291
#define KSCATEGORY_AUDIO
Definition: ksmedia.h:172
#define KSDATAFORMAT_SUBTYPE_MIDI
Definition: ksmedia.h:1016
#define KSNODEPIN_STANDARD_IN
Definition: ksmedia.h:1269
if(dx< 0)
Definition: linetemp.h:194
struct SYNCWRITECONTEXT * PSYNCWRITECONTEXT
NTSTATUS WriteMPU(IN PUCHAR PortBase, IN BOOLEAN IsCommand, IN UCHAR Value)
#define MPU401_REG_DATA
static PCPROPERTY_ITEM SynthProperties[]
NTSTATUS NTAPI InitMPU(IN PINTERRUPTSYNC InterruptSync, IN PVOID DynamicContext)
static KSDATARANGE PinDataRangesBridge[]
static KSDATARANGE_MUSIC PinDataRangesStreamDMusic
#define kOneMillisec
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)
#define kMPUPollTimeout
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[]
@ eFilterInputPinDM
@ eFilterInputPinLeg
@ eBridgeOutputPin
@ eBridgeInputPin
@ eFilterOutputPin
BOOLEAN TryMPU(IN PUCHAR PortBase)
SnapTimeStamp(PINTERRUPTSYNC InterruptSync, PVOID pStream)
#define kMaxNumLegacyRenderStreams
NTSTATUS ResetHardware(PUCHAR portBase)
const WCHAR wszDescIn[]
const ULONG kMPUInputBufferSize
#define MPU401_CMD_UART
NTSTATUS ValidatePropertyRequest(IN PPCPROPERTY_REQUEST pRequest, IN ULONG ulValueSize, IN BOOLEAN fValueRequired)
@ eSynthNode
@ eInputNode
#define MPU401_CMD_RESET
#define UartFifoOkForWrite(status)
#define MPU401_REG_STATUS
#define UartFifoOkForRead(status)
const WCHAR wszDescOut[]
static PCNODE_DESCRIPTOR MiniportNodes[]
static PCCONNECTION_DESCRIPTOR MiniportConnections[]
static PCFILTER_DESCRIPTOR MiniportFilterDescriptor
#define ASSERT(a)
Definition: mode.c:44
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
static HRESULT QueryInterface(REFIID, void **)
Definition: events.c:2587
static IStream Stream
Definition: htmldoc.c:1115
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:391
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ PowerDeviceD1
Definition: ntpoapi.h:50
@ PowerDeviceUnspecified
Definition: ntpoapi.h:48
@ PowerDeviceD0
Definition: ntpoapi.h:49
@ PowerDeviceD2
Definition: ntpoapi.h:51
@ PowerDeviceD3
Definition: ntpoapi.h:52
@ Service
Definition: ntsecapi.h:292
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:619
#define L(x)
Definition: ntvdm.h:50
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
BYTE * PBYTE
Definition: pedump.c:66
unsigned short USHORT
Definition: pedump.c:61
static PHARDWARE_TIMER MasterClock
Definition: pit.c:28
IInterruptSync * PINTERRUPTSYNC
Definition: portcls.h:888
IResourceList * PRESOURCELIST
Definition: portcls.h:442
IMusicTechnology * PMUSICTECHNOLOGY
Definition: portcls.h:1028
#define PCFILTER_NODE
Definition: portcls.h:154
#define GTI_MILLISECONDS(t)
Definition: portcls.h:2502
#define DEFINE_PCAUTOMATION_TABLE_PROP(AutomationTable, PropertyTable)
Definition: portcls.h:368
NTSTATUS(NTAPI * PINTERRUPTSYNCROUTINE)(IN struct IInterruptSync *InterruptSync, IN PVOID DynamicContext)
Definition: portcls.h:847
IServiceGroup * PSERVICEGROUP
Definition: portcls.h:614
@ InterruptSyncModeNormal
Definition: portcls.h:840
IPowerNotify * PPOWERNOTIFY
Definition: portcls.h:2059
#define TAG_PORTCLASS
Definition: private.hpp:24
#define REFIID
Definition: guiddef.h:118
#define REFCLSID
Definition: guiddef.h:117
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
NTSTATUS NTAPI PcNewServiceGroup(OUT PSERVICEGROUP *OutServiceGroup, IN PUNKNOWN OuterUnknown OPTIONAL)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
CMiniportDMusUART * Miniport
Definition: main.c:15
struct _DMUS_KERNEL_EVENT * pPackageEvt
Definition: dmusicks.h:24
struct _DMUS_KERNEL_EVENT * pNextEvt
Definition: dmusicks.h:20
BYTE abData[sizeof(PBYTE)]
Definition: dmusicks.h:22
union _DMUS_KERNEL_EVENT::@1936 uData
USHORT usChannelGroup
Definition: dmusicks.h:16
REFERENCE_TIME ullPresTime100ns
Definition: dmusicks.h:18
Definition: ketypes.h:699
WCHAR Description[128]
Definition: dmusprop.h:89
DWORD Flags
Definition: dmusprop.h:83
DWORD MemorySize
Definition: dmusprop.h:84
DWORD MaxChannelGroups
Definition: dmusprop.h:85
DWORD MaxAudioChannels
Definition: dmusprop.h:87
GUID Guid
Definition: dmusprop.h:82
DWORD EffectFlags
Definition: dmusprop.h:88
DWORD MaxVoices
Definition: dmusprop.h:86
Definition: http.c:7252
Definition: ps.c:97
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t DWORD_PTR
Definition: typedefs.h:65
INT POOL_TYPE
Definition: typedefs.h:78
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
DEVICE_POWER_STATE DeviceState
Definition: ntpoapi.h:58
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
Definition: wdfdevice.h:3034
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID _Out_ PINTERFACE Interface
Definition: wdffdo.h:465
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_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
Definition: wdfiotarget.h:960
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
_Must_inspect_result_ _In_ WDFIORESREQLIST _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFIORESLIST * ResourceList
Definition: wdfresource.h:309
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:235
#define success(from, fromstr, to, tostr)
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193