2 Copyright (c) 2006-2007 dogbert <dogber1@gmail.com>
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #define PUT_GUIDS_HERE
30 #include "adapter.hpp"
32 //#pragma code_seg("PAGE")
34 const GUID KSNODETYPE_DAC
= {0x507AE360L
, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
35 const GUID KSNODETYPE_ADC
= {0x4D837FE0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
36 const GUID KSNODETYPE_AGC
= {0xE88C9BA0L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
37 const GUID KSNODETYPE_LOUDNESS
= {0x41887440L
, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
38 const GUID KSNODETYPE_MUTE
= {0x02B223C0L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
39 const GUID KSNODETYPE_TONE
= {0x7607E580L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
40 const GUID KSNODETYPE_VOLUME
= {0x3A5ACC00L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
41 const GUID KSNODETYPE_PEAKMETER
= {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}};
42 const GUID KSNODETYPE_MUX
= {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
43 const GUID KSNODETYPE_STEREO_WIDE
= {0xA9E69800L
, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
44 const GUID KSNODETYPE_CHORUS
= {0x20173F20L
, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
45 const GUID KSNODETYPE_REVERB
= {0xEF0328E0L
, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
46 const GUID KSNODETYPE_SUPERMIX
= {0xE573ADC0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
47 const GUID KSNODETYPE_SUM
= {0xDA441A60L
, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
48 const GUID KSNODETYPE_SRC
= {0x9DB7B9E0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
49 const GUID KSNODETYPE_3D_EFFECTS
= {0x55515860L
, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
50 const GUID KSNODETYPE_SPDIF_INTERFACE
= {0x0605+0xDFF219E0, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
51 const GUID KSNODETYPE_MICROPHONE
= {0x0201+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
52 const GUID KSNODETYPE_CD_PLAYER
= {0x0703+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
53 const GUID KSNODETYPE_LINE_CONNECTOR
= {0x0603+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
54 const GUID KSNODETYPE_ANALOG_CONNECTOR
= {0x601+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
55 const GUID KSNODETYPE_SPEAKER
= {0x0301+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
57 const GUID KSPROPTYPESETID_General
= {0x97E99BA0L
, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
58 const GUID KSPROPSETID_General
= {0x1464EDA5L
, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
59 const GUID KSPROPSETID_Audio
= {0x45FFAAA0L
, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
60 const GUID GUID_NULL
={0x00000000L
, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
61 const GUID KSCATEGORY_AUDIO
= {0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
64 const GUID KSDATAFORMAT_TYPE_AUDIO
= {0x73647561L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
65 const GUID KSDATAFORMAT_SUBTYPE_PCM
= {0x00000001L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
66 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
= {0x05589f81L
, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
67 const GUID KSDATAFORMAT_SPECIFIER_DSOUND
= {0x518590a2L
, 0xa184, 0x11d0, {0x85, 0x22, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3}};
68 const GUID KSDATAFORMAT_SUBTYPE_WAVEFORMATEX
= {0x00000000L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
69 const GUID KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF
= {0x00000092L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
72 const GUID KSAUDFNAME_WAVE_VOLUME
= {0x185FEDE5L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
73 const GUID KSAUDFNAME_WAVE_MUTE
= {0x185FEDE6L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
74 const GUID KSAUDFNAME_MIC_VOLUME
= {0x185FEDEDL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
75 const GUID KSAUDFNAME_MASTER_VOLUME
= {0x185FEDE3L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
76 const GUID KSAUDFNAME_RECORDING_SOURCE
= {0x185FEDEFL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
77 const GUID KSAUDFNAME_CD_VOLUME
= {0x185FEDE9L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
78 const GUID KSAUDFNAME_CD_IN_VOLUME
= {0x185FEDF3L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
79 const GUID KSAUDFNAME_MIC_IN_VOLUME
= {0x185FEDF5L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
80 const GUID KSAUDFNAME_MICROPHONE_BOOST
= {0x2bc31d6aL
, 0x96e3, 0x11d2, {0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68}};
81 const GUID KSAUDFNAME_CD_MUTE
= {0x185FEDEAL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
82 const GUID KSAUDFNAME_LINE_MUTE
= {0x185FEDECL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
83 const GUID KSAUDFNAME_MIC_MUTE
= {0x185FEDEEL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
84 const GUID KSAUDFNAME_AUX_MUTE
= {0x185FEDFDL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
85 const GUID KSAUDFNAME_MASTER_MUTE
= {0x185FEDE4L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
86 const GUID KSAUDFNAME_RECORDING_CONTROL
= {0x185FEDFAL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
87 const GUID KSAUDFNAME_VOLUME_CONTROL
= {0x185FEDF7L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
88 const GUID KSAUDFNAME_LINE_IN_VOLUME
= {0x185FEDF4L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
89 const GUID KSAUDFNAME_AUX_VOLUME
= {0x185FEDFCL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
91 const GUID KSPROPSETID_CMI
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}};
94 const GUID CMINAME_IEC_5V
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF0}};
95 const GUID CMINAME_IEC_OUT
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF1}};
96 const GUID CMINAME_IEC_INVERSE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF2}};
97 const GUID CMINAME_IEC_MONITOR
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF3}};
98 const GUID CMINAME_IEC_SELECT
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF5}};
99 const GUID CMINAME_XCHG_FB
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF6}};
100 const GUID CMINAME_BASS2LINE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF7}};
101 const GUID CMINAME_CENTER2LINE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF8}};
102 const GUID CMINAME_IEC_COPYRIGHT
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF9}};
103 const GUID CMINAME_IEC_POLVALID
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFA}};
104 const GUID CMINAME_IEC_LOOP
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFB}};
105 const GUID CMINAME_REAR2LINE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFC}};
106 const GUID CMINAME_CENTER2MIC
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFD}};
107 const GUID CMINAME_DAC
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF4}};
108 const GUID PRODUCT_CM8738
= {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9c}};
109 const GUID COMPONENT_CM8738
= {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9d}};
110 const GUID MANUFACTURER_CM8738
= {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9e}};
113 NTSTATUS
InstallSubdevice(
114 PDEVICE_OBJECT DeviceObject
,
118 REFGUID MiniportClassId
,
119 PFNCREATEINSTANCE MiniportCreate
,
120 PUNKNOWN UnknownAdapter
,
121 PRESOURCELIST ResourceList
,
122 REFGUID PortInterfaceId
,
123 PUNKNOWN
* OutPortUnknown
)
130 DBGPRINT(("InstallSubdevice()"));
132 ntStatus
= PcNewPort(&Port
, PortClassId
);
133 if (NT_SUCCESS(ntStatus
)) {
134 if (MiniportCreate
) {
135 ntStatus
= MiniportCreate((PUNKNOWN
*)&MiniPort
, MiniportClassId
, NULL
, NonPagedPool
);
137 ntStatus
= PcNewMiniport(&MiniPort
, MiniportClassId
);
141 if (!NT_SUCCESS(ntStatus
)) {
146 ntStatus
= Port
->Init(DeviceObject
, Irp
, MiniPort
, UnknownAdapter
, ResourceList
);
147 if (NT_SUCCESS(ntStatus
)) {
148 ntStatus
= PcRegisterSubdevice(DeviceObject
, Name
, Port
);
150 if (OutPortUnknown
&& NT_SUCCESS (ntStatus
)) {
151 ntStatus
= Port
->QueryInterface(IID_IUnknown
, (PVOID
*)OutPortUnknown
);
169 PRESOURCELIST ResourceList
,
170 PRESOURCELIST
* UartResourceList
)
175 ////ASSERT(ResourceList);
176 ////ASSERT(UartResourceList);
177 //DBGPRINT(("ProcessResources()"));
178 //DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas()));
181 (*UartResourceList
) = NULL
;
185 if ((ResourceList
->NumberOfPorts() == 0) || (ResourceList
->NumberOfPorts() > 2) || (ResourceList
->NumberOfInterrupts() != 1) || (ResourceList
->NumberOfDmas() != 0)) {
186 DBGPRINT(("Unexpected configuration"));
187 return STATUS_DEVICE_CONFIGURATION_ERROR
;
191 ntStatus
= PcNewResourceSublist(UartResourceList
, NULL
, PagedPool
, ResourceList
, 2);
192 if (NT_SUCCESS(ntStatus
)) {
193 (*UartResourceList
)->AddPortFromParent(ResourceList
, 1);
194 (*UartResourceList
)->AddInterruptFromParent(ResourceList
, 0);
198 return STATUS_SUCCESS
;
202 NTSTATUS
StartDevice(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PRESOURCELIST ResourceList
)
209 //ASSERT(DeviceObject);
211 //ASSERT(ResourceList);
212 DBGPRINT(("StartDevice()"));
215 ntStatus
= PcNewPort(&pPort
,CLSID_PortWaveCyclic
);
216 if (NT_SUCCESS(ntStatus
)) {
217 // not supported in the first edition of win98
218 PPORTEVENTS pPortEvents
= 0;
219 ntStatus
= pPort
->QueryInterface(IID_IPortEvents
, (PVOID
*)&pPortEvents
);
220 if (!NT_SUCCESS(ntStatus
)) {
221 DBGPRINT(("ERROR: This driver doesn't work under Win98!"));
222 ntStatus
= STATUS_UNSUCCESSFUL
;
226 pPortEvents
->Release();
233 // resource validation
234 PRESOURCELIST UartResourceList
= NULL
;
235 ntStatus
= ProcessResources(ResourceList
, &UartResourceList
);
236 if (!NT_SUCCESS(ntStatus
)) {
237 DBGPRINT(("ProcessResources() failed"));
241 PCMIADAPTER pCMIAdapter
= NULL
;
242 PUNKNOWN pUnknownCommon
= NULL
;
244 // create the CMIAdapter object
245 ntStatus
= NewCMIAdapter(&pUnknownCommon
, IID_ICMIAdapter
, NULL
, NonPagedPool
);
246 if (!NT_SUCCESS(ntStatus
)) {
247 DBGPRINT(("NewCMIAdapter() failed"));
251 ntStatus
= pUnknownCommon
->QueryInterface(IID_ICMIAdapter
, (PVOID
*)&pCMIAdapter
);
252 if (!NT_SUCCESS(ntStatus
)) {
253 DBGPRINT(("QueryInterface() for ICMIAdapter failed"));
256 ntStatus
= pCMIAdapter
->init(ResourceList
, DeviceObject
);
257 if (!NT_SUCCESS(ntStatus
)) {
258 DBGPRINT(("CMIAdapter->init() failed"));
262 ntStatus
= PcRegisterAdapterPowerManagement((PUNKNOWN
)pCMIAdapter
, DeviceObject
);
264 pUnknownCommon
->Release();
266 PUNKNOWN unknownWave
= NULL
;
267 PUNKNOWN unknownTopology
= NULL
;
269 // install the topology miniport.
270 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Topology", CLSID_PortTopology
, CLSID_PortTopology
, CreateMiniportTopologyCMI
, pCMIAdapter
, NULL
, GUID_NULL
, &unknownTopology
);
271 if (!NT_SUCCESS (ntStatus
)) {
272 DBGPRINT(("Topology miniport installation failed"));
277 // install the UART miniport - execution order important
278 ntStatus
= STATUS_UNSUCCESSFUL
;
280 for (int i
=0;i
<ResourceList
->NumberOfPorts();i
++) {
281 if (ResourceList
->FindTranslatedPort(i
)->u
.Port
.Length
== 2) {
282 MPUBase
= (UInt32
*)ResourceList
->FindTranslatedPort(i
)->u
.Port
.Start
.QuadPart
;
286 ntStatus
= pCMIAdapter
->activateMPU(MPUBase
);
287 if (NT_SUCCESS(ntStatus
)) {
288 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Uart", CLSID_PortDMus
, CLSID_MiniportDriverDMusUART
, NULL
, pCMIAdapter
->getInterruptSync(), UartResourceList
, IID_IPortDMus
, NULL
);
291 if (!NT_SUCCESS(ntStatus
)) {
293 pCMIAdapter
->activateMPU(0);
294 DBGPRINT(("UART miniport installation failed"));
296 if (UartResourceList
) {
297 UartResourceList
->Release();
301 // install the wave miniport - the order matters here
303 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Wave", CLSID_PortWaveRT
, CLSID_PortWaveRT
, CreateMiniportWaveCMI
, pCMIAdapter
, ResourceList
, IID_IPortWaveRT
, &unknownWave
);
305 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Wave", CLSID_PortWaveCyclic
, CLSID_PortWaveCyclic
, CreateMiniportWaveCMI
, pCMIAdapter
, ResourceList
, IID_IPortWaveCyclic
, &unknownWave
);
307 if (!NT_SUCCESS(ntStatus
)) {
308 DBGPRINT(("Wave miniport installation failed"));
312 // connect wave and topology pins
313 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownWave
, PIN_WAVE_RENDER_SOURCE
, unknownTopology
, PIN_WAVEOUT_SOURCE
);
314 if (!NT_SUCCESS(ntStatus
)) {
315 DBGPRINT(("Cannot connect topology and wave miniport (render)!"));
318 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownTopology
, PIN_WAVEIN_DEST
, unknownWave
, PIN_WAVE_CAPTURE_SOURCE
);
319 if (!NT_SUCCESS(ntStatus
)) {
320 DBGPRINT(("Cannot connect topology and wave miniport (capture)!"));
323 if (!IoIsWdmVersionAvailable(6,0)) {
324 // this shit fixes the fucking XP mixer and breaks the vista mixer, so we have to check for vista here
325 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownWave
, PIN_WAVE_AC3_RENDER_SOURCE
, unknownTopology
, PIN_SPDIF_AC3_SOURCE
);
326 if (!NT_SUCCESS(ntStatus
)) {
327 DBGPRINT(("Cannot connect topology and wave miniport (ac3)!"));
333 pCMIAdapter
->Release();
335 if (unknownTopology
) {
336 unknownTopology
->Release();
339 unknownWave
->Release();
350 PDRIVER_OBJECT DriverObject
,
351 PDEVICE_OBJECT PhysicalDeviceObject
)
355 DBGPRINT(("AddDevice()"));
358 return PcAddAdapterDevice(DriverObject
, PhysicalDeviceObject
, (PCPFNSTARTDEVICE
)StartDevice
, MAX_MINIPORTS
, 0);
361 bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor
, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor
)
365 //ASSERT(pInResDescriptor);
366 //ASSERT(pOutResDescriptor);
367 DBGPRINT(("CopyResourceDescriptor()"));
368 RtlCopyMemory(pOutResDescriptor
, pInResDescriptor
, sizeof(IO_RESOURCE_DESCRIPTOR
));
370 pOutResDescriptor
->Type
= pInResDescriptor
->Type
;
371 pOutResDescriptor
->ShareDisposition
= pInResDescriptor
->ShareDisposition
;
372 pOutResDescriptor
->Flags
= pInResDescriptor
->Flags
;
373 pOutResDescriptor
->Option
= pInResDescriptor
->Option
;
375 switch (pInResDescriptor
->Type
) {
376 case CmResourceTypePort
:
377 case CmResourceTypePort
| CmResourceTypeNonArbitrated
: // huh?
379 if ((pInResDescriptor->u.Port.Length == 0) ||
380 ( (pInResDescriptor->u.Port.MinimumAddress.HighPart == pInResDescriptor->u.Port.MaximumAddress.HighPart) && (pInResDescriptor->u.Port.MinimumAddress.LowPart == pInResDescriptor->u.Port.MaximumAddress.LowPart) ) ) {
383 */ pOutResDescriptor
->u
.Port
.MinimumAddress
= pInResDescriptor
->u
.Port
.MinimumAddress
;
384 pOutResDescriptor
->u
.Port
.MaximumAddress
= pInResDescriptor
->u
.Port
.MaximumAddress
;
385 pOutResDescriptor
->u
.Port
.Length
= pInResDescriptor
->u
.Port
.Length
;
386 pOutResDescriptor
->u
.Port
.Alignment
= pInResDescriptor
->u
.Port
.Alignment
;
388 DBGPRINT((" Port: min %08x.%08x max %08x.%08x, Length: %x, Option: %x", pOutResDescriptor
->u
.Port
.MinimumAddress
.HighPart
, pOutResDescriptor
->u
.Port
.MinimumAddress
.LowPart
,
389 pOutResDescriptor
->u
.Port
.MaximumAddress
.HighPart
, pOutResDescriptor
->u
.Port
.MaximumAddress
.LowPart
,
390 pOutResDescriptor
->u
.Port
.Length
, pOutResDescriptor
->Option
));
393 case CmResourceTypeInterrupt
:
394 pOutResDescriptor
->u
.Interrupt
.MinimumVector
= pInResDescriptor
->u
.Interrupt
.MinimumVector
;
395 pOutResDescriptor
->u
.Interrupt
.MaximumVector
= pInResDescriptor
->u
.Interrupt
.MaximumVector
;
397 DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor
->u
.Interrupt
.MinimumVector
, pOutResDescriptor
->u
.Interrupt
.MaximumVector
, pOutResDescriptor
->Option
));
412 PDEVICE_OBJECT pDeviceObject
,
415 NTSTATUS ntStatus
= STATUS_SUCCESS
;
416 ULONG resourceListSize
;
417 PIO_RESOURCE_REQUIREMENTS_LIST resourceList
, list
;
418 PIO_RESOURCE_DESCRIPTOR descriptor
;
419 PIO_STACK_LOCATION pIrpStack
= IoGetCurrentIrpStackLocation(pIrp
);
422 ////ASSERT(pDeviceObject);
424 DBGPRINT(("AdapterDispatchPnp()"));
426 if (pIrpStack
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
) {
427 DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS"));
429 list
= (PIO_RESOURCE_REQUIREMENTS_LIST
)pIrp
->IoStatus
.Information
;
431 // IO_RESOURCE_REQUIREMENTS_LIST has 1 IO_RESOURCE_LIST, IO_RESOURCE_LIST has 1 IO_RESOURCE_DESCRIPTOR and we want 2 more
432 resourceListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
)*(list
->List
[0].Count
+2) ;
433 resourceList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePoolWithTag(PagedPool
, resourceListSize
, 'LRDV');
436 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
441 RtlZeroMemory(resourceList
, resourceListSize
);
443 // initialize the list header
444 resourceList
->AlternativeLists
= 1; // number of IO_RESOURCE_LISTs
445 resourceList
->ListSize
= resourceListSize
;
447 resourceList
->List
[0].Version
= 1;
448 resourceList
->List
[0].Revision
= 1;
449 resourceList
->List
[0].Count
= 0;
451 // copy the resources which have already been assigned
452 for (int i
=0;i
<list
->List
[0].Count
;i
++) {
453 if (CopyResourceDescriptor(&list
->List
[0].Descriptors
[i
], &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
])) {
454 resourceList
->List
[0].Count
++;
459 // an additional port for mpu401
460 resourceList
->List
[0].Count
++;
461 descriptor
= &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
-1];
462 descriptor
->Option
= IO_RESOURCE_PREFERRED
;
463 descriptor
->Type
= CmResourceTypePort
;
464 descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
465 descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
466 descriptor
->u
.Port
.MinimumAddress
.LowPart
= 0x300;
467 descriptor
->u
.Port
.MinimumAddress
.HighPart
= 0;
468 descriptor
->u
.Port
.MaximumAddress
.LowPart
= 0x330;
469 descriptor
->u
.Port
.MaximumAddress
.HighPart
= 0;
470 descriptor
->u
.Port
.Length
= 2;
471 descriptor
->u
.Port
.Alignment
= 0x10;
473 // mpu401 port should be optional. yes, this is severely braindamaged.
474 resourceList
->List
[0].Count
++;
475 descriptor
= &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
-1];
476 descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
477 descriptor
->Type
= CmResourceTypePort
;
478 descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
479 descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
480 descriptor
->u
.Port
.MinimumAddress
.LowPart
= 0x0;
481 descriptor
->u
.Port
.MinimumAddress
.HighPart
= 0;
482 descriptor
->u
.Port
.MaximumAddress
.LowPart
= 0xFFFF;
483 descriptor
->u
.Port
.MaximumAddress
.HighPart
= 0;
484 descriptor
->u
.Port
.Length
= 1;
485 descriptor
->u
.Port
.Alignment
= 0x10;
487 // DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count));
489 pIrp
->IoStatus
.Information
= (ULONG_PTR
)resourceList
;
491 // set the return status
492 pIrp
->IoStatus
.Status
= ntStatus
;
495 // Pass the IRPs on to PortCls
496 ntStatus
= PcDispatchIrp(pDeviceObject
, pIrp
);
506 PDRIVER_OBJECT DriverObject
,
507 PUNICODE_STRING RegistryPathName
)
511 DBGPRINT(("DriverEntry()"));
514 //bind the adapter driver to the portclass driver
515 ntStatus
= PcInitializeAdapterDriver(DriverObject
, RegistryPathName
, AddDevice
);
519 if(NT_SUCCESS(ntStatus
)) {
520 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = AdapterDispatchPnp
;
524 if (!IoIsWdmVersionAvailable(6,0)) {
525 ntStatus
= STATUS_UNSUCCESSFUL
;
536 int __cdecl
_purecall (void)
544 void __cxa_pure_virtual()
546 // put error handling here