Sync to trunk (r44371)
[reactos.git] / reactos / drivers / wdm / audio / drivers / CMIDriver / adapter.cpp
1 /*
2 Copyright (c) 2006-2007 dogbert <dogber1@gmail.com>
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27
28 #define PUT_GUIDS_HERE
29 #include <initguid.h>
30 #include "adapter.hpp"
31
32 //#pragma code_seg("PAGE")
33
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}};
56
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}};
62
63
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}};
70
71
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}};
90
91 const GUID KSPROPSETID_CMI = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}};
92
93
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}};
111
112
113 NTSTATUS InstallSubdevice(
114 PDEVICE_OBJECT DeviceObject,
115 PIRP Irp,
116 PWCHAR Name,
117 REFGUID PortClassId,
118 REFGUID MiniportClassId,
119 PFNCREATEINSTANCE MiniportCreate,
120 PUNKNOWN UnknownAdapter,
121 PRESOURCELIST ResourceList,
122 REFGUID PortInterfaceId,
123 PUNKNOWN* OutPortUnknown)
124 {
125 NTSTATUS ntStatus;
126 PPORT Port;
127 PMINIPORT MiniPort;
128
129 ////PAGED_CODE();
130 DBGPRINT(("InstallSubdevice()"));
131
132 ntStatus = PcNewPort(&Port, PortClassId);
133 if (NT_SUCCESS(ntStatus)) {
134 if (MiniportCreate) {
135 ntStatus = MiniportCreate((PUNKNOWN*)&MiniPort, MiniportClassId, NULL, NonPagedPool);
136 } else {
137 ntStatus = PcNewMiniport(&MiniPort, MiniportClassId);
138 }
139 }
140
141 if (!NT_SUCCESS(ntStatus)) {
142 Port->Release();
143 return ntStatus;
144 }
145
146 ntStatus = Port->Init(DeviceObject, Irp, MiniPort, UnknownAdapter, ResourceList);
147 if (NT_SUCCESS(ntStatus)) {
148 ntStatus = PcRegisterSubdevice(DeviceObject, Name, Port);
149
150 if (OutPortUnknown && NT_SUCCESS (ntStatus)) {
151 ntStatus = Port->QueryInterface(IID_IUnknown, (PVOID *)OutPortUnknown);
152 }
153 }
154
155 if (MiniPort) {
156 MiniPort->Release();
157 }
158
159 if (Port) {
160 Port->Release();
161 }
162
163 return ntStatus;
164 }
165
166
167 NTSTATUS
168 ProcessResources(
169 PRESOURCELIST ResourceList,
170 PRESOURCELIST* UartResourceList)
171 {
172 NTSTATUS ntStatus;
173
174 ////PAGED_CODE();
175 ////ASSERT(ResourceList);
176 ////ASSERT(UartResourceList);
177 //DBGPRINT(("ProcessResources()"));
178 //DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas()));
179
180 #ifdef UART
181 (*UartResourceList) = NULL;
182 #endif
183
184
185 if ((ResourceList->NumberOfPorts() == 0) || (ResourceList->NumberOfPorts() > 2) || (ResourceList->NumberOfInterrupts() != 1) || (ResourceList->NumberOfDmas() != 0)) {
186 DBGPRINT(("Unexpected configuration"));
187 return STATUS_DEVICE_CONFIGURATION_ERROR;
188 }
189
190 #ifdef UART
191 ntStatus = PcNewResourceSublist(UartResourceList, NULL, PagedPool, ResourceList, 2);
192 if (NT_SUCCESS(ntStatus)) {
193 (*UartResourceList)->AddPortFromParent(ResourceList, 1);
194 (*UartResourceList)->AddInterruptFromParent(ResourceList, 0);
195 }
196 #endif
197
198 return STATUS_SUCCESS;
199 }
200
201
202 NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST ResourceList)
203 {
204 NTSTATUS ntStatus;
205 PPORT pPort = 0;
206 ULONG* MPUBase;
207 #if 0
208 //PAGED_CODE();
209 //ASSERT(DeviceObject);
210 //ASSERT(Irp);
211 //ASSERT(ResourceList);
212 DBGPRINT(("StartDevice()"));
213 #endif
214
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;
223 }
224 else
225 {
226 pPortEvents->Release();
227 }
228 pPort->Release ();
229 } else {
230 return ntStatus;
231 }
232
233 // resource validation
234 PRESOURCELIST UartResourceList = NULL;
235 ntStatus = ProcessResources(ResourceList, &UartResourceList);
236 if (!NT_SUCCESS(ntStatus)) {
237 DBGPRINT(("ProcessResources() failed"));
238 return ntStatus;
239 }
240
241 PCMIADAPTER pCMIAdapter = NULL;
242 PUNKNOWN pUnknownCommon = NULL;
243
244 // create the CMIAdapter object
245 ntStatus = NewCMIAdapter(&pUnknownCommon, IID_ICMIAdapter, NULL, NonPagedPool);
246 if (!NT_SUCCESS(ntStatus)) {
247 DBGPRINT(("NewCMIAdapter() failed"));
248 return ntStatus;
249 }
250
251 ntStatus = pUnknownCommon->QueryInterface(IID_ICMIAdapter, (PVOID *)&pCMIAdapter);
252 if (!NT_SUCCESS(ntStatus)) {
253 DBGPRINT(("QueryInterface() for ICMIAdapter failed"));
254 return ntStatus;
255 }
256 ntStatus = pCMIAdapter->init(ResourceList, DeviceObject);
257 if (!NT_SUCCESS(ntStatus)) {
258 DBGPRINT(("CMIAdapter->init() failed"));
259 return ntStatus;
260 }
261
262 ntStatus = PcRegisterAdapterPowerManagement((PUNKNOWN)pCMIAdapter, DeviceObject);
263
264 pUnknownCommon->Release();
265
266 PUNKNOWN unknownWave = NULL;
267 PUNKNOWN unknownTopology = NULL;
268
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"));
273 return ntStatus;
274 }
275
276 #ifdef UART
277 // install the UART miniport - execution order important
278 ntStatus = STATUS_UNSUCCESSFUL;
279 MPUBase = 0;
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;
283 }
284 }
285 if (MPUBase != 0) {
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);
289 }
290 }
291 if (!NT_SUCCESS(ntStatus)) {
292 MPUBase = 0;
293 pCMIAdapter->activateMPU(0);
294 DBGPRINT(("UART miniport installation failed"));
295 }
296 if (UartResourceList) {
297 UartResourceList->Release();
298 }
299 #endif
300
301 // install the wave miniport - the order matters here
302 #ifdef WAVERT
303 ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveRT, CLSID_PortWaveRT, CreateMiniportWaveCMI, pCMIAdapter, ResourceList, IID_IPortWaveRT, &unknownWave);
304 #else
305 ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCMI, pCMIAdapter, ResourceList, IID_IPortWaveCyclic, &unknownWave);
306 #endif
307 if (!NT_SUCCESS(ntStatus)) {
308 DBGPRINT(("Wave miniport installation failed"));
309 return ntStatus;
310 }
311
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)!"));
316 return ntStatus;
317 }
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)!"));
321 return ntStatus;
322 }
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)!"));
328 }
329 }
330
331 // clean up
332 if (pCMIAdapter) {
333 pCMIAdapter->Release();
334 }
335 if (unknownTopology) {
336 unknownTopology->Release();
337 }
338 if (unknownWave) {
339 unknownWave->Release();
340 }
341
342 return ntStatus;
343 }
344
345 extern
346 "C"
347 NTSTATUS
348 NTAPI
349 AddDevice(
350 PDRIVER_OBJECT DriverObject,
351 PDEVICE_OBJECT PhysicalDeviceObject)
352 {
353 #if 0
354 //PAGED_CODE();
355 DBGPRINT(("AddDevice()"));
356 #endif
357
358 return PcAddAdapterDevice(DriverObject, PhysicalDeviceObject, (PCPFNSTARTDEVICE)StartDevice, MAX_MINIPORTS, 0);
359 }
360
361 bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor)
362 {
363 #if 0
364 //PAGED_CODE();
365 //ASSERT(pInResDescriptor);
366 //ASSERT(pOutResDescriptor);
367 DBGPRINT(("CopyResourceDescriptor()"));
368 RtlCopyMemory(pOutResDescriptor, pInResDescriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
369 #else
370 pOutResDescriptor->Type = pInResDescriptor->Type;
371 pOutResDescriptor->ShareDisposition = pInResDescriptor->ShareDisposition;
372 pOutResDescriptor->Flags = pInResDescriptor->Flags;
373 pOutResDescriptor->Option = pInResDescriptor->Option;
374
375 switch (pInResDescriptor->Type) {
376 case CmResourceTypePort:
377 case CmResourceTypePort | CmResourceTypeNonArbitrated: // huh?
378 /* // filter crap
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) ) ) {
381 return FALSE;
382 }
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;
387 #if 0
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));
391 #endif
392 break;
393 case CmResourceTypeInterrupt:
394 pOutResDescriptor->u.Interrupt.MinimumVector = pInResDescriptor->u.Interrupt.MinimumVector;
395 pOutResDescriptor->u.Interrupt.MaximumVector = pInResDescriptor->u.Interrupt.MaximumVector;
396 #if 0
397 DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor->u.Interrupt.MinimumVector, pOutResDescriptor->u.Interrupt.MaximumVector, pOutResDescriptor->Option));
398 #endif
399 break;
400 default:
401 return FALSE;
402 }
403 return TRUE;
404 #endif
405 }
406
407 extern
408 "C"
409 NTSTATUS
410 NTAPI
411 AdapterDispatchPnp(
412 PDEVICE_OBJECT pDeviceObject,
413 PIRP pIrp)
414 {
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);
420
421 ////PAGED_CODE();
422 ////ASSERT(pDeviceObject);
423 ////ASSERT(pIrp);
424 DBGPRINT(("AdapterDispatchPnp()"));
425
426 if (pIrpStack->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS) {
427 DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS"));
428
429 list = (PIO_RESOURCE_REQUIREMENTS_LIST)pIrp->IoStatus.Information;
430
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');
434
435 if (!resourceList) {
436 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
437 return ntStatus;
438 }
439
440
441 RtlZeroMemory(resourceList, resourceListSize);
442
443 // initialize the list header
444 resourceList->AlternativeLists = 1; // number of IO_RESOURCE_LISTs
445 resourceList->ListSize = resourceListSize;
446
447 resourceList->List[0].Version = 1;
448 resourceList->List[0].Revision = 1;
449 resourceList->List[0].Count = 0;
450
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++;
455 }
456 }
457 ExFreePool(list);
458
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;
472
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;
486
487 // DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count));
488
489 pIrp->IoStatus.Information = (ULONG_PTR)resourceList;
490
491 // set the return status
492 pIrp->IoStatus.Status = ntStatus;
493 }
494
495 // Pass the IRPs on to PortCls
496 ntStatus = PcDispatchIrp(pDeviceObject, pIrp);
497
498 return ntStatus;
499 }
500
501 extern
502 "C"
503 NTSTATUS
504 NTAPI
505 DriverEntry(
506 PDRIVER_OBJECT DriverObject,
507 PUNICODE_STRING RegistryPathName)
508 {
509 NTSTATUS ntStatus;
510
511 DBGPRINT(("DriverEntry()"));
512
513
514 //bind the adapter driver to the portclass driver
515 ntStatus = PcInitializeAdapterDriver(DriverObject, RegistryPathName, AddDevice);
516
517
518 #ifdef UART
519 if(NT_SUCCESS(ntStatus)) {
520 DriverObject->MajorFunction[IRP_MJ_PNP] = AdapterDispatchPnp;
521 }
522 #endif
523 #ifdef WAVERT
524 if (!IoIsWdmVersionAvailable(6,0)) {
525 ntStatus = STATUS_UNSUCCESSFUL;
526 }
527 #endif
528
529 return ntStatus;
530 }
531
532
533 #ifdef _MSC_VER
534
535 #pragma code_seg()
536 int __cdecl _purecall (void)
537 {
538 return 0;
539 }
540
541 #else
542
543 extern "C" {
544 void __cxa_pure_virtual()
545 {
546 // put error handling here
547
548 DbgBreakPoint();
549
550 }
551 }
552 #endif