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"
33 //#pragma code_seg("PAGE") // GCC ignores pragma code_seg
36 const GUID KSNODETYPE_DAC
= {0x507AE360L
, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
37 const GUID KSNODETYPE_ADC
= {0x4D837FE0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
38 const GUID KSNODETYPE_AGC
= {0xE88C9BA0L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
39 const GUID KSNODETYPE_LOUDNESS
= {0x41887440L
, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
40 const GUID KSNODETYPE_MUTE
= {0x02B223C0L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
41 const GUID KSNODETYPE_TONE
= {0x7607E580L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
42 const GUID KSNODETYPE_VOLUME
= {0x3A5ACC00L
, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
43 const GUID KSNODETYPE_PEAKMETER
= {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}};
44 const GUID KSNODETYPE_MUX
= {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
45 const GUID KSNODETYPE_STEREO_WIDE
= {0xA9E69800L
, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
46 const GUID KSNODETYPE_CHORUS
= {0x20173F20L
, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
47 const GUID KSNODETYPE_REVERB
= {0xEF0328E0L
, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
48 const GUID KSNODETYPE_SUPERMIX
= {0xE573ADC0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
49 const GUID KSNODETYPE_SUM
= {0xDA441A60L
, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
50 const GUID KSNODETYPE_SRC
= {0x9DB7B9E0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
51 const GUID KSNODETYPE_3D_EFFECTS
= {0x55515860L
, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
52 const GUID KSNODETYPE_SPDIF_INTERFACE
= {0x0605+0xDFF219E0, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
53 const GUID KSNODETYPE_MICROPHONE
= {0x0201+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
54 const GUID KSNODETYPE_CD_PLAYER
= {0x0703+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
55 const GUID KSNODETYPE_LINE_CONNECTOR
= {0x0603+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
56 const GUID KSNODETYPE_ANALOG_CONNECTOR
= {0x601+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
57 const GUID KSNODETYPE_SPEAKER
= {0x0301+0xDFF219E0,0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
59 const GUID KSPROPTYPESETID_General
= {0x97E99BA0L
, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
60 const GUID KSPROPSETID_General
= {0x1464EDA5L
, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
61 const GUID KSPROPSETID_Audio
= {0x45FFAAA0L
, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
62 const GUID GUID_NULL
={0x00000000L
, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
63 const GUID KSCATEGORY_AUDIO
= {0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
66 const GUID KSDATAFORMAT_TYPE_AUDIO
= {0x73647561L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
67 const GUID KSDATAFORMAT_SUBTYPE_PCM
= {0x00000001L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
68 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
= {0x05589f81L
, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
69 const GUID KSDATAFORMAT_SPECIFIER_DSOUND
= {0x518590a2L
, 0xa184, 0x11d0, {0x85, 0x22, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3}};
70 const GUID KSDATAFORMAT_SUBTYPE_WAVEFORMATEX
= {0x00000000L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
71 const GUID KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF
= {0x00000092L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
74 const GUID KSAUDFNAME_WAVE_VOLUME
= {0x185FEDE5L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
75 const GUID KSAUDFNAME_WAVE_MUTE
= {0x185FEDE6L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
76 const GUID KSAUDFNAME_MIC_VOLUME
= {0x185FEDEDL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
77 const GUID KSAUDFNAME_MASTER_VOLUME
= {0x185FEDE3L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
78 const GUID KSAUDFNAME_RECORDING_SOURCE
= {0x185FEDEFL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
79 const GUID KSAUDFNAME_CD_VOLUME
= {0x185FEDE9L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
80 const GUID KSAUDFNAME_CD_IN_VOLUME
= {0x185FEDF3L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
81 const GUID KSAUDFNAME_MIC_IN_VOLUME
= {0x185FEDF5L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
82 const GUID KSAUDFNAME_MICROPHONE_BOOST
= {0x2bc31d6aL
, 0x96e3, 0x11d2, {0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68}};
83 const GUID KSAUDFNAME_CD_MUTE
= {0x185FEDEAL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
84 const GUID KSAUDFNAME_LINE_MUTE
= {0x185FEDECL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
85 const GUID KSAUDFNAME_MIC_MUTE
= {0x185FEDEEL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
86 const GUID KSAUDFNAME_AUX_MUTE
= {0x185FEDFDL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
87 const GUID KSAUDFNAME_MASTER_MUTE
= {0x185FEDE4L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
88 const GUID KSAUDFNAME_RECORDING_CONTROL
= {0x185FEDFAL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
89 const GUID KSAUDFNAME_VOLUME_CONTROL
= {0x185FEDF7L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
90 const GUID KSAUDFNAME_LINE_IN_VOLUME
= {0x185FEDF4L
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
91 const GUID KSAUDFNAME_AUX_VOLUME
= {0x185FEDFCL
, 0x9905, 0x11D1, {0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3}};
93 const GUID KSPROPSETID_CMI
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}};
96 const GUID CMINAME_IEC_5V
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF0}};
97 const GUID CMINAME_IEC_OUT
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF1}};
98 const GUID CMINAME_IEC_INVERSE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF2}};
99 const GUID CMINAME_IEC_MONITOR
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF3}};
100 const GUID CMINAME_IEC_SELECT
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF5}};
101 const GUID CMINAME_XCHG_FB
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF6}};
102 const GUID CMINAME_BASS2LINE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF7}};
103 const GUID CMINAME_CENTER2LINE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF8}};
104 const GUID CMINAME_IEC_COPYRIGHT
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF9}};
105 const GUID CMINAME_IEC_POLVALID
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFA}};
106 const GUID CMINAME_IEC_LOOP
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFB}};
107 const GUID CMINAME_REAR2LINE
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFC}};
108 const GUID CMINAME_CENTER2MIC
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFD}};
109 const GUID CMINAME_DAC
= {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF4}};
110 const GUID PRODUCT_CM8738
= {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9c}};
111 const GUID COMPONENT_CM8738
= {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9d}};
112 const GUID MANUFACTURER_CM8738
= {0x9db14e9a, 0x7be7, 0x480d, {0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9e}};
115 NTSTATUS
InstallSubdevice(
116 PDEVICE_OBJECT DeviceObject
,
120 REFGUID MiniportClassId
,
121 PFNCREATEINSTANCE MiniportCreate
,
122 PUNKNOWN UnknownAdapter
,
123 PRESOURCELIST ResourceList
,
124 REFGUID PortInterfaceId
,
125 PUNKNOWN
* OutPortUnknown
)
132 DBGPRINT(("InstallSubdevice()"));
134 ntStatus
= PcNewPort(&Port
, PortClassId
);
135 if (NT_SUCCESS(ntStatus
)) {
136 if (MiniportCreate
) {
137 ntStatus
= MiniportCreate((PUNKNOWN
*)&MiniPort
, MiniportClassId
, NULL
, NonPagedPool
);
139 ntStatus
= PcNewMiniport(&MiniPort
, MiniportClassId
);
143 if (!NT_SUCCESS(ntStatus
)) {
148 ntStatus
= Port
->Init(DeviceObject
, Irp
, MiniPort
, UnknownAdapter
, ResourceList
);
149 if (NT_SUCCESS(ntStatus
)) {
150 ntStatus
= PcRegisterSubdevice(DeviceObject
, Name
, Port
);
152 if (OutPortUnknown
&& NT_SUCCESS (ntStatus
)) {
153 ntStatus
= Port
->QueryInterface(IID_IUnknown
, (PVOID
*)OutPortUnknown
);
171 PRESOURCELIST ResourceList
,
172 PRESOURCELIST
* UartResourceList
)
177 ////ASSERT(ResourceList);
178 ////ASSERT(UartResourceList);
179 //DBGPRINT(("ProcessResources()"));
180 //DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas()));
183 (*UartResourceList
) = NULL
;
187 if ((ResourceList
->NumberOfPorts() == 0) || (ResourceList
->NumberOfPorts() > 2) || (ResourceList
->NumberOfInterrupts() != 1) || (ResourceList
->NumberOfDmas() != 0)) {
188 DBGPRINT(("Unexpected configuration"));
189 return STATUS_DEVICE_CONFIGURATION_ERROR
;
193 ntStatus
= PcNewResourceSublist(UartResourceList
, NULL
, PagedPool
, ResourceList
, 2);
194 if (NT_SUCCESS(ntStatus
)) {
195 (*UartResourceList
)->AddPortFromParent(ResourceList
, 1);
196 (*UartResourceList
)->AddInterruptFromParent(ResourceList
, 0);
200 return STATUS_SUCCESS
;
204 NTSTATUS
StartDevice(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PRESOURCELIST ResourceList
)
211 //ASSERT(DeviceObject);
213 //ASSERT(ResourceList);
214 DBGPRINT(("StartDevice()"));
217 ntStatus
= PcNewPort(&pPort
,CLSID_PortWaveCyclic
);
218 if (NT_SUCCESS(ntStatus
)) {
219 // not supported in the first edition of win98
220 PPORTEVENTS pPortEvents
= 0;
221 ntStatus
= pPort
->QueryInterface(IID_IPortEvents
, (PVOID
*)&pPortEvents
);
222 if (!NT_SUCCESS(ntStatus
)) {
223 DBGPRINT(("ERROR: This driver doesn't work under Win98!"));
224 ntStatus
= STATUS_UNSUCCESSFUL
;
228 pPortEvents
->Release();
235 // resource validation
236 PRESOURCELIST UartResourceList
= NULL
;
237 ntStatus
= ProcessResources(ResourceList
, &UartResourceList
);
238 if (!NT_SUCCESS(ntStatus
)) {
239 DBGPRINT(("ProcessResources() failed"));
243 PCMIADAPTER pCMIAdapter
= NULL
;
244 PUNKNOWN pUnknownCommon
= NULL
;
246 // create the CMIAdapter object
247 ntStatus
= NewCMIAdapter(&pUnknownCommon
, IID_ICMIAdapter
, NULL
, NonPagedPool
);
248 if (!NT_SUCCESS(ntStatus
)) {
249 DBGPRINT(("NewCMIAdapter() failed"));
253 ntStatus
= pUnknownCommon
->QueryInterface(IID_ICMIAdapter
, (PVOID
*)&pCMIAdapter
);
254 if (!NT_SUCCESS(ntStatus
)) {
255 DBGPRINT(("QueryInterface() for ICMIAdapter failed"));
258 ntStatus
= pCMIAdapter
->init(ResourceList
, DeviceObject
);
259 if (!NT_SUCCESS(ntStatus
)) {
260 DBGPRINT(("CMIAdapter->init() failed"));
264 ntStatus
= PcRegisterAdapterPowerManagement((PUNKNOWN
)pCMIAdapter
, DeviceObject
);
266 pUnknownCommon
->Release();
268 PUNKNOWN unknownWave
= NULL
;
269 PUNKNOWN unknownTopology
= NULL
;
271 // install the topology miniport.
272 ntStatus
= InstallSubdevice( DeviceObject
, Irp
, (PWCHAR
) L
"Topology",
273 CLSID_PortTopology
, CLSID_PortTopology
, CreateMiniportTopologyCMI
,
274 pCMIAdapter
, NULL
, GUID_NULL
, &unknownTopology
);
275 if (!NT_SUCCESS (ntStatus
)) {
276 DBGPRINT(("Topology miniport installation failed"));
281 // install the UART miniport - execution order important
282 ntStatus
= STATUS_UNSUCCESSFUL
;
284 for ( UINT i
=0; i
< ResourceList
->NumberOfPorts(); i
++ ) {
285 if (ResourceList
->FindTranslatedPort(i
)->u
.Port
.Length
== 2) {
286 MPUBase
= (UInt32
*)ResourceList
->FindTranslatedPort(i
)->u
.Port
.Start
.QuadPart
;
290 ntStatus
= pCMIAdapter
->activateMPU(MPUBase
);
291 if (NT_SUCCESS(ntStatus
)) {
292 ntStatus
= InstallSubdevice( DeviceObject
, Irp
, (PWCHAR
) L
"Uart",
293 CLSID_PortDMus
, CLSID_MiniportDriverDMusUART
, NULL
,
294 pCMIAdapter
->getInterruptSync(), UartResourceList
,
295 IID_IPortDMus
, NULL
);
298 if (!NT_SUCCESS(ntStatus
)) {
300 pCMIAdapter
->activateMPU(0);
301 DBGPRINT(("UART miniport installation failed"));
303 if (UartResourceList
) {
304 UartResourceList
->Release();
308 // install the wave miniport - the order matters here
310 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, (PWCHAR
) L
"Wave",
311 CLSID_PortWaveRT
, CLSID_PortWaveRT
, CreateMiniportWaveCMI
,
312 pCMIAdapter
, ResourceList
, IID_IPortWaveRT
, &unknownWave
);
314 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, (PWCHAR
) L
"Wave",
315 CLSID_PortWaveCyclic
, CLSID_PortWaveCyclic
, CreateMiniportWaveCMI
,
316 pCMIAdapter
, ResourceList
, IID_IPortWaveCyclic
, &unknownWave
);
318 if (!NT_SUCCESS(ntStatus
)) {
319 DBGPRINT(("Wave miniport installation failed"));
323 // connect wave and topology pins
324 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownWave
, PIN_WAVE_RENDER_SOURCE
, unknownTopology
, PIN_WAVEOUT_SOURCE
);
325 if (!NT_SUCCESS(ntStatus
)) {
326 DBGPRINT(("Cannot connect topology and wave miniport (render)!"));
329 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownTopology
, PIN_WAVEIN_DEST
, unknownWave
, PIN_WAVE_CAPTURE_SOURCE
);
330 if (!NT_SUCCESS(ntStatus
)) {
331 DBGPRINT(("Cannot connect topology and wave miniport (capture)!"));
334 if (!IoIsWdmVersionAvailable(6,0)) {
335 // this shit fixes the fucking XP mixer and breaks the vista mixer, so we have to check for vista here
336 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownWave
, PIN_WAVE_AC3_RENDER_SOURCE
, unknownTopology
, PIN_SPDIF_AC3_SOURCE
);
337 if (!NT_SUCCESS(ntStatus
)) {
338 DBGPRINT(("Cannot connect topology and wave miniport (ac3)!"));
344 pCMIAdapter
->Release();
346 if (unknownTopology
) {
347 unknownTopology
->Release();
350 unknownWave
->Release();
361 PDRIVER_OBJECT DriverObject
,
362 PDEVICE_OBJECT PhysicalDeviceObject
)
366 DBGPRINT(("AddDevice()"));
369 return PcAddAdapterDevice(DriverObject
, PhysicalDeviceObject
, (PCPFNSTARTDEVICE
)StartDevice
, MAX_MINIPORTS
, 0);
372 bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor
, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor
)
376 //ASSERT(pInResDescriptor);
377 //ASSERT(pOutResDescriptor);
378 DBGPRINT(("CopyResourceDescriptor()"));
379 RtlCopyMemory(pOutResDescriptor
, pInResDescriptor
, sizeof(IO_RESOURCE_DESCRIPTOR
));
381 pOutResDescriptor
->Type
= pInResDescriptor
->Type
;
382 pOutResDescriptor
->ShareDisposition
= pInResDescriptor
->ShareDisposition
;
383 pOutResDescriptor
->Flags
= pInResDescriptor
->Flags
;
384 pOutResDescriptor
->Option
= pInResDescriptor
->Option
;
386 switch (pInResDescriptor
->Type
) {
387 case CmResourceTypePort
:
388 case CmResourceTypePort
| CmResourceTypeNonArbitrated
: // huh?
390 if ((pInResDescriptor->u.Port.Length == 0) ||
391 ( (pInResDescriptor->u.Port.MinimumAddress.HighPart == pInResDescriptor->u.Port.MaximumAddress.HighPart) && (pInResDescriptor->u.Port.MinimumAddress.LowPart == pInResDescriptor->u.Port.MaximumAddress.LowPart) ) ) {
394 */ pOutResDescriptor
->u
.Port
.MinimumAddress
= pInResDescriptor
->u
.Port
.MinimumAddress
;
395 pOutResDescriptor
->u
.Port
.MaximumAddress
= pInResDescriptor
->u
.Port
.MaximumAddress
;
396 pOutResDescriptor
->u
.Port
.Length
= pInResDescriptor
->u
.Port
.Length
;
397 pOutResDescriptor
->u
.Port
.Alignment
= pInResDescriptor
->u
.Port
.Alignment
;
399 DBGPRINT((" Port: min %08x.%08x max %08x.%08x, Length: %x, Option: %x", pOutResDescriptor
->u
.Port
.MinimumAddress
.HighPart
, pOutResDescriptor
->u
.Port
.MinimumAddress
.LowPart
,
400 pOutResDescriptor
->u
.Port
.MaximumAddress
.HighPart
, pOutResDescriptor
->u
.Port
.MaximumAddress
.LowPart
,
401 pOutResDescriptor
->u
.Port
.Length
, pOutResDescriptor
->Option
));
404 case CmResourceTypeInterrupt
:
405 pOutResDescriptor
->u
.Interrupt
.MinimumVector
= pInResDescriptor
->u
.Interrupt
.MinimumVector
;
406 pOutResDescriptor
->u
.Interrupt
.MaximumVector
= pInResDescriptor
->u
.Interrupt
.MaximumVector
;
408 DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor
->u
.Interrupt
.MinimumVector
, pOutResDescriptor
->u
.Interrupt
.MaximumVector
, pOutResDescriptor
->Option
));
423 PDEVICE_OBJECT pDeviceObject
,
426 NTSTATUS ntStatus
= STATUS_SUCCESS
;
427 ULONG resourceListSize
;
428 PIO_RESOURCE_REQUIREMENTS_LIST resourceList
, list
;
429 PIO_RESOURCE_DESCRIPTOR descriptor
;
430 PIO_STACK_LOCATION pIrpStack
= IoGetCurrentIrpStackLocation(pIrp
);
433 ////ASSERT(pDeviceObject);
435 DBGPRINT(("AdapterDispatchPnp()"));
437 if (pIrpStack
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
) {
438 DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS"));
440 list
= (PIO_RESOURCE_REQUIREMENTS_LIST
)pIrp
->IoStatus
.Information
;
442 // IO_RESOURCE_REQUIREMENTS_LIST has 1 IO_RESOURCE_LIST, IO_RESOURCE_LIST has 1 IO_RESOURCE_DESCRIPTOR and we want 2 more
443 resourceListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
)*(list
->List
[0].Count
+2) ;
444 resourceList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePoolWithTag(PagedPool
, resourceListSize
, 'LRDV');
447 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
452 RtlZeroMemory(resourceList
, resourceListSize
);
454 // initialize the list header
455 resourceList
->AlternativeLists
= 1; // number of IO_RESOURCE_LISTs
456 resourceList
->ListSize
= resourceListSize
;
458 resourceList
->List
[0].Version
= 1;
459 resourceList
->List
[0].Revision
= 1;
460 resourceList
->List
[0].Count
= 0;
462 // copy the resources which have already been assigned
463 for ( UINT i
=0; i
< list
->List
[0].Count
; i
++ ) {
464 if (CopyResourceDescriptor( &list
->List
[0].Descriptors
[i
],
465 &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
] ))
467 resourceList
->List
[0].Count
++;
472 // an additional port for mpu401
473 resourceList
->List
[0].Count
++;
474 descriptor
= &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
-1];
475 descriptor
->Option
= IO_RESOURCE_PREFERRED
;
476 descriptor
->Type
= CmResourceTypePort
;
477 descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
478 descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
479 descriptor
->u
.Port
.MinimumAddress
.LowPart
= 0x300;
480 descriptor
->u
.Port
.MinimumAddress
.HighPart
= 0;
481 descriptor
->u
.Port
.MaximumAddress
.LowPart
= 0x330;
482 descriptor
->u
.Port
.MaximumAddress
.HighPart
= 0;
483 descriptor
->u
.Port
.Length
= 2;
484 descriptor
->u
.Port
.Alignment
= 0x10;
486 // mpu401 port should be optional. yes, this is severely braindamaged.
487 resourceList
->List
[0].Count
++;
488 descriptor
= &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
-1];
489 descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
490 descriptor
->Type
= CmResourceTypePort
;
491 descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
492 descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
493 descriptor
->u
.Port
.MinimumAddress
.LowPart
= 0x0;
494 descriptor
->u
.Port
.MinimumAddress
.HighPart
= 0;
495 descriptor
->u
.Port
.MaximumAddress
.LowPart
= 0xFFFF;
496 descriptor
->u
.Port
.MaximumAddress
.HighPart
= 0;
497 descriptor
->u
.Port
.Length
= 1;
498 descriptor
->u
.Port
.Alignment
= 0x10;
500 // DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count));
502 pIrp
->IoStatus
.Information
= (ULONG_PTR
)resourceList
;
504 // set the return status
505 pIrp
->IoStatus
.Status
= ntStatus
;
508 // Pass the IRPs on to PortCls
509 ntStatus
= PcDispatchIrp(pDeviceObject
, pIrp
);
519 PDRIVER_OBJECT DriverObject
,
520 PUNICODE_STRING RegistryPathName
)
524 DBGPRINT(("DriverEntry()"));
527 //bind the adapter driver to the portclass driver
528 ntStatus
= PcInitializeAdapterDriver(DriverObject
, RegistryPathName
, AddDevice
);
532 if(NT_SUCCESS(ntStatus
)) {
533 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = AdapterDispatchPnp
;
537 if (!IoIsWdmVersionAvailable(6,0)) {
538 ntStatus
= STATUS_UNSUCCESSFUL
;
549 int __cdecl
_purecall (void)
557 void __cxa_pure_virtual()
559 // put error handling here