ReactOS 0.4.15-dev-5667-ged97270
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#ifndef YDEBUG
13#define NDEBUG
14#endif
15
16#include <debug.h>
17
18// + for absolute / - for relative
19
20#define kOneMillisec (10 * 1000)
21
22//
23// MPU401 ports
24//
25#define MPU401_REG_STATUS 0x01 // Status register
26#define MPU401_DRR 0x40 // Output ready (for command or data)
27 // if this bit is set, the output FIFO is FULL
28#define MPU401_DSR 0x80 // Input ready (for data)
29 // if this bit is set, the input FIFO is empty
30
31#define MPU401_REG_DATA 0x00 // Data in
32#define MPU401_REG_COMMAND 0x01 // Commands
33#define MPU401_CMD_RESET 0xFF // Reset command
34#define MPU401_CMD_UART 0x3F // Switch to UART mod
35
36
37/*****************************************************************************
38 * Prototypes
39 */
40
41NTSTATUS NTAPI InitMPU(IN PINTERRUPTSYNC InterruptSync,IN PVOID DynamicContext);
48/*****************************************************************************
49 * Constants
50 */
51
55
56
57/*****************************************************************************
58 * Classes
59 */
60
61/*****************************************************************************
62 * CMiniportDMusUART
63 *****************************************************************************
64 * MPU-401 miniport. This object is associated with the device and is
65 * created when the device is started. The class inherits IMiniportDMus
66 * so it can expose this interface and CUnknown so it automatically gets
67 * reference counting and aggregation support.
68 */
69class CMiniportDMusUART : public CUnknownImpl<IMiniportDMus, IMusicTechnology, IPowerNotify>
70{
71private:
72 KSSTATE m_KSStateInput; // Miniport state (RUN/PAUSE/ACQUIRE/STOP)
73 PPORTDMUS m_pPort; // Callback interface.
74 PUCHAR m_pPortBase; // Base port address.
75 PINTERRUPTSYNC m_pInterruptSync; // Interrupt synchronization object.
76 PSERVICEGROUP m_pServiceGroup; // Service group for capture.
77 PMASTERCLOCK m_MasterClock; // for input data
78 REFERENCE_TIME m_InputTimeStamp; // capture data timestamp
79 USHORT m_NumRenderStreams; // Num active render streams.
80 USHORT m_NumCaptureStreams; // Num active capture streams.
81 ULONG m_MPUInputBufferHead; // Index of the newest byte in the FIFO.
82 ULONG m_MPUInputBufferTail; // Index of the oldest empty space in the FIFO.
84 POWER_STATE m_PowerState; // Saved power state (D0 = full power, D3 = off)
85 BOOLEAN m_fMPUInitialized; // Is the MPU HW initialized.
86 BOOLEAN m_UseIRQ; // FALSE if no IRQ is used for MIDI.
88
89 /*************************************************************************
90 * CMiniportDMusUART methods
91 *
92 * These are private member functions used internally by the object.
93 * See MINIPORT.CPP for specific descriptions.
94 */
96 (
98 );
99 NTSTATUS InitializeHardware(PINTERRUPTSYNC interruptSync,PUCHAR portBase);
100
101public:
103
105 virtual ~CMiniportDMusUART();
106
107 /*************************************************************************
108 * IMiniport methods
109 */
112 ( OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
113 );
116 ( IN ULONG PinId
117 , IN PKSDATARANGE DataRange
118 , IN PKSDATARANGE MatchingDataRange
120 , OUT PVOID ResultantFormat
121 , OUT PULONG ResultantFormatLength
122 )
123 {
125 }
126
127 /*************************************************************************
128 * IMiniportDMus methods
129 */
131 (
132 IN PUNKNOWN UnknownAdapter,
136 );
138 (
139 OUT PMXF * Stream,
140 IN PUNKNOWN OuterUnknown OPTIONAL,
149 );
151 ( void
152 );
153
154 /*************************************************************************
155 * IMusicTechnology methods
156 */
158
159 /*************************************************************************
160 * IPowerNotify methods
161 */
163
164 /*************************************************************************
165 * Friends
166 */
168 friend NTSTATUS NTAPI
170 friend NTSTATUS NTAPI
171 SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync,PVOID syncWriteContext);
172 friend VOID NTAPI
176};
177
178/*****************************************************************************
179 * CMiniportDMusUARTStream
180 *****************************************************************************
181 * MPU-401 miniport stream. This object is associated with the pin and is
182 * created when the pin is instantiated. It inherits IMXF
183 * so it can expose this interface and CUnknown so it automatically gets
184 * reference counting and aggregation support.
185 */
187{
188private:
190 REFERENCE_TIME m_SnapshotTimeStamp; // Current snapshot of miniport's input timestamp.
191 PUCHAR m_pPortBase; // Base port address.
192 BOOLEAN m_fCapture; // Whether this is capture.
193 long m_NumFailedMPUTries; // Deadman timeout for MPU hardware.
194 PAllocatorMXF m_AllocatorMXF; // source/sink for DMus structs
195 PMXF m_sinkMXF; // sink for DMus capture
196 PDMUS_KERNEL_EVENT m_DMKEvtQueue; // queue of waiting events
197 ULONG m_NumberOfRetries; // Number of consecutive times the h/w was busy/full
198 ULONG m_DMKEvtOffset; // offset into the event
199 KDPC m_Dpc; // DPC for timer
201 BOOL m_TimerQueued; // whether a timer has been set
202 KSPIN_LOCK m_DpcSpinLock; // protects the ConsumeEvents DPC
203
204 STDMETHODIMP_(NTSTATUS) SourceEvtsToPort();
205 STDMETHODIMP_(NTSTATUS) ConsumeEvents();
206 STDMETHODIMP_(NTSTATUS) PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt);
207
208public:
210
211 virtual ~CMiniportDMusUARTStream();
212
214 (
215 IN CMiniportDMusUART * pMiniport,
220 );
221
223 (
225 );
226
227 /*************************************************************************
228 * IMiniportStreamDMusUART methods
229 */
231
233 (
237 );
238
239 friend VOID NTAPI
241 (
242 IN PKDPC Dpc,
246 );
249};
250
251
252
253#define STR_MODULENAME "DMusUART:Miniport: "
254
255#ifdef _MSC_VER
256#pragma code_seg("PAGE")
257#endif
258
259#define UartFifoOkForWrite(status) ((status & MPU401_DRR) == 0)
260#define UartFifoOkForRead(status) ((status & MPU401_DSR) == 0)
261
262typedef struct
263{
269}
271
272/*****************************************************************************
273 * PinDataRangesStreamLegacy
274 * PinDataRangesStreamDMusic
275 *****************************************************************************
276 * Structures indicating range of valid format values for live pins.
277 */
278static
280{
281 {
282 {
283 sizeof(KSDATARANGE_MUSIC),
284 0,
285 0,
286 0,
290 }
291 },
293 0,
294 0,
295 0xFFFF
296};
297static
299{
300 {
301 {
302 sizeof(KSDATARANGE_MUSIC),
303 0,
304 0,
305 0,
309 }
310 },
312 0,
313 0,
314 0xFFFF
315};
316
317/*****************************************************************************
318 * PinDataRangePointersStreamLegacy
319 * PinDataRangePointersStreamDMusic
320 * PinDataRangePointersStreamCombined
321 *****************************************************************************
322 * List of pointers to structures indicating range of valid format values
323 * for live pins.
324 */
325static
327{
329};
330static
332{
334};
335static
337{
340};
341
342/*****************************************************************************
343 * PinDataRangesBridge
344 *****************************************************************************
345 * Structures indicating range of valid format values for bridge pins.
346 */
347static
349{
350 {
351 {
352 sizeof(KSDATARANGE),
353 0,
354 0,
355 0,
359 }
360 }
361};
362
363/*****************************************************************************
364 * PinDataRangePointersBridge
365 *****************************************************************************
366 * List of pointers to structures indicating range of valid format values
367 * for bridge pins.
368 */
369static
371{
373};
374
375/*****************************************************************************
376 * SynthProperties
377 *****************************************************************************
378 * List of properties in the Synth set.
379 */
380static
383{
384 // Global: S/Get synthesizer caps
385 {
390 },
391 // Global: S/Get port parameters
392 {
397 },
398 // Per stream: S/Get channel groups
399 {
404 },
405 // Per stream: Get current latency time
406 {
411 }
412};
415
416#define kMaxNumCaptureStreams 1
417#define kMaxNumLegacyRenderStreams 1
418#define kMaxNumDMusicRenderStreams 1
419
420/*****************************************************************************
421 * MiniportPins
422 *****************************************************************************
423 * List of pins.
424 */
425static
427{
428 {
430 NULL, // AutomationTable
431 { // KsPinDescriptor
432 0, // InterfacesCount
433 NULL, // Interfaces
434 0, // MediumsCount
435 NULL, // Mediums
438 KSPIN_DATAFLOW_IN, // DataFlow
439 KSPIN_COMMUNICATION_SINK, // Communication
440 (GUID *) &KSCATEGORY_AUDIO, // Category
441 &KSAUDFNAME_MIDI, // Name
442 {0} // Reserved
443 }
444 },
445 {
447 NULL, // AutomationTable
448 { // KsPinDescriptor
449 0, // InterfacesCount
450 NULL, // Interfaces
451 0, // MediumsCount
452 NULL, // Mediums
455 KSPIN_DATAFLOW_IN, // DataFlow
456 KSPIN_COMMUNICATION_SINK, // Communication
457 (GUID *) &KSCATEGORY_AUDIO, // Category
459 {0} // Reserved
460 }
461 },
462 {
463 0,0,0, // InstanceCount
464 NULL, // AutomationTable
465 { // KsPinDescriptor
466 0, // InterfacesCount
467 NULL, // Interfaces
468 0, // MediumsCount
469 NULL, // Mediums
470 SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount
471 PinDataRangePointersBridge, // DataRanges
472 KSPIN_DATAFLOW_OUT, // DataFlow
473 KSPIN_COMMUNICATION_NONE, // Communication
474 (GUID *) &KSCATEGORY_AUDIO, // Category
475 NULL, // Name
476 {0} // Reserved
477 }
478 },
479 {
480 0,0,0, // InstanceCount
481 NULL, // AutomationTable
482 { // KsPinDescriptor
483 0, // InterfacesCount
484 NULL, // Interfaces
485 0, // MediumsCount
486 NULL, // Mediums
487 SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount
488 PinDataRangePointersBridge, // DataRanges
489 KSPIN_DATAFLOW_IN, // DataFlow
490 KSPIN_COMMUNICATION_NONE, // Communication
491 (GUID *) &KSCATEGORY_AUDIO, // Category
492 NULL, // Name
493 {0} // Reserved
494 }
495 },
496 {
498 NULL, // AutomationTable
499 { // KsPinDescriptor
500 0, // InterfacesCount
501 NULL, // Interfaces
502 0, // MediumsCount
503 NULL, // Mediums
506 KSPIN_DATAFLOW_OUT, // DataFlow
507 KSPIN_COMMUNICATION_SINK, // Communication
508 (GUID *) &KSCATEGORY_AUDIO, // Category
510 {0} // Reserved
511 }
512 }
513};
514
515/*****************************************************************************
516 * MiniportNodes
517 *****************************************************************************
518 * List of nodes.
519 */
520#define CONST_PCNODE_DESCRIPTOR(n) { 0, NULL, &n, NULL }
521#define CONST_PCNODE_DESCRIPTOR_AUTO(n,a) { 0, &a, &n, NULL }
522static
524{
527};
528
529/*****************************************************************************
530 * MiniportConnections
531 *****************************************************************************
532 * List of connections.
533 */
534enum {
535 eSynthNode = 0
538
539enum {
546
547static
549{ // From To
550 // Node pin Node pin
551 { PCFILTER_NODE, eFilterInputPinLeg, PCFILTER_NODE, eBridgeOutputPin } // Legacy Stream in to synth.
552 , { PCFILTER_NODE, eFilterInputPinDM, eSynthNode, KSNODEPIN_STANDARD_IN } // DM Stream in to synth.
553 , { eSynthNode, KSNODEPIN_STANDARD_OUT, PCFILTER_NODE, eBridgeOutputPin } // Synth to bridge out.
554 , { PCFILTER_NODE, eBridgeInputPin, eInputNode, KSNODEPIN_STANDARD_IN } // Bridge in to input.
555 , { eInputNode, KSNODEPIN_STANDARD_OUT, PCFILTER_NODE, eFilterOutputPin } // Input to DM/Legacy Stream out.
556};
557
558/*****************************************************************************
559 * MiniportCategories
560 *****************************************************************************
561 * List of categories.
562 */
563static
565{
569};
570
571/*****************************************************************************
572 * MiniportFilterDescriptor
573 *****************************************************************************
574 * Complete miniport filter description.
575 */
576static
578{
579 0, // Version
580 NULL, // AutomationTable
581 sizeof(PCPIN_DESCRIPTOR), // PinSize
582 SIZEOF_ARRAY(MiniportPins), // PinCount
583 MiniportPins, // Pins
584 sizeof(PCNODE_DESCRIPTOR), // NodeSize
585 SIZEOF_ARRAY(MiniportNodes), // NodeCount
586 MiniportNodes, // Nodes
587 SIZEOF_ARRAY(MiniportConnections), // ConnectionCount
588 MiniportConnections, // Connections
589 SIZEOF_ARRAY(MiniportCategories), // CategoryCount
590 MiniportCategories // Categories
591};
592
593#ifdef _MSC_VER
594#pragma code_seg("PAGE")
595#endif
596
597BOOLEAN TryMPU(IN PUCHAR PortBase);
598NTSTATUS WriteMPU(IN PUCHAR PortBase,IN BOOLEAN IsCommand,IN UCHAR Value);
599
600#ifdef _MSC_VER
601#pragma code_seg("PAGE")
602#endif
603
604// make sure we're in UART mode
606{
607 PAGED_CODE();
608
609 return WriteMPU(portBase,COMMAND,MPU401_CMD_UART);
610}
611
612#ifdef _MSC_VER
613#pragma code_seg("PAGE")
614#endif
615
616//
617// We initialize the UART with interrupts suppressed so we don't
618// try to service the chip prematurely.
619//
621{
622 PAGED_CODE();
623
624 NTSTATUS ntStatus;
625 if (m_UseIRQ)
626 {
627 ntStatus = interruptSync->CallSynchronizedRoutine(InitMPU,PVOID(portBase));
628 }
629 else
630 {
631 ntStatus = InitMPU(NULL,PVOID(portBase));
632 }
633
634 if (NT_SUCCESS(ntStatus))
635 {
636 //
637 // Start the UART (this should trigger an interrupt).
638 //
639 ntStatus = ResetHardware(portBase);
640 }
641 else
642 {
643 DPRINT("*** InitMPU returned with ntStatus 0x%08x ***", ntStatus);
644 }
645
646 m_fMPUInitialized = NT_SUCCESS(ntStatus);
647
648 return ntStatus;
649}
650
651#ifdef _MSC_VER
652#pragma code_seg()
653#endif
654
655/*****************************************************************************
656 * InitMPU()
657 *****************************************************************************
658 * Synchronized routine to initialize the MPU401.
659 */
661NTAPI
663(
664 IN PINTERRUPTSYNC InterruptSync,
665 IN PVOID DynamicContext
666)
667{
668 DPRINT("InitMPU");
669 if (!DynamicContext)
670 {
672 }
673
674 PUCHAR portBase = PUCHAR(DynamicContext);
678 NTSTATUS ntStatus = STATUS_SUCCESS;
679
680 //
681 // Reset the card (puts it into "smart mode")
682 //
683 ntStatus = WriteMPU(portBase,COMMAND,MPU401_CMD_RESET);
684
685 // wait for the acknowledgement
686 // NOTE: When the Ack arrives, it will trigger an interrupt.
687 // Normally the DPC routine would read in the ack byte and we
688 // would never see it, however since we have the hardware locked (HwEnter),
689 // we can read the port before the DPC can and thus we receive the Ack.
691 success = FALSE;
693 {
695
696 if (UartFifoOkForRead(status)) // Is data waiting?
697 {
698 READ_PORT_UCHAR(portBase + MPU401_REG_DATA); // yep.. read ACK
699 success = TRUE; // don't need to do more
700 break;
701 }
702 KeStallExecutionProcessor(25); // microseconds
703 }
704#if (DBG)
705 if (!success)
706 {
707 DPRINT("First attempt to reset the MPU didn't get ACKed.\n");
708 }
709#endif // (DBG)
710
711 // NOTE: We cannot check the ACK byte because if the card was already in
712 // UART mode it will not send an ACK but it will reset.
713
714 // reset the card again
716
717 // wait for ack (again)
718 startTime = PcGetTimeInterval(0); // This might take a while
719 BYTE dataByte = 0;
720 success = FALSE;
722 {
724 if (UartFifoOkForRead(status)) // Is data waiting?
725 {
726 dataByte = READ_PORT_UCHAR(portBase + MPU401_REG_DATA); // yep.. read ACK
727 success = TRUE; // don't need to do more
728 break;
729 }
731 }
732
733 if ((0xFE != dataByte) || !success) // Did we succeed? If no second ACK, something is hosed
734 {
735 DPRINT("Second attempt to reset the MPU didn't get ACKed.\n");
736 DPRINT("Init Reset failure error. Ack = %X", ULONG(dataByte));
737
738 ntStatus = STATUS_IO_DEVICE_ERROR;
739 }
740
741 return ntStatus;
742}
743
744#ifdef _MSC_VER
745#pragma code_seg()
746#endif
747
748/*****************************************************************************
749 * CMiniportDMusUARTStream::Write()
750 *****************************************************************************
751 * Writes outgoing MIDI data.
752 */
754CMiniportDMusUARTStream::
755Write
756(
760)
761{
762 DPRINT("Write\n");
764 if (!BufferAddress)
765 {
766 Length = 0;
767 }
768
769 NTSTATUS ntStatus = STATUS_SUCCESS;
770
771 if (!m_fCapture)
772 {
773 PUCHAR pMidiData;
774 ULONG count;
775
776 count = 0;
777 pMidiData = PUCHAR(BufferAddress);
778
779 if (Length)
780 {
782 context.Miniport = (m_pMiniport);
783 context.PortBase = m_pPortBase;
784 context.BufferAddress = pMidiData;
785 context.Length = Length;
786 context.BytesRead = &count;
787
789 {
790 ntStatus = m_pMiniport->m_pInterruptSync->
791 CallSynchronizedRoutine(SynchronizedDMusMPUWrite,PVOID(&context));
792 }
793 else // !m_UseIRQ
794 {
796 } // !m_UseIRQ
797
798 if (count == 0)
799 {
801 if (m_NumFailedMPUTries >= 100)
802 {
803 ntStatus = STATUS_IO_DEVICE_ERROR;
805 }
806 }
807 else
808 {
810 }
811 } // if we have data at all
813 }
814 else // called write on the read stream
815 {
817 }
818 return ntStatus;
819}
820
821#ifdef _MSC_VER
822#pragma code_seg()
823#endif
824
825/*****************************************************************************
826 * SynchronizedDMusMPUWrite()
827 *****************************************************************************
828 * Writes outgoing MIDI data.
829 */
831NTAPI
833(
834 IN PINTERRUPTSYNC InterruptSync,
835 IN PVOID syncWriteContext
836)
837{
839 context = (PSYNCWRITECONTEXT)syncWriteContext;
840 ASSERT(context->Miniport);
841 ASSERT(context->PortBase);
842 ASSERT(context->BufferAddress);
843 ASSERT(context->Length);
844 ASSERT(context->BytesRead);
845
846 PUCHAR pChar = PUCHAR(context->BufferAddress);
847 NTSTATUS ntStatus; // , readStatus
848 ntStatus = STATUS_SUCCESS;
849 //
850 // while we're not there yet, and
851 // while we don't have to wait on an aligned byte (including 0)
852 // (we never wait on a byte. Better to come back later)
853 /*readStatus = */ DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport));
854 while ( (*(context->BytesRead) < context->Length)
855 && ( TryMPU(context->PortBase)
856 || (*(context->BytesRead)%3)
857 ) )
858 {
859 ntStatus = WriteMPU(context->PortBase,DATA,*pChar);
860 if (NT_SUCCESS(ntStatus))
861 {
862 pChar++;
863 *(context->BytesRead) = *(context->BytesRead) + 1;
864// readStatus = DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport));
865 }
866 else
867 {
868 DPRINT("SynchronizedDMusMPUWrite failed (0x%08x)",ntStatus);
869 break;
870 }
871 }
872 /*readStatus = */ DMusMPUInterruptServiceRoutine(InterruptSync,PVOID(context->Miniport));
873 return ntStatus;
874}
875
876#define kMPUPollTimeout 2
877
878#ifdef _MSC_VER
879#pragma code_seg()
880#endif
881
882/*****************************************************************************
883 * TryMPU()
884 *****************************************************************************
885 * See if the MPU401 is free.
886 */
889(
890 IN PUCHAR PortBase
891)
892{
894 USHORT numPolls;
896
897 DPRINT("TryMPU");
898 numPolls = 0;
899
900 while (numPolls < kMPUPollTimeout)
901 {
903
904 if (UartFifoOkForWrite(status)) // Is this a good time to write data?
905 {
906 break;
907 }
908 numPolls++;
909 }
910 if (numPolls >= kMPUPollTimeout)
911 {
912 success = FALSE;
913 DPRINT("TryMPU failed");
914 }
915 else
916 {
917 success = TRUE;
918 }
919
920 return success;
921}
922
923#ifdef _MSC_VER
924#pragma code_seg()
925#endif
926
927/*****************************************************************************
928 * WriteMPU()
929 *****************************************************************************
930 * Write a byte out to the MPU401.
931 */
934(
935 IN PUCHAR PortBase,
936 IN BOOLEAN IsCommand,
938)
939{
940 DPRINT("WriteMPU");
942
943 if (!PortBase)
944 {
945 DPRINT("O: PortBase is zero\n");
946 return ntStatus;
947 }
948 PUCHAR deviceAddr = PortBase + MPU401_REG_DATA;
949
950 if (IsCommand)
951 {
952 deviceAddr = PortBase + MPU401_REG_COMMAND;
953 }
954
956
958 {
961
962 if (UartFifoOkForWrite(status)) // Is this a good time to write data?
963 { // yep (Jon comment)
964 WRITE_PORT_UCHAR(deviceAddr,Value);
965 DPRINT("WriteMPU emitted 0x%02x",Value);
966 ntStatus = STATUS_SUCCESS;
967 break;
968 }
969 }
970 return ntStatus;
971}
972
973#ifdef _MSC_VER
974#pragma code_seg()
975#endif
976
977/*****************************************************************************
978 * SnapTimeStamp()
979 *****************************************************************************
980 *
981 * At synchronized execution to ISR, copy miniport's volatile m_InputTimeStamp
982 * to stream's m_SnapshotTimeStamp and zero m_InputTimeStamp.
983 *
984 */
986SnapTimeStamp(PINTERRUPTSYNC InterruptSync,PVOID pStream)
987{
988 CMiniportDMusUARTStream *pMPStream = (CMiniportDMusUARTStream *)pStream;
989
990 // cache the timestamp
991 pMPStream->m_SnapshotTimeStamp = pMPStream->m_pMiniport->m_InputTimeStamp;
992
993 // if the window is closed, zero the timestamp
994 if (pMPStream->m_pMiniport->m_MPUInputBufferHead ==
996 {
997 pMPStream->m_pMiniport->m_InputTimeStamp = 0;
998 }
999
1000 return STATUS_SUCCESS;
1001}
1002
1003/*****************************************************************************
1004 * CMiniportDMusUARTStream::SourceEvtsToPort()
1005 *****************************************************************************
1006 *
1007 * Reads incoming MIDI data, feeds into DMus events.
1008 * No need to touch the hardware, just read from our SW FIFO.
1009 *
1010 */
1012CMiniportDMusUARTStream::SourceEvtsToPort()
1013{
1014 NTSTATUS ntStatus;
1015
1017 DPRINT("SourceEvtsToPort");
1018
1019 if (m_fCapture)
1020 {
1021 ntStatus = STATUS_SUCCESS;
1023 {
1024 PDMUS_KERNEL_EVENT aDMKEvt,eventTail,eventHead = NULL;
1025
1027 {
1028 (void) m_AllocatorMXF->GetMessage(&aDMKEvt);
1029 if (!aDMKEvt)
1030 {
1031 DPRINT("SourceEvtsToPort can't allocate DMKEvt");
1033 }
1034
1035 // put this event at the end of the list
1036 if (!eventHead)
1037 {
1038 eventHead = aDMKEvt;
1039 }
1040 else
1041 {
1042 eventTail = eventHead;
1043 while (eventTail->pNextEvt)
1044 {
1045 eventTail = eventTail->pNextEvt;
1046 }
1047 eventTail->pNextEvt = aDMKEvt;
1048 }
1049 // read all the bytes out of the buffer, into event(s)
1050 for (aDMKEvt->cbEvent = 0; aDMKEvt->cbEvent < sizeof(PBYTE); aDMKEvt->cbEvent++)
1051 {
1053 {
1054// _DbgPrintF(DEBUGLVL_TERSE, ("SourceEvtsToPort m_MPUInputBufferHead met m_MPUInputBufferTail, overrun"));
1055 break;
1056 }
1060 {
1062 }
1063 }
1064 }
1065
1066 if (m_pMiniport->m_UseIRQ)
1067 {
1068 ntStatus = m_pMiniport->m_pInterruptSync->CallSynchronizedRoutine(SnapTimeStamp,PVOID(this));
1069 }
1070 else // !m_UseIRQ
1071 {
1072 ntStatus = SnapTimeStamp(NULL,PVOID(this));
1073 } // !m_UseIRQ
1074 aDMKEvt = eventHead;
1075 while (aDMKEvt)
1076 {
1078 aDMKEvt->usChannelGroup = 1;
1080 aDMKEvt = aDMKEvt->pNextEvt;
1081 }
1082 (void)m_sinkMXF->PutMessage(eventHead);
1083 }
1084 }
1085 else // render stream
1086 {
1087 DPRINT("SourceEvtsToPort called on render stream");
1089 }
1090 return ntStatus;
1091}
1092
1093#ifdef _MSC_VER
1094#pragma code_seg()
1095#endif
1096
1097/*****************************************************************************
1098 * DMusMPUInterruptServiceRoutine()
1099 *****************************************************************************
1100 * ISR.
1101 */
1103NTAPI
1105(
1106 IN PINTERRUPTSYNC InterruptSync,
1107 IN PVOID DynamicContext
1108)
1109{
1110 DPRINT("DMusMPUInterruptServiceRoutine");
1112
1113 ASSERT(DynamicContext);
1114
1115 NTSTATUS ntStatus;
1116 BOOL newBytesAvailable;
1117 CMiniportDMusUART *that;
1118 NTSTATUS clockStatus;
1119
1120 that = (CMiniportDMusUART *) DynamicContext;
1121 newBytesAvailable = FALSE;
1122 ntStatus = STATUS_UNSUCCESSFUL;
1123
1124 UCHAR portStatus = 0xff;
1125
1126 //
1127 // Read the MPU status byte.
1128 //
1129 if (that->m_pPortBase)
1130 {
1131 portStatus =
1133
1134 //
1135 // If there is outstanding work to do and there is a port-driver for
1136 // the MPU miniport...
1137 //
1138 if (UartFifoOkForRead(portStatus) && that->m_pPort)
1139 {
1142 && (UartFifoOkForRead(portStatus)) )
1143 {
1145 if ( (that->m_KSStateInput == KSSTATE_RUN)
1146 && (that->m_NumCaptureStreams)
1147 )
1148 {
1149 ULONG buffHead = that->m_MPUInputBufferHead;
1150 if ( (that->m_MPUInputBufferTail + 1 == buffHead)
1151 || (that->m_MPUInputBufferTail + 1 - kMPUInputBufferSize == buffHead))
1152 {
1153 DPRINT("*****MPU Input Buffer Overflow*****");
1154 }
1155 else
1156 {
1157 if (!that->m_InputTimeStamp)
1158 {
1159 clockStatus = that->m_MasterClock->GetTime(&that->m_InputTimeStamp);
1160 if (STATUS_SUCCESS != clockStatus)
1161 {
1162 DPRINT("GetTime failed for clock 0x%08x",that->m_MasterClock);
1163 }
1164 }
1165 newBytesAvailable = TRUE;
1166 // ...place the data in our FIFO...
1167 that->m_MPUInputBuffer[that->m_MPUInputBufferTail] = uDest;
1169
1170 that->m_MPUInputBufferTail++;
1172 {
1173 that->m_MPUInputBufferTail = 0;
1174 }
1175 }
1176 }
1177 //
1178 // Look for more MIDI data.
1179 //
1180 portStatus =
1182 } // either there's no data or we ran too long
1183 if (newBytesAvailable)
1184 {
1185 //
1186 // ...notify the MPU port driver that we have bytes.
1187 //
1188 that->m_pPort->Notify(that->m_pServiceGroup);
1189 }
1190 ntStatus = STATUS_SUCCESS;
1191 }
1192 }
1193
1194 return ntStatus;
1195}
1196
1197/*****************************************************************************
1198 * CMiniportDMusUART::GetDescription()
1199 *****************************************************************************
1200 * Gets the topology.
1201 */
1204GetDescription
1205(
1206 OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
1207)
1208{
1209 PAGED_CODE();
1210
1211 ASSERT(OutFilterDescriptor);
1212
1213 DPRINT("GetDescription");
1214
1215 *OutFilterDescriptor = &MiniportFilterDescriptor;
1216
1217 return STATUS_SUCCESS;
1218}
1219
1220#ifdef _MSC_VER
1221#pragma code_seg("PAGE")
1222#endif
1223
1226 OUT PMINIPORT* OutMiniport,
1227 IN REFCLSID ClassId)
1228{
1231
1233 if (!This)
1235
1236 Status = This->QueryInterface(IID_IMiniport, (PVOID*)OutMiniport);
1237
1238 if (!NT_SUCCESS(Status))
1239 {
1240 delete This;
1241 }
1242
1243 DPRINT("NewMiniportDMusUART %p Status %x\n", *OutMiniport, Status);
1244 return Status;
1245}
1246
1247
1248#ifdef _MSC_VER
1249#pragma code_seg("PAGE")
1250#endif
1251
1252/*****************************************************************************
1253 * CMiniportDMusUART::ProcessResources()
1254 *****************************************************************************
1255 * Processes the resource list, setting up helper objects accordingly.
1256 */
1260(
1262)
1263{
1264 PAGED_CODE();
1265
1266 DPRINT("ProcessResources");
1267
1269 if (!ResourceList)
1270 {
1272 }
1273 //
1274 // Get counts for the types of resources.
1275 //
1276 ULONG countIO = ResourceList->NumberOfPorts();
1277 ULONG countIRQ = ResourceList->NumberOfInterrupts();
1278 ULONG countDMA = ResourceList->NumberOfDmas();
1279 ULONG lengthIO = ResourceList->FindTranslatedPort(0)->u.Port.Length;
1280
1281#if DBG
1282 DPRINT("Starting MPU401 Port 0x%lx", ResourceList->FindTranslatedPort(0)->u.Port.Start.LowPart);
1283#endif
1284
1285 NTSTATUS ntStatus = STATUS_SUCCESS;
1286
1287 //
1288 // Make sure we have the expected number of resources.
1289 //
1290 if ( (countIO != 1)
1291 || (countIRQ > 1)
1292 || (countDMA != 0)
1293 || (lengthIO == 0)
1294 )
1295 {
1296 DPRINT("Unknown ResourceList configuration");
1298 }
1299
1300 if (NT_SUCCESS(ntStatus))
1301 {
1302 //
1303 // Get the port address.
1304 //
1305 m_pPortBase =
1306 PUCHAR(ResourceList->FindTranslatedPort(0)->u.Port.Start.QuadPart);
1307
1309 }
1310
1311 return ntStatus;
1312}
1313
1314#ifdef _MSC_VER
1315#pragma code_seg("PAGE")
1316#endif
1317/*****************************************************************************
1318 * CMiniportDMusUART::NonDelegatingQueryInterface()
1319 *****************************************************************************
1320 * Obtains an interface. This function works just like a COM QueryInterface
1321 * call and is used if the object is not being aggregated.
1322 */
1325(
1327 PVOID * Object
1328)
1329{
1330 PAGED_CODE();
1331
1332 DPRINT("Miniport::NonDelegatingQueryInterface");
1333 ASSERT(Object);
1334
1336 {
1338 }
1339 else
1340 if (IsEqualGUIDAligned(Interface,IID_IMiniport))
1341 {
1342 *Object = PVOID(PMINIPORT(this));
1343 }
1344 else
1345 if (IsEqualGUIDAligned(Interface,IID_IMiniportDMus))
1346 {
1347 *Object = PVOID(PMINIPORTDMUS(this));
1348 }
1349 else
1350 if (IsEqualGUIDAligned(Interface,IID_IMusicTechnology))
1351 {
1352 *Object = PVOID(PMUSICTECHNOLOGY(this));
1353 }
1354 else
1355 if (IsEqualGUIDAligned(Interface,IID_IPowerNotify))
1356 {
1357 *Object = PVOID(PPOWERNOTIFY(this));
1358 }
1359 else
1360 {
1361 *Object = NULL;
1362 }
1363
1364 if (*Object)
1365 {
1366 //
1367 // We reference the interface for the caller.
1368 //
1369 PUNKNOWN(*Object)->AddRef();
1370 return STATUS_SUCCESS;
1371 }
1372
1374}
1375
1376#ifdef _MSC_VER
1377#pragma code_seg("PAGE")
1378#endif
1379/*****************************************************************************
1380 * CMiniportDMusUART::~CMiniportDMusUART()
1381 *****************************************************************************
1382 * Destructor.
1383 */
1385{
1386 PAGED_CODE();
1387
1388 DPRINT("~CMiniportDMusUART");
1389
1392
1393 // reset the HW so we don't get anymore interrupts
1395 {
1397 }
1398 else
1399 {
1401 }
1402
1403 if (m_pInterruptSync)
1404 {
1405 m_pInterruptSync->Release();
1407 }
1408 if (m_pServiceGroup)
1409 {
1410 m_pServiceGroup->Release();
1412 }
1413 if (m_pPort)
1414 {
1415 m_pPort->Release();
1416 m_pPort = NULL;
1417 }
1418}
1419
1420#ifdef _MSC_VER
1421#pragma code_seg("PAGE")
1422#endif
1423/*****************************************************************************
1424 * CMiniportDMusUART::Init()
1425 *****************************************************************************
1426 * Initializes a the miniport.
1427 */
1429CMiniportDMusUART::
1430Init
1431(
1432 IN PUNKNOWN UnknownInterruptSync OPTIONAL,
1434 IN PPORTDMUS Port_,
1435 OUT PSERVICEGROUP * ServiceGroup
1436)
1437{
1438 PAGED_CODE();
1439
1441 if (!ResourceList)
1442 {
1444 }
1445
1446 ASSERT(Port_);
1448
1449 DPRINT("Init");
1450
1451 *ServiceGroup = NULL;
1452 m_pPortBase = 0;
1454
1455 // This will remain unspecified if the miniport does not get any power
1456 // messages.
1457 //
1459
1460 //
1461 // AddRef() is required because we are keeping this pointer.
1462 //
1463 m_pPort = Port_;
1464 m_pPort->AddRef();
1465
1466 // Set dataformat.
1467 //
1469 {
1472 sizeof(GUID));
1473 }
1476 sizeof(GUID));
1479 sizeof(GUID));
1480
1481 for (ULONG bufferCount = 0;bufferCount < kMPUInputBufferSize;bufferCount++)
1482 {
1483 m_MPUInputBuffer[bufferCount] = 0;
1484 }
1487 m_InputTimeStamp = 0;
1489
1490 NTSTATUS ntStatus = STATUS_SUCCESS;
1491
1494
1495 m_UseIRQ = TRUE;
1496 if (ResourceList->NumberOfInterrupts() == 0)
1497 {
1498 m_UseIRQ = FALSE;
1499 }
1500
1502 if (NT_SUCCESS(ntStatus) && !m_pServiceGroup) // keep any error
1503 {
1505 }
1506
1507 if (NT_SUCCESS(ntStatus))
1508 {
1510 m_pServiceGroup->AddRef();
1511
1512 //
1513 // Register the service group with the port early so the port is
1514 // prepared to handle interrupts.
1515 //
1516 m_pPort->RegisterServiceGroup(m_pServiceGroup);
1517 }
1518
1519 if (NT_SUCCESS(ntStatus) && m_UseIRQ)
1520 {
1521 //
1522 // Due to a bug in the InterruptSync design, we shouldn't share
1523 // the interrupt sync object. Whoever goes away first
1524 // will disconnect it, and the other points off into nowhere.
1525 //
1526 // Instead we generate our own interrupt sync object.
1527 //
1528 UnknownInterruptSync = NULL;
1529
1530 if (UnknownInterruptSync)
1531 {
1532 ntStatus =
1533 UnknownInterruptSync->QueryInterface
1534 (
1535 IID_IInterruptSync,
1537 );
1538
1539 if (!m_pInterruptSync && NT_SUCCESS(ntStatus)) // keep any error
1540 {
1542 }
1543 if (NT_SUCCESS(ntStatus))
1544 { // run this ISR first
1545 ntStatus = m_pInterruptSync->
1546 RegisterServiceRoutine(DMusMPUInterruptServiceRoutine,PVOID(this),TRUE);
1547 }
1548
1549 }
1550 else
1551 { // create our own interruptsync mechanism.
1552 ntStatus =
1554 (
1556 NULL,
1558 0, // Resource Index
1559 InterruptSyncModeNormal // Run ISRs once until we get SUCCESS
1560 );
1561
1562 if (!m_pInterruptSync && NT_SUCCESS(ntStatus)) // keep any error
1563 {
1565 }
1566
1567 if (NT_SUCCESS(ntStatus))
1568 {
1569 ntStatus = m_pInterruptSync->RegisterServiceRoutine(
1571 PVOID(this),
1572 TRUE); // run this ISR first
1573 }
1574 if (NT_SUCCESS(ntStatus))
1575 {
1576 ntStatus = m_pInterruptSync->Connect();
1577 }
1578 }
1579 }
1580
1581 if (NT_SUCCESS(ntStatus))
1582 {
1583 ntStatus = ProcessResources(ResourceList);
1584 }
1585
1586 if (!NT_SUCCESS(ntStatus))
1587 {
1588 //
1589 // clean up our mess
1590 //
1591
1592 // clean up the interrupt sync
1593 if( m_pInterruptSync )
1594 {
1595 m_pInterruptSync->Release();
1597 }
1598
1599 // clean up the service group
1600 if( m_pServiceGroup )
1601 {
1602 m_pServiceGroup->Release();
1604 }
1605
1606 // clean up the out param service group.
1607 if (*ServiceGroup)
1608 {
1609 (*ServiceGroup)->Release();
1610 (*ServiceGroup) = NULL;
1611 }
1612
1613 // release the port
1614 m_pPort->Release();
1615 m_pPort = NULL;
1616 }
1617
1618 return ntStatus;
1619}
1620
1621#ifdef _MSC_VER
1622#pragma code_seg("PAGE")
1623#endif
1624/*****************************************************************************
1625 * CMiniportDMusUART::NewStream()
1626 *****************************************************************************
1627 * Gets the topology.
1628 */
1630CMiniportDMusUART::
1631NewStream
1632(
1633 OUT PMXF * MXF,
1634 IN PUNKNOWN OuterUnknown OPTIONAL,
1636 IN ULONG PinID,
1637 IN DMUS_STREAM_TYPE StreamType,
1639 OUT PSERVICEGROUP * ServiceGroup,
1640 IN PAllocatorMXF AllocatorMXF,
1642 OUT PULONGLONG SchedulePreFetch
1643)
1644{
1645 PAGED_CODE();
1646
1647 DPRINT("NewStream");
1648 NTSTATUS ntStatus = STATUS_SUCCESS;
1649
1650 // In 100 ns, we want stuff as soon as it comes in
1651 //
1652 *SchedulePreFetch = 0;
1653
1654 // if we don't have any streams already open, get the hardware ready.
1656 {
1657 ntStatus = ResetHardware(m_pPortBase);
1658 if (!NT_SUCCESS(ntStatus))
1659 {
1660 DPRINT("CMiniportDMusUART::NewStream ResetHardware failed");
1661 return ntStatus;
1662 }
1663 }
1664
1669 )
1670 {
1672 new(PoolType, 'wNcP') CMiniportDMusUARTStream();
1673
1674 if (pStream)
1675 {
1676 pStream->AddRef();
1677
1678 ntStatus =
1680
1681 if (NT_SUCCESS(ntStatus))
1682 {
1683 *MXF = PMXF(pStream);
1684 (*MXF)->AddRef();
1685
1687 {
1690 (*ServiceGroup)->AddRef();
1691 }
1692 else
1693 {
1695 *ServiceGroup = NULL;
1696 }
1697 }
1698
1699 pStream->Release();
1700 }
1701 else
1702 {
1704 }
1705 }
1706 else
1707 {
1710 {
1711 DPRINT("NewStream failed, too many capture streams");
1712 }
1714 {
1715 DPRINT("NewStream failed, too many render streams");
1716 }
1717 else
1718 {
1719 DPRINT("NewStream invalid stream type");
1720 }
1721 }
1722
1723 return ntStatus;
1724}
1725
1726#ifdef _MSC_VER
1727#pragma code_seg("PAGE")
1728#endif
1729/*****************************************************************************
1730 * CMiniportDMusUART::SetTechnology()
1731 *****************************************************************************
1732 * Sets pindatarange technology.
1733 */
1735CMiniportDMusUART::
1736SetTechnology
1737(
1738 IN const GUID * Technology
1739)
1740{
1741 PAGED_CODE();
1742
1743 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1744
1745 // Fail if miniport has already been initialized.
1746 //
1747 if (NULL == m_pPort)
1748 {
1749 RtlCopyMemory(&m_MusicFormatTechnology, Technology, sizeof(GUID));
1750 ntStatus = STATUS_SUCCESS;
1751 }
1752
1753 return ntStatus;
1754} // SetTechnology
1755
1756/*****************************************************************************
1757 * CMiniportDMusUART::PowerChangeNotify()
1758 *****************************************************************************
1759 * Handle power state change for the miniport.
1760 */
1761#ifdef _MSC_VER
1762#pragma code_seg("PAGE")
1763#endif
1764
1765STDMETHODIMP_(void)
1766CMiniportDMusUART::
1767PowerChangeNotify
1768(
1770)
1771{
1772 PAGED_CODE();
1773
1774 DPRINT("CMiniportDMusUART::PoweChangeNotify D%d", PowerState.DeviceState);
1775
1776 switch (PowerState.DeviceState)
1777 {
1778 case PowerDeviceD0:
1780 {
1782 {
1783 DPRINT("InitializeHardware failed when resuming");
1784 }
1785 }
1786 break;
1787
1788 case PowerDeviceD1:
1789 case PowerDeviceD2:
1790 case PowerDeviceD3:
1791 default:
1792 break;
1793 }
1794 m_PowerState.DeviceState = PowerState.DeviceState;
1795} // PowerChangeNotify
1796
1797#ifdef _MSC_VER
1798#pragma code_seg("PAGE")
1799#endif
1800/*****************************************************************************
1801 * CMiniportDMusUARTStream::NonDelegatingQueryInterface()
1802 *****************************************************************************
1803 * Obtains an interface. This function works just like a COM QueryInterface
1804 * call and is used if the object is not being aggregated.
1805 */
1808(
1810 PVOID * Object
1811)
1812{
1813 PAGED_CODE();
1814
1815 DPRINT("Stream::NonDelegatingQueryInterface");
1816 ASSERT(Object);
1817
1819 {
1820 *Object = PVOID(PUNKNOWN(this));
1821 }
1822 else
1824 {
1825 *Object = PVOID(PMXF(this));
1826 }
1827 else
1828 {
1829 *Object = NULL;
1830 }
1831
1832 if (*Object)
1833 {
1834 //
1835 // We reference the interface for the caller.
1836 //
1837 PUNKNOWN(*Object)->AddRef();
1838 return STATUS_SUCCESS;
1839 }
1840
1842}
1843
1844#ifdef _MSC_VER
1845#pragma code_seg("PAGE")
1846#endif
1847/*****************************************************************************
1848 * CMiniportDMusUARTStream::~CMiniportDMusUARTStream()
1849 *****************************************************************************
1850 * Destructs a stream.
1851 */
1853{
1854 PAGED_CODE();
1855
1856 DPRINT("~CMiniportDMusUARTStream");
1857
1859
1860 if (m_DMKEvtQueue)
1861 {
1862 if (m_AllocatorMXF)
1863 {
1864 m_AllocatorMXF->PutMessage(m_DMKEvtQueue);
1865 }
1866 else
1867 {
1868 DPRINT("~CMiniportDMusUARTStream, no allocator, can't flush DMKEvts");
1869 }
1871 }
1872 if (m_AllocatorMXF)
1873 {
1874 m_AllocatorMXF->Release();
1876 }
1877
1878 if (m_pMiniport)
1879 {
1880 if (m_fCapture)
1881 {
1883 }
1884 else
1885 {
1887 }
1888
1889 m_pMiniport->Release();
1890 }
1891}
1892
1893#ifdef _MSC_VER
1894#pragma code_seg("PAGE")
1895#endif
1896/*****************************************************************************
1897 * CMiniportDMusUARTStream::Init()
1898 *****************************************************************************
1899 * Initializes a stream.
1900 */
1902CMiniportDMusUARTStream::
1903Init
1904(
1905 IN CMiniportDMusUART * pMiniport,
1906 IN PUCHAR pPortBase,
1907 IN BOOLEAN fCapture,
1908 IN PAllocatorMXF allocatorMXF,
1909 IN PMASTERCLOCK masterClock
1910)
1911{
1912 PAGED_CODE();
1913
1914 ASSERT(pMiniport);
1916
1917 DPRINT("Init");
1918
1922 m_pMiniport = pMiniport;
1923 m_pMiniport->AddRef();
1924
1925 pMiniport->m_MasterClock = masterClock;
1926
1929
1932 m_DMKEvtOffset = 0;
1933
1935
1936 if (allocatorMXF)
1937 {
1938 allocatorMXF->AddRef();
1941 }
1942 else
1943 {
1945 }
1946
1948 (
1949 &m_Dpc,
1951 PVOID(this)
1952 );
1954
1955 return STATUS_SUCCESS;
1956}
1957
1958#ifdef _MSC_VER
1959#pragma code_seg("PAGE")
1960#endif
1961/*****************************************************************************
1962 * CMiniportDMusUARTStream::SetState()
1963 *****************************************************************************
1964 * Sets the state of the channel.
1965 */
1967CMiniportDMusUARTStream::
1968SetState
1969(
1970 IN KSSTATE NewState
1971)
1972{
1973 PAGED_CODE();
1974
1975 DPRINT("SetState %d",NewState);
1976
1977 if (NewState == KSSTATE_RUN)
1978 {
1980 {
1981 LARGE_INTEGER timeDue100ns;
1982 timeDue100ns.QuadPart = 0;
1983 KeSetTimer(&m_TimerEvent,timeDue100ns,&m_Dpc);
1984 }
1985 else
1986 {
1987 DPRINT("CMiniportDMusUARTStream::SetState KSSTATE_RUN failed due to uninitialized MPU");
1989 }
1990 }
1991
1992 if (m_fCapture)
1993 {
1994 m_pMiniport->m_KSStateInput = NewState;
1995 if (NewState == KSSTATE_STOP) // STOPping
1996 {
1997 m_pMiniport->m_MPUInputBufferHead = 0; // Previously read bytes are discarded.
1998 m_pMiniport->m_MPUInputBufferTail = 0; // The entire FIFO is available.
1999 }
2000 }
2001 return STATUS_SUCCESS;
2002}
2003
2004#ifdef _MSC_VER
2005#pragma code_seg()
2006#endif
2007
2008
2009/*****************************************************************************
2010 * CMiniportDMusUART::Service()
2011 *****************************************************************************
2012 * DPC-mode service call from the port.
2013 */
2014STDMETHODIMP_(void)
2015CMiniportDMusUART::
2016Service
2017( void
2018)
2019{
2020 DPRINT("Service");
2022 {
2023 // we should never get here....
2024 // if we do, we must have read some trash,
2025 // so just reset the input FIFO
2027 }
2028}
2029
2030#ifdef _MSC_VER
2031#pragma code_seg("PAGE")
2032#endif
2033
2034/*****************************************************************************
2035 * CMiniportDMusUARTStream::ConnectOutput()
2036 *****************************************************************************
2037 * Writes outgoing MIDI data.
2038 */
2040CMiniportDMusUARTStream::
2041ConnectOutput(PMXF sinkMXF)
2042{
2043 PAGED_CODE();
2044
2045 if (m_fCapture)
2046 {
2047 if ((sinkMXF) && (m_sinkMXF == m_AllocatorMXF))
2048 {
2049 DPRINT("ConnectOutput");
2050 m_sinkMXF = sinkMXF;
2051 return STATUS_SUCCESS;
2052 }
2053 else
2054 {
2055 DPRINT("ConnectOutput failed");
2056 }
2057 }
2058 else
2059 {
2060 DPRINT("ConnectOutput called on renderer; failed");
2061 }
2062 return STATUS_UNSUCCESSFUL;
2063}
2064
2065#ifdef _MSC_VER
2066#pragma code_seg("PAGE")
2067#endif
2068
2069/*****************************************************************************
2070 * CMiniportDMusUARTStream::DisconnectOutput()
2071 *****************************************************************************
2072 * Writes outgoing MIDI data.
2073 */
2075CMiniportDMusUARTStream::
2076DisconnectOutput(PMXF sinkMXF)
2077{
2078 PAGED_CODE();
2079
2080 if (m_fCapture)
2081 {
2082 if ((m_sinkMXF == sinkMXF) || (!sinkMXF))
2083 {
2084 DPRINT("DisconnectOutput");
2086 return STATUS_SUCCESS;
2087 }
2088 else
2089 {
2090 DPRINT("DisconnectOutput failed");
2091 }
2092 }
2093 else
2094 {
2095 DPRINT("DisconnectOutput called on renderer; failed");
2096 }
2097 return STATUS_UNSUCCESSFUL;
2098}
2099
2100#ifdef _MSC_VER
2101#pragma code_seg()
2102#endif
2103
2104
2105/*****************************************************************************
2106 * CMiniportDMusUARTStream::PutMessageLocked()
2107 *****************************************************************************
2108 * Now that the spinlock is held, add this message to the queue.
2109 *
2110 * Writes an outgoing MIDI message.
2111 * We don't sort a new message into the queue -- we append it.
2112 * This is fine, since the sequencer feeds us sequenced data.
2113 * Timestamps will ascend by design.
2114 */
2115NTSTATUS CMiniportDMusUARTStream::PutMessageLocked(PDMUS_KERNEL_EVENT pDMKEvt)
2116{
2117 NTSTATUS ntStatus = STATUS_SUCCESS;
2118 PDMUS_KERNEL_EVENT aDMKEvt;
2119
2121
2122 if (!m_fCapture)
2123 {
2124 DPRINT("PutMessage to render stream");
2125 if (pDMKEvt)
2126 {
2127 // m_DpcSpinLock already held
2128
2129 if (m_DMKEvtQueue)
2130 {
2131 aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue
2132
2133 while (aDMKEvt->pNextEvt)
2134 {
2135 aDMKEvt = aDMKEvt->pNextEvt;
2136 }
2137 aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue
2138 }
2139 else // currently nothing in queue
2140 {
2141 m_DMKEvtQueue = pDMKEvt;
2142 if (m_DMKEvtOffset)
2143 {
2144 DPRINT("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d",m_DMKEvtOffset);
2145 m_DMKEvtOffset = 0;
2146 }
2147 }
2148
2149 // m_DpcSpinLock already held
2150 }
2151 if (!m_TimerQueued)
2152 {
2153 (void) ConsumeEvents();
2154 }
2155 }
2156 else // capture
2157 {
2158 DPRINT("PutMessage to capture stream");
2159 ASSERT(NULL == pDMKEvt);
2160
2161 SourceEvtsToPort();
2162 }
2163 return ntStatus;
2164}
2165
2166#ifdef _MSC_VER
2167#pragma code_seg()
2168#endif
2169
2170/*****************************************************************************
2171 * CMiniportDMusUARTStream::PutMessage()
2172 *****************************************************************************
2173 * Writes an outgoing MIDI message.
2174 * We don't sort a new message into the queue -- we append it.
2175 * This is fine, since the sequencer feeds us sequenced data.
2176 * Timestamps will ascend by design.
2177 */
2178NTSTATUS CMiniportDMusUARTStream::PutMessage(PDMUS_KERNEL_EVENT pDMKEvt)
2179{
2180 NTSTATUS ntStatus = STATUS_SUCCESS;
2181 PDMUS_KERNEL_EVENT aDMKEvt;
2182
2184
2185 if (!m_fCapture)
2186 {
2187 DPRINT("PutMessage to render stream");
2188 if (pDMKEvt)
2189 {
2191
2192 if (m_DMKEvtQueue)
2193 {
2194 aDMKEvt = m_DMKEvtQueue; // put pDMKEvt in event queue
2195
2196 while (aDMKEvt->pNextEvt)
2197 {
2198 aDMKEvt = aDMKEvt->pNextEvt;
2199 }
2200 aDMKEvt->pNextEvt = pDMKEvt; // here is end of queue
2201 }
2202 else // currently nothing in queue
2203 {
2204 m_DMKEvtQueue = pDMKEvt;
2205 if (m_DMKEvtOffset)
2206 {
2207 DPRINT("PutMessage Nothing in the queue, but m_DMKEvtOffset == %d", m_DMKEvtOffset);
2208 m_DMKEvtOffset = 0;
2209 }
2210 }
2211
2213 }
2214 if (!m_TimerQueued)
2215 {
2216 (void) ConsumeEvents();
2217 }
2218 }
2219 else // capture
2220 {
2221 DPRINT("PutMessage to capture stream");
2222 ASSERT(NULL == pDMKEvt);
2223
2224 SourceEvtsToPort();
2225 }
2226 return ntStatus;
2227}
2228
2229#ifdef _MSC_VER
2230#pragma code_seg()
2231#endif
2232
2233/*****************************************************************************
2234 * CMiniportDMusUARTStream::ConsumeEvents()
2235 *****************************************************************************
2236 * Attempts to empty the render message queue.
2237 * Called either from DPC timer or upon IRP submittal.
2238// TODO: support packages right
2239// process the package (actually, should do this above.
2240// treat the package as a list fragment that shouldn't be sorted.
2241// better yet, go through each event in the package, and when
2242// an event is exhausted, delete it and decrement m_offset.
2243 */
2244NTSTATUS CMiniportDMusUARTStream::ConsumeEvents(void)
2245{
2246 PDMUS_KERNEL_EVENT aDMKEvt;
2247
2248 NTSTATUS ntStatus = STATUS_SUCCESS;
2249 ULONG bytesRemaining = 0,bytesWritten = 0;
2250 LARGE_INTEGER aMillisecIn100ns;
2251
2254
2256 while (m_DMKEvtQueue) // do we have anything to play at all?
2257 {
2258 aDMKEvt = m_DMKEvtQueue; // event we try to play
2259 if (aDMKEvt->cbEvent)
2260 {
2261 bytesRemaining = aDMKEvt->cbEvent - m_DMKEvtOffset; // number of bytes left in this evt
2262
2263 ASSERT(bytesRemaining > 0);
2264 if (bytesRemaining <= 0)
2265 {
2266 bytesRemaining = aDMKEvt->cbEvent;
2267 }
2268
2269 if (aDMKEvt->cbEvent <= sizeof(PBYTE)) // short message
2270 {
2271 DPRINT("ConsumeEvents(%02x%02x%02x%02x)", aDMKEvt->uData.abData[0], aDMKEvt->uData.abData[1], aDMKEvt->uData.abData[2], aDMKEvt->uData.abData[3]);
2272 ntStatus = Write(aDMKEvt->uData.abData + m_DMKEvtOffset,bytesRemaining,&bytesWritten);
2273 }
2274 else if (PACKAGE_EVT(aDMKEvt))
2275 {
2276 ASSERT(m_DMKEvtOffset == 0);
2277 m_DMKEvtOffset = 0;
2278 DPRINT("ConsumeEvents(Package)");
2279
2280 ntStatus = PutMessageLocked(aDMKEvt->uData.pPackageEvt); // we already own the spinlock
2281
2282 // null this because we are about to throw it in the allocator
2283 aDMKEvt->uData.pPackageEvt = NULL;
2284 aDMKEvt->cbEvent = 0;
2285 bytesWritten = bytesRemaining;
2286 }
2287 else // SysEx message
2288 {
2289 DPRINT("ConsumeEvents(%02x%02x%02x%02x)", aDMKEvt->uData.pbData[0], aDMKEvt->uData.pbData[1], aDMKEvt->uData.pbData[2], aDMKEvt->uData.pbData[3]);
2290
2291 ntStatus = Write(aDMKEvt->uData.pbData + m_DMKEvtOffset,bytesRemaining,&bytesWritten);
2292 }
2293 } // if (aDMKEvt->cbEvent)
2294 if (STATUS_SUCCESS != ntStatus)
2295 {
2296 DPRINT("ConsumeEvents: Write returned 0x%08x", ntStatus);
2297 bytesWritten = bytesRemaining; // just bail on this event and try next time
2298 }
2299
2300 ASSERT(bytesWritten <= bytesRemaining);
2301 if (bytesWritten == bytesRemaining)
2302 {
2304 aDMKEvt->pNextEvt = NULL;
2305
2306 m_AllocatorMXF->PutMessage(aDMKEvt); // throw back in free pool
2307 m_DMKEvtOffset = 0; // start fresh on next evt
2309 } // but wait ... there's more!
2310 else // our FIFO is full for now.
2311 {
2312 // update our offset by that amount we did write
2314 ASSERT(m_DMKEvtOffset < aDMKEvt->cbEvent);
2315
2316 DPRINT("ConsumeEvents tried %d, wrote %d, at offset %d", bytesRemaining,bytesWritten,m_DMKEvtOffset);
2317 aMillisecIn100ns.QuadPart = -(kOneMillisec); // set timer, come back later
2320 ntStatus = KeSetTimer( &m_TimerEvent, aMillisecIn100ns, &m_Dpc );
2321 break;
2322 } // we didn't write it all
2323 } // go back, Jack, do it again (while m_DMKEvtQueue)
2325 return ntStatus;
2326}
2327
2328#ifdef _MSC_VER
2329#pragma code_seg()
2330#endif
2331
2332/*****************************************************************************
2333 * CMiniportDMusUARTStream::HandlePortParams()
2334 *****************************************************************************
2335 * Writes an outgoing MIDI message.
2336 */
2340(
2342)
2343{
2344 PAGED_CODE();
2345
2346 NTSTATUS ntStatus;
2347
2348 if (pRequest->Verb & KSPROPERTY_TYPE_SET)
2349 {
2351 }
2352
2354 if (NT_SUCCESS(ntStatus))
2355 {
2356 RtlCopyMemory(pRequest->Value, pRequest->Instance, sizeof(SYNTH_PORTPARAMS));
2357
2359
2360 if (Params->ValidParams & ~SYNTH_PORTPARAMS_CHANNELGROUPS)
2361 {
2362 Params->ValidParams &= SYNTH_PORTPARAMS_CHANNELGROUPS;
2363 }
2364
2365 if (!(Params->ValidParams & SYNTH_PORTPARAMS_CHANNELGROUPS))
2366 {
2367 Params->ChannelGroups = 1;
2368 }
2369 else if (Params->ChannelGroups != 1)
2370 {
2371 Params->ChannelGroups = 1;
2372 }
2373
2374 pRequest->ValueSize = sizeof(SYNTH_PORTPARAMS);
2375 }
2376
2377 return ntStatus;
2378}
2379
2380#ifdef _MSC_VER
2381#pragma code_seg()
2382#endif
2383
2384/*****************************************************************************
2385 * DMusTimerDPC()
2386 *****************************************************************************
2387 * The timer DPC callback. Thunks to a C++ member function.
2388 * This is called by the OS in response to the DirectMusic pin
2389 * wanting to wakeup later to process more DirectMusic stuff.
2390 */
2391VOID
2392NTAPI
2394(
2395 IN PKDPC Dpc,
2399)
2400{
2402
2403 CMiniportDMusUARTStream *aStream;
2405 if (aStream)
2406 {
2407 DPRINT("DMusUARTTimerDPC");
2408 if (false == aStream->m_fCapture)
2409 {
2410 (void) aStream->ConsumeEvents();
2411 }
2412 // ignores return value!
2413 }
2414}
2415
2416/*****************************************************************************
2417 * DirectMusic properties
2418 ****************************************************************************/
2419
2420#ifdef _MSC_VER
2421#pragma code_seg()
2422#endif
2423
2424/*
2425 * Properties concerning synthesizer functions.
2426 */
2427const WCHAR wszDescOut[] = L"DMusic MPU-401 Out ";
2428const WCHAR wszDescIn[] = L"DMusic MPU-401 In ";
2429
2431NTAPI
2433(
2435)
2436{
2437 NTSTATUS ntStatus;
2438
2439 PAGED_CODE();
2440
2442 {
2443 ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONG), TRUE);
2444 if (NT_SUCCESS(ntStatus))
2445 {
2446 // if return buffer can hold a ULONG, return the access flags
2447 PULONG AccessFlags = PULONG(pRequest->Value);
2448
2449 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT;
2450 switch (pRequest->PropertyItem->Id)
2451 {
2454 *AccessFlags |= KSPROPERTY_TYPE_GET;
2455 }
2456 switch (pRequest->PropertyItem->Id)
2457 {
2459 *AccessFlags |= KSPROPERTY_TYPE_SET;
2460 }
2461 ntStatus = STATUS_SUCCESS;
2462 pRequest->ValueSize = sizeof(ULONG);
2463
2464 switch (pRequest->PropertyItem->Id)
2465 {
2467 if (pRequest->MinorTarget)
2468 {
2469 *AccessFlags |= KSPROPERTY_TYPE_GET;
2470 }
2471 else
2472 {
2473 pRequest->ValueSize = 0;
2475 }
2476 }
2477 }
2478 }
2479 else
2480 {
2481 ntStatus = STATUS_SUCCESS;
2482 switch(pRequest->PropertyItem->Id)
2483 {
2485 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_CAPS");
2486
2487 if (pRequest->Verb & KSPROPERTY_TYPE_SET)
2488 {
2490 }
2491
2492 if (NT_SUCCESS(ntStatus))
2493 {
2494 ntStatus = ValidatePropertyRequest(pRequest, sizeof(SYNTHCAPS), TRUE);
2495
2496 if (NT_SUCCESS(ntStatus))
2497 {
2498 SYNTHCAPS *caps = (SYNTHCAPS*)pRequest->Value;
2499 int increment;
2500 RtlZeroMemory(caps, sizeof(SYNTHCAPS));
2501 // XXX Different guids for different instances!
2502 //
2503 if (pRequest->Node == eSynthNode)
2504 {
2505 increment = sizeof(wszDescOut) - 2;
2506 RtlCopyMemory( caps->Description,wszDescOut,increment);
2507 caps->Guid = CLSID_MiniportDriverDMusUART;
2508 }
2509 else
2510 {
2511 increment = sizeof(wszDescIn) - 2;
2512 RtlCopyMemory( caps->Description,wszDescIn,increment);
2513 caps->Guid = CLSID_MiniportDriverDMusUARTCapture;
2514 }
2515
2516 caps->Flags = SYNTH_PC_EXTERNAL;
2517 caps->MemorySize = 0;
2518 caps->MaxChannelGroups = 1;
2519 caps->MaxVoices = 0xFFFFFFFF;
2520 caps->MaxAudioChannels = 0xFFFFFFFF;
2521
2522 caps->EffectFlags = 0;
2523
2524 CMiniportDMusUART *aMiniport;
2525 ASSERT(pRequest->MajorTarget);
2526 aMiniport = (CMiniportDMusUART *)(PMINIPORTDMUS)(pRequest->MajorTarget);
2527 WCHAR wszDesc2[16];
2528 int cLen;
2529 cLen = swprintf(wszDesc2,L"[%03x]\0",PtrToUlong(aMiniport->m_pPortBase));
2530
2531 cLen *= sizeof(WCHAR);
2532 RtlCopyMemory((WCHAR *)((DWORD_PTR)(caps->Description) + increment),
2533 wszDesc2,
2534 cLen);
2535
2536
2537 pRequest->ValueSize = sizeof(SYNTHCAPS);
2538 }
2539 }
2540
2541 break;
2542
2544 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_PORTPARAMETERS");
2545 {
2546 CMiniportDMusUARTStream *aStream;
2547
2548 aStream = (CMiniportDMusUARTStream*)(pRequest->MinorTarget);
2549 if (aStream)
2550 {
2551 ntStatus = aStream->HandlePortParams(pRequest);
2552 }
2553 else
2554 {
2556 }
2557 }
2558 break;
2559
2561 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_CHANNELGROUPS");
2562
2563 ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONG), TRUE);
2564 if (NT_SUCCESS(ntStatus))
2565 {
2566 *(PULONG)(pRequest->Value) = 1;
2567 pRequest->ValueSize = sizeof(ULONG);
2568 }
2569 break;
2570
2572 DPRINT("PropertyHandler_Synth:KSPROPERTY_SYNTH_LATENCYCLOCK");
2573
2574 if(pRequest->Verb & KSPROPERTY_TYPE_SET)
2575 {
2577 }
2578 else
2579 {
2580 ntStatus = ValidatePropertyRequest(pRequest, sizeof(ULONGLONG), TRUE);
2581 if(NT_SUCCESS(ntStatus))
2582 {
2583 REFERENCE_TIME rtLatency;
2584 CMiniportDMusUARTStream *aStream;
2585
2586 aStream = (CMiniportDMusUARTStream*)(pRequest->MinorTarget);
2587 if(aStream == NULL)
2588 {
2590 }
2591 else
2592 {
2593 aStream->m_pMiniport->m_MasterClock->GetTime(&rtLatency);
2594 *((PULONGLONG)pRequest->Value) = rtLatency;
2595 pRequest->ValueSize = sizeof(ULONGLONG);
2596 }
2597 }
2598 }
2599 break;
2600
2601 default:
2602 DPRINT("Unhandled property in PropertyHandler_Synth");
2603 break;
2604 }
2605 }
2606 return ntStatus;
2607}
2608
2609/*****************************************************************************
2610 * ValidatePropertyRequest()
2611 *****************************************************************************
2612 * Validates pRequest.
2613 * Checks if the ValueSize is valid
2614 * Checks if the Value is valid
2615 *
2616 * This does not update pRequest->ValueSize if it returns NT_SUCCESS.
2617 * Caller must set pRequest->ValueSize in case of NT_SUCCESS.
2618 */
2620(
2622 IN ULONG ulValueSize,
2623 IN BOOLEAN fValueRequired
2624)
2625{
2626 NTSTATUS ntStatus;
2627
2628 if (pRequest->ValueSize >= ulValueSize)
2629 {
2630 if (fValueRequired && NULL == pRequest->Value)
2631 {
2632 ntStatus = STATUS_INVALID_PARAMETER;
2633 }
2634 else
2635 {
2636 ntStatus = STATUS_SUCCESS;
2637 }
2638 }
2639 else if (0 == pRequest->ValueSize)
2640 {
2641 ntStatus = STATUS_BUFFER_OVERFLOW;
2642 }
2643 else
2644 {
2645 ntStatus = STATUS_BUFFER_TOO_SMALL;
2646 }
2647
2648 if (STATUS_BUFFER_OVERFLOW == ntStatus)
2649 {
2650 pRequest->ValueSize = ulValueSize;
2651 }
2652 else
2653 {
2654 pRequest->ValueSize = 0;
2655 }
2656
2657 return ntStatus;
2658} // ValidatePropertyRequest
2659
2660#ifdef _MSC_VER
2661#pragma code_seg()
2662#endif
2663
2664
#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
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
#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 NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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:37
#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:305
#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
@ eSynthNode
@ eInputNode
static PKSDATARANGE PinDataRangePointersStreamDMusic[]
static PKSDATARANGE PinDataRangePointersBridge[]
NTSTATUS NewMiniportDMusUART(OUT PMINIPORT *OutMiniport, IN REFCLSID ClassId)
NTSTATUS NTAPI SynchronizedDMusMPUWrite(PINTERRUPTSYNC InterruptSync, PVOID syncWriteContext)
@ eFilterInputPinDM
@ eFilterInputPinLeg
@ eBridgeOutputPin
@ eBridgeInputPin
@ eFilterOutputPin
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[]
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)
#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
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:383
_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 STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#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:71
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
USHORT usChannelGroup
Definition: dmusicks.h:16
REFERENCE_TIME ullPresTime100ns
Definition: dmusicks.h:18
union _DMUS_KERNEL_EVENT::@1902 uData
Definition: ketypes.h:687
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:676
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:677
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193