[CMAKE]
[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 #ifdef _MSC_VER
33 //#pragma code_seg("PAGE") // GCC ignores pragma code_seg
34 #endif
35
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}};
58
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}};
64
65
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}};
72
73
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}};
92
93 const GUID KSPROPSETID_CMI = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}};
94
95
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}};
113
114
115 NTSTATUS InstallSubdevice(
116 PDEVICE_OBJECT DeviceObject,
117 PIRP Irp,
118 PWCHAR Name,
119 REFGUID PortClassId,
120 REFGUID MiniportClassId,
121 PFNCREATEINSTANCE MiniportCreate,
122 PUNKNOWN UnknownAdapter,
123 PRESOURCELIST ResourceList,
124 REFGUID PortInterfaceId,
125 PUNKNOWN* OutPortUnknown)
126 {
127 NTSTATUS ntStatus;
128 PPORT Port;
129 PMINIPORT MiniPort;
130
131 ////PAGED_CODE();
132 DBGPRINT(("InstallSubdevice()"));
133
134 ntStatus = PcNewPort(&Port, PortClassId);
135 if (NT_SUCCESS(ntStatus)) {
136 if (MiniportCreate) {
137 ntStatus = MiniportCreate((PUNKNOWN*)&MiniPort, MiniportClassId, NULL, NonPagedPool);
138 } else {
139 ntStatus = PcNewMiniport(&MiniPort, MiniportClassId);
140 }
141 }
142
143 if (!NT_SUCCESS(ntStatus)) {
144 Port->Release();
145 return ntStatus;
146 }
147
148 ntStatus = Port->Init(DeviceObject, Irp, MiniPort, UnknownAdapter, ResourceList);
149 if (NT_SUCCESS(ntStatus)) {
150 ntStatus = PcRegisterSubdevice(DeviceObject, Name, Port);
151
152 if (OutPortUnknown && NT_SUCCESS (ntStatus)) {
153 ntStatus = Port->QueryInterface(IID_IUnknown, (PVOID *)OutPortUnknown);
154 }
155 }
156
157 if (MiniPort) {
158 MiniPort->Release();
159 }
160
161 if (Port) {
162 Port->Release();
163 }
164
165 return ntStatus;
166 }
167
168
169 NTSTATUS
170 ProcessResources(
171 PRESOURCELIST ResourceList,
172 PRESOURCELIST* UartResourceList)
173 {
174 NTSTATUS ntStatus;
175
176 ////PAGED_CODE();
177 ////ASSERT(ResourceList);
178 ////ASSERT(UartResourceList);
179 //DBGPRINT(("ProcessResources()"));
180 //DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas()));
181
182 #ifdef UART
183 (*UartResourceList) = NULL;
184 #endif
185
186
187 if ((ResourceList->NumberOfPorts() == 0) || (ResourceList->NumberOfPorts() > 2) || (ResourceList->NumberOfInterrupts() != 1) || (ResourceList->NumberOfDmas() != 0)) {
188 DBGPRINT(("Unexpected configuration"));
189 return STATUS_DEVICE_CONFIGURATION_ERROR;
190 }
191
192 #ifdef UART
193 ntStatus = PcNewResourceSublist(UartResourceList, NULL, PagedPool, ResourceList, 2);
194 if (NT_SUCCESS(ntStatus)) {
195 (*UartResourceList)->AddPortFromParent(ResourceList, 1);
196 (*UartResourceList)->AddInterruptFromParent(ResourceList, 0);
197 }
198 #endif
199
200 return STATUS_SUCCESS;
201 }
202
203
204 NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST ResourceList)
205 {
206 NTSTATUS ntStatus;
207 PPORT pPort = 0;
208 ULONG* MPUBase;
209 #if 0
210 //PAGED_CODE();
211 //ASSERT(DeviceObject);
212 //ASSERT(Irp);
213 //ASSERT(ResourceList);
214 DBGPRINT(("StartDevice()"));
215 #endif
216
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;
225 }
226 else
227 {
228 pPortEvents->Release();
229 }
230 pPort->Release ();
231 } else {
232 return ntStatus;
233 }
234
235 // resource validation
236 PRESOURCELIST UartResourceList = NULL;
237 ntStatus = ProcessResources(ResourceList, &UartResourceList);
238 if (!NT_SUCCESS(ntStatus)) {
239 DBGPRINT(("ProcessResources() failed"));
240 return ntStatus;
241 }
242
243 PCMIADAPTER pCMIAdapter = NULL;
244 PUNKNOWN pUnknownCommon = NULL;
245
246 // create the CMIAdapter object
247 ntStatus = NewCMIAdapter(&pUnknownCommon, IID_ICMIAdapter, NULL, NonPagedPool);
248 if (!NT_SUCCESS(ntStatus)) {
249 DBGPRINT(("NewCMIAdapter() failed"));
250 return ntStatus;
251 }
252
253 ntStatus = pUnknownCommon->QueryInterface(IID_ICMIAdapter, (PVOID *)&pCMIAdapter);
254 if (!NT_SUCCESS(ntStatus)) {
255 DBGPRINT(("QueryInterface() for ICMIAdapter failed"));
256 return ntStatus;
257 }
258 ntStatus = pCMIAdapter->init(ResourceList, DeviceObject);
259 if (!NT_SUCCESS(ntStatus)) {
260 DBGPRINT(("CMIAdapter->init() failed"));
261 return ntStatus;
262 }
263
264 ntStatus = PcRegisterAdapterPowerManagement((PUNKNOWN)pCMIAdapter, DeviceObject);
265
266 pUnknownCommon->Release();
267
268 PUNKNOWN unknownWave = NULL;
269 PUNKNOWN unknownTopology = NULL;
270
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"));
277 return ntStatus;
278 }
279
280 #ifdef UART
281 // install the UART miniport - execution order important
282 ntStatus = STATUS_UNSUCCESSFUL;
283 MPUBase = 0;
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;
287 }
288 }
289 if (MPUBase != 0) {
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 );
296 }
297 }
298 if (!NT_SUCCESS(ntStatus)) {
299 MPUBase = 0;
300 pCMIAdapter->activateMPU(0);
301 DBGPRINT(("UART miniport installation failed"));
302 }
303 if (UartResourceList) {
304 UartResourceList->Release();
305 }
306 #endif
307
308 // install the wave miniport - the order matters here
309 #ifdef WAVERT
310 ntStatus = InstallSubdevice(DeviceObject, Irp, (PWCHAR) L"Wave",
311 CLSID_PortWaveRT, CLSID_PortWaveRT, CreateMiniportWaveCMI,
312 pCMIAdapter, ResourceList, IID_IPortWaveRT, &unknownWave );
313 #else
314 ntStatus = InstallSubdevice(DeviceObject, Irp, (PWCHAR) L"Wave",
315 CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCMI,
316 pCMIAdapter, ResourceList, IID_IPortWaveCyclic, &unknownWave );
317 #endif
318 if (!NT_SUCCESS(ntStatus)) {
319 DBGPRINT(("Wave miniport installation failed"));
320 return ntStatus;
321 }
322
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)!"));
327 return ntStatus;
328 }
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)!"));
332 return ntStatus;
333 }
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)!"));
339 }
340 }
341
342 // clean up
343 if (pCMIAdapter) {
344 pCMIAdapter->Release();
345 }
346 if (unknownTopology) {
347 unknownTopology->Release();
348 }
349 if (unknownWave) {
350 unknownWave->Release();
351 }
352
353 return ntStatus;
354 }
355
356 extern
357 "C"
358 NTSTATUS
359 NTAPI
360 AddDevice(
361 PDRIVER_OBJECT DriverObject,
362 PDEVICE_OBJECT PhysicalDeviceObject)
363 {
364 #if 0
365 //PAGED_CODE();
366 DBGPRINT(("AddDevice()"));
367 #endif
368
369 return PcAddAdapterDevice(DriverObject, PhysicalDeviceObject, (PCPFNSTARTDEVICE)StartDevice, MAX_MINIPORTS, 0);
370 }
371
372 bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor)
373 {
374 #if 0
375 //PAGED_CODE();
376 //ASSERT(pInResDescriptor);
377 //ASSERT(pOutResDescriptor);
378 DBGPRINT(("CopyResourceDescriptor()"));
379 RtlCopyMemory(pOutResDescriptor, pInResDescriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
380 #else
381 pOutResDescriptor->Type = pInResDescriptor->Type;
382 pOutResDescriptor->ShareDisposition = pInResDescriptor->ShareDisposition;
383 pOutResDescriptor->Flags = pInResDescriptor->Flags;
384 pOutResDescriptor->Option = pInResDescriptor->Option;
385
386 switch (pInResDescriptor->Type) {
387 case CmResourceTypePort:
388 case CmResourceTypePort | CmResourceTypeNonArbitrated: // huh?
389 /* // filter crap
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) ) ) {
392 return FALSE;
393 }
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;
398 #if 0
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));
402 #endif
403 break;
404 case CmResourceTypeInterrupt:
405 pOutResDescriptor->u.Interrupt.MinimumVector = pInResDescriptor->u.Interrupt.MinimumVector;
406 pOutResDescriptor->u.Interrupt.MaximumVector = pInResDescriptor->u.Interrupt.MaximumVector;
407 #if 0
408 DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor->u.Interrupt.MinimumVector, pOutResDescriptor->u.Interrupt.MaximumVector, pOutResDescriptor->Option));
409 #endif
410 break;
411 default:
412 return FALSE;
413 }
414 return TRUE;
415 #endif
416 }
417
418 extern
419 "C"
420 NTSTATUS
421 NTAPI
422 AdapterDispatchPnp(
423 PDEVICE_OBJECT pDeviceObject,
424 PIRP pIrp)
425 {
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);
431
432 ////PAGED_CODE();
433 ////ASSERT(pDeviceObject);
434 ////ASSERT(pIrp);
435 DBGPRINT(("AdapterDispatchPnp()"));
436
437 if (pIrpStack->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS) {
438 DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS"));
439
440 list = (PIO_RESOURCE_REQUIREMENTS_LIST)pIrp->IoStatus.Information;
441
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');
445
446 if (!resourceList) {
447 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
448 return ntStatus;
449 }
450
451
452 RtlZeroMemory(resourceList, resourceListSize);
453
454 // initialize the list header
455 resourceList->AlternativeLists = 1; // number of IO_RESOURCE_LISTs
456 resourceList->ListSize = resourceListSize;
457
458 resourceList->List[0].Version = 1;
459 resourceList->List[0].Revision = 1;
460 resourceList->List[0].Count = 0;
461
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] ))
466 {
467 resourceList->List[0].Count++;
468 }
469 }
470 ExFreePool(list);
471
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;
485
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;
499
500 // DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count));
501
502 pIrp->IoStatus.Information = (ULONG_PTR)resourceList;
503
504 // set the return status
505 pIrp->IoStatus.Status = ntStatus;
506 }
507
508 // Pass the IRPs on to PortCls
509 ntStatus = PcDispatchIrp(pDeviceObject, pIrp);
510
511 return ntStatus;
512 }
513
514 extern
515 "C"
516 NTSTATUS
517 NTAPI
518 DriverEntry(
519 PDRIVER_OBJECT DriverObject,
520 PUNICODE_STRING RegistryPathName)
521 {
522 NTSTATUS ntStatus;
523
524 DBGPRINT(("DriverEntry()"));
525
526
527 //bind the adapter driver to the portclass driver
528 ntStatus = PcInitializeAdapterDriver(DriverObject, RegistryPathName, AddDevice);
529
530
531 #ifdef UART
532 if(NT_SUCCESS(ntStatus)) {
533 DriverObject->MajorFunction[IRP_MJ_PNP] = AdapterDispatchPnp;
534 }
535 #endif
536 #ifdef WAVERT
537 if (!IoIsWdmVersionAvailable(6,0)) {
538 ntStatus = STATUS_UNSUCCESSFUL;
539 }
540 #endif
541
542 return ntStatus;
543 }
544
545
546 #ifdef _MSC_VER
547
548 #pragma code_seg()
549 int __cdecl _purecall (void)
550 {
551 return 0;
552 }
553
554 #else
555
556 extern "C" {
557 void __cxa_pure_virtual()
558 {
559 // put error handling here
560
561 DbgBreakPoint();
562
563 }
564 }
565 #endif