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")
35 NTSTATUS
InstallSubdevice(
36 PDEVICE_OBJECT DeviceObject
,
40 REFGUID MiniportClassId
,
41 PFNCREATEINSTANCE MiniportCreate
,
42 PUNKNOWN UnknownAdapter
,
43 PRESOURCELIST ResourceList
,
44 REFGUID PortInterfaceId
,
45 PUNKNOWN
* OutPortUnknown
)
52 DBGPRINT(("InstallSubdevice()"));
54 ntStatus
= PcNewPort(&Port
, PortClassId
);
55 if (NT_SUCCESS(ntStatus
)) {
57 ntStatus
= MiniportCreate((PUNKNOWN
*)&MiniPort
, MiniportClassId
, NULL
, NonPagedPool
);
59 ntStatus
= PcNewMiniport(&MiniPort
, MiniportClassId
);
63 if (!NT_SUCCESS(ntStatus
)) {
68 ntStatus
= Port
->Init(DeviceObject
, Irp
, MiniPort
, UnknownAdapter
, ResourceList
);
69 if (NT_SUCCESS(ntStatus
)) {
70 ntStatus
= PcRegisterSubdevice(DeviceObject
, Name
, Port
);
72 if (OutPortUnknown
&& NT_SUCCESS (ntStatus
)) {
73 ntStatus
= Port
->QueryInterface(IID_IUnknown
, (PVOID
*)OutPortUnknown
);
91 PRESOURCELIST ResourceList
,
92 PRESOURCELIST
* UartResourceList
)
97 ////ASSERT(ResourceList);
98 ////ASSERT(UartResourceList);
99 //DBGPRINT(("ProcessResources()"));
100 //DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas()));
103 (*UartResourceList
) = NULL
;
107 if ((ResourceList
->NumberOfPorts() == 0) || (ResourceList
->NumberOfPorts() > 2) || (ResourceList
->NumberOfInterrupts() != 1) || (ResourceList
->NumberOfDmas() != 0)) {
108 DBGPRINT(("Unexpected configuration"));
109 return STATUS_DEVICE_CONFIGURATION_ERROR
;
113 ntStatus
= PcNewResourceSublist(UartResourceList
, NULL
, PagedPool
, ResourceList
, 2);
114 if (NT_SUCCESS(ntStatus
)) {
115 (*UartResourceList
)->AddPortFromParent(ResourceList
, 1);
116 (*UartResourceList
)->AddInterruptFromParent(ResourceList
, 0);
120 return STATUS_SUCCESS
;
124 NTSTATUS
StartDevice(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PRESOURCELIST ResourceList
)
131 //ASSERT(DeviceObject);
133 //ASSERT(ResourceList);
134 DBGPRINT(("StartDevice()"));
137 ntStatus
= PcNewPort(&pPort
,CLSID_PortWaveCyclic
);
138 if (NT_SUCCESS(ntStatus
)) {
139 // not supported in the first edition of win98
140 PPORTEVENTS pPortEvents
= 0;
141 ntStatus
= pPort
->QueryInterface(IID_IPortEvents
, (PVOID
*)&pPortEvents
);
142 if (!NT_SUCCESS(ntStatus
)) {
143 DBGPRINT(("ERROR: This driver doesn't work under Win98!"));
144 ntStatus
= STATUS_UNSUCCESSFUL
;
148 pPortEvents
->Release();
155 // resource validation
156 PRESOURCELIST UartResourceList
= NULL
;
157 ntStatus
= ProcessResources(ResourceList
, &UartResourceList
);
158 if (!NT_SUCCESS(ntStatus
)) {
159 DBGPRINT(("ProcessResources() failed"));
163 PCMIADAPTER pCMIAdapter
= NULL
;
164 PUNKNOWN pUnknownCommon
= NULL
;
166 // create the CMIAdapter object
167 ntStatus
= NewCMIAdapter(&pUnknownCommon
, IID_ICMIAdapter
, NULL
, NonPagedPool
);
168 if (!NT_SUCCESS(ntStatus
)) {
169 DBGPRINT(("NewCMIAdapter() failed"));
173 ntStatus
= pUnknownCommon
->QueryInterface(IID_ICMIAdapter
, (PVOID
*)&pCMIAdapter
);
174 if (!NT_SUCCESS(ntStatus
)) {
175 DBGPRINT(("QueryInterface() for ICMIAdapter failed"));
178 ntStatus
= pCMIAdapter
->init(ResourceList
, DeviceObject
);
179 if (!NT_SUCCESS(ntStatus
)) {
180 DBGPRINT(("CMIAdapter->init() failed"));
184 ntStatus
= PcRegisterAdapterPowerManagement((PUNKNOWN
)pCMIAdapter
, DeviceObject
);
186 pUnknownCommon
->Release();
188 PUNKNOWN unknownWave
= NULL
;
189 PUNKNOWN unknownTopology
= NULL
;
191 // install the topology miniport.
192 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Topology", CLSID_PortTopology
, CLSID_PortTopology
, CreateMiniportTopologyCMI
, pCMIAdapter
, NULL
, GUID_NULL
, &unknownTopology
);
193 if (!NT_SUCCESS (ntStatus
)) {
194 DBGPRINT(("Topology miniport installation failed"));
199 // install the UART miniport - execution order important
200 ntStatus
= STATUS_UNSUCCESSFUL
;
202 for (int i
=0;i
<ResourceList
->NumberOfPorts();i
++) {
203 if (ResourceList
->FindTranslatedPort(i
)->u
.Port
.Length
== 2) {
204 MPUBase
= (UInt32
*)ResourceList
->FindTranslatedPort(i
)->u
.Port
.Start
.QuadPart
;
208 ntStatus
= pCMIAdapter
->activateMPU(MPUBase
);
209 if (NT_SUCCESS(ntStatus
)) {
210 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Uart", CLSID_PortDMus
, CLSID_MiniportDriverDMusUART
, NULL
, pCMIAdapter
->getInterruptSync(), UartResourceList
, IID_IPortDMus
, NULL
);
213 if (!NT_SUCCESS(ntStatus
)) {
215 pCMIAdapter
->activateMPU(0);
216 DBGPRINT(("UART miniport installation failed"));
218 if (UartResourceList
) {
219 UartResourceList
->Release();
223 // install the wave miniport - the order matters here
225 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Wave", CLSID_PortWaveRT
, CLSID_PortWaveRT
, CreateMiniportWaveCMI
, pCMIAdapter
, ResourceList
, IID_IPortWaveRT
, &unknownWave
);
227 ntStatus
= InstallSubdevice(DeviceObject
, Irp
, L
"Wave", CLSID_PortWaveCyclic
, CLSID_PortWaveCyclic
, CreateMiniportWaveCMI
, pCMIAdapter
, ResourceList
, IID_IPortWaveCyclic
, &unknownWave
);
229 if (!NT_SUCCESS(ntStatus
)) {
230 DBGPRINT(("Wave miniport installation failed"));
234 // connect wave and topology pins
235 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownWave
, PIN_WAVE_RENDER_SOURCE
, unknownTopology
, PIN_WAVEOUT_SOURCE
);
236 if (!NT_SUCCESS(ntStatus
)) {
237 DBGPRINT(("Cannot connect topology and wave miniport (render)!"));
240 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownTopology
, PIN_WAVEIN_DEST
, unknownWave
, PIN_WAVE_CAPTURE_SOURCE
);
241 if (!NT_SUCCESS(ntStatus
)) {
242 DBGPRINT(("Cannot connect topology and wave miniport (capture)!"));
245 if (!IoIsWdmVersionAvailable(6,0)) {
246 // this shit fixes the fucking XP mixer and breaks the vista mixer, so we have to check for vista here
247 ntStatus
= PcRegisterPhysicalConnection(DeviceObject
, unknownWave
, PIN_WAVE_AC3_RENDER_SOURCE
, unknownTopology
, PIN_SPDIF_AC3_SOURCE
);
248 if (!NT_SUCCESS(ntStatus
)) {
249 DBGPRINT(("Cannot connect topology and wave miniport (ac3)!"));
255 pCMIAdapter
->Release();
257 if (unknownTopology
) {
258 unknownTopology
->Release();
261 unknownWave
->Release();
272 PDRIVER_OBJECT DriverObject
,
273 PDEVICE_OBJECT PhysicalDeviceObject
)
277 DBGPRINT(("AddDevice()"));
280 return PcAddAdapterDevice(DriverObject
, PhysicalDeviceObject
, (PCPFNSTARTDEVICE
)StartDevice
, MAX_MINIPORTS
, 0);
283 bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor
, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor
)
287 //ASSERT(pInResDescriptor);
288 //ASSERT(pOutResDescriptor);
289 DBGPRINT(("CopyResourceDescriptor()"));
290 RtlCopyMemory(pOutResDescriptor
, pInResDescriptor
, sizeof(IO_RESOURCE_DESCRIPTOR
));
292 pOutResDescriptor
->Type
= pInResDescriptor
->Type
;
293 pOutResDescriptor
->ShareDisposition
= pInResDescriptor
->ShareDisposition
;
294 pOutResDescriptor
->Flags
= pInResDescriptor
->Flags
;
295 pOutResDescriptor
->Option
= pInResDescriptor
->Option
;
297 switch (pInResDescriptor
->Type
) {
298 case CmResourceTypePort
:
299 case CmResourceTypePort
| CmResourceTypeNonArbitrated
: // huh?
301 if ((pInResDescriptor->u.Port.Length == 0) ||
302 ( (pInResDescriptor->u.Port.MinimumAddress.HighPart == pInResDescriptor->u.Port.MaximumAddress.HighPart) && (pInResDescriptor->u.Port.MinimumAddress.LowPart == pInResDescriptor->u.Port.MaximumAddress.LowPart) ) ) {
305 */ pOutResDescriptor
->u
.Port
.MinimumAddress
= pInResDescriptor
->u
.Port
.MinimumAddress
;
306 pOutResDescriptor
->u
.Port
.MaximumAddress
= pInResDescriptor
->u
.Port
.MaximumAddress
;
307 pOutResDescriptor
->u
.Port
.Length
= pInResDescriptor
->u
.Port
.Length
;
308 pOutResDescriptor
->u
.Port
.Alignment
= pInResDescriptor
->u
.Port
.Alignment
;
310 DBGPRINT((" Port: min %08x.%08x max %08x.%08x, Length: %x, Option: %x", pOutResDescriptor
->u
.Port
.MinimumAddress
.HighPart
, pOutResDescriptor
->u
.Port
.MinimumAddress
.LowPart
,
311 pOutResDescriptor
->u
.Port
.MaximumAddress
.HighPart
, pOutResDescriptor
->u
.Port
.MaximumAddress
.LowPart
,
312 pOutResDescriptor
->u
.Port
.Length
, pOutResDescriptor
->Option
));
315 case CmResourceTypeInterrupt
:
316 pOutResDescriptor
->u
.Interrupt
.MinimumVector
= pInResDescriptor
->u
.Interrupt
.MinimumVector
;
317 pOutResDescriptor
->u
.Interrupt
.MaximumVector
= pInResDescriptor
->u
.Interrupt
.MaximumVector
;
319 DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor
->u
.Interrupt
.MinimumVector
, pOutResDescriptor
->u
.Interrupt
.MaximumVector
, pOutResDescriptor
->Option
));
334 PDEVICE_OBJECT pDeviceObject
,
337 NTSTATUS ntStatus
= STATUS_SUCCESS
;
338 ULONG resourceListSize
;
339 PIO_RESOURCE_REQUIREMENTS_LIST resourceList
, list
;
340 PIO_RESOURCE_DESCRIPTOR descriptor
;
341 PIO_STACK_LOCATION pIrpStack
= IoGetCurrentIrpStackLocation(pIrp
);
344 ////ASSERT(pDeviceObject);
346 DBGPRINT(("AdapterDispatchPnp()"));
348 if (pIrpStack
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
) {
349 DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS"));
351 list
= (PIO_RESOURCE_REQUIREMENTS_LIST
)pIrp
->IoStatus
.Information
;
353 // IO_RESOURCE_REQUIREMENTS_LIST has 1 IO_RESOURCE_LIST, IO_RESOURCE_LIST has 1 IO_RESOURCE_DESCRIPTOR and we want 2 more
354 resourceListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
) + sizeof(IO_RESOURCE_DESCRIPTOR
)*(list
->List
[0].Count
+2) ;
355 resourceList
= (PIO_RESOURCE_REQUIREMENTS_LIST
)ExAllocatePoolWithTag(PagedPool
, resourceListSize
, 'LRDV');
358 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
363 RtlZeroMemory(resourceList
, resourceListSize
);
365 // initialize the list header
366 resourceList
->AlternativeLists
= 1; // number of IO_RESOURCE_LISTs
367 resourceList
->ListSize
= resourceListSize
;
369 resourceList
->List
[0].Version
= 1;
370 resourceList
->List
[0].Revision
= 1;
371 resourceList
->List
[0].Count
= 0;
373 // copy the resources which have already been assigned
374 for (int i
=0;i
<list
->List
[0].Count
;i
++) {
375 if (CopyResourceDescriptor(&list
->List
[0].Descriptors
[i
], &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
])) {
376 resourceList
->List
[0].Count
++;
381 // an additional port for mpu401
382 resourceList
->List
[0].Count
++;
383 descriptor
= &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
-1];
384 descriptor
->Option
= IO_RESOURCE_PREFERRED
;
385 descriptor
->Type
= CmResourceTypePort
;
386 descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
387 descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
388 descriptor
->u
.Port
.MinimumAddress
.LowPart
= 0x300;
389 descriptor
->u
.Port
.MinimumAddress
.HighPart
= 0;
390 descriptor
->u
.Port
.MaximumAddress
.LowPart
= 0x330;
391 descriptor
->u
.Port
.MaximumAddress
.HighPart
= 0;
392 descriptor
->u
.Port
.Length
= 2;
393 descriptor
->u
.Port
.Alignment
= 0x10;
395 // mpu401 port should be optional. yes, this is severely braindamaged.
396 resourceList
->List
[0].Count
++;
397 descriptor
= &resourceList
->List
[0].Descriptors
[resourceList
->List
[0].Count
-1];
398 descriptor
->Option
= IO_RESOURCE_ALTERNATIVE
;
399 descriptor
->Type
= CmResourceTypePort
;
400 descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
401 descriptor
->Flags
= CM_RESOURCE_PORT_IO
;
402 descriptor
->u
.Port
.MinimumAddress
.LowPart
= 0x0;
403 descriptor
->u
.Port
.MinimumAddress
.HighPart
= 0;
404 descriptor
->u
.Port
.MaximumAddress
.LowPart
= 0xFFFF;
405 descriptor
->u
.Port
.MaximumAddress
.HighPart
= 0;
406 descriptor
->u
.Port
.Length
= 1;
407 descriptor
->u
.Port
.Alignment
= 0x10;
409 // DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count));
411 pIrp
->IoStatus
.Information
= (ULONG_PTR
)resourceList
;
413 // set the return status
414 pIrp
->IoStatus
.Status
= ntStatus
;
417 // Pass the IRPs on to PortCls
418 ntStatus
= PcDispatchIrp(pDeviceObject
, pIrp
);
428 PDRIVER_OBJECT DriverObject
,
429 PUNICODE_STRING RegistryPathName
)
433 DBGPRINT(("DriverEntry()"));
436 //bind the adapter driver to the portclass driver
437 ntStatus
= PcInitializeAdapterDriver(DriverObject
, RegistryPathName
, AddDevice
);
441 if(NT_SUCCESS(ntStatus
)) {
442 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = AdapterDispatchPnp
;
446 if (!IoIsWdmVersionAvailable(6,0)) {
447 ntStatus
= STATUS_UNSUCCESSFUL
;
455 int __cdecl
_purecall (void)