ReactOS 0.4.15-dev-7842-g558ab78
adapter.cpp
Go to the documentation of this file.
1/********************************************************************************
2** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
3**
4** Portions Copyright (c) 1998-1999 Intel Corporation
5**
6********************************************************************************/
7
8/* The file adapter.cpp was reviewed by LCA in June 2011 and is acceptable for use by Microsoft. */
9
10//
11// The name that is printed in debug output messages
12//
13#define STR_MODULENAME "AC97 Adapter: "
14
15//
16// All the GUIDs from portcls and your own defined GUIDs end up in this object.
17//
18#define PUT_GUIDS_HERE
19
20//
21// We want the global debug variables here.
22//
23#define DEFINE_DEBUG_VARS
24
25#include "adapter.h"
26
27
28/*****************************************************************************
29 * Referenced forward
30 */
31DRIVER_ADD_DEVICE AddDevice;
32
33#ifdef _MSC_VER
34#pragma code_seg("PAGE")
35#endif
36/*****************************************************************************
37 * InstallSubdevice
38 *****************************************************************************
39 * This function creates and registers a subdevice consisting of a port
40 * driver, a minport driver and a set of resources bound together. It will
41 * also optionally place a pointer to an interface on the port driver in a
42 * specified location before initializing the port driver. This is done so
43 * that a common ISR can have access to the port driver during initialization,
44 * when the ISR might fire.
45 * This function is internally used and validates no parameters.
46 */
48(
52 _In_ REFGUID PortClassId,
53 _In_ REFGUID MiniportClassId,
54 _In_opt_ PFNCREATEMINIPORT MiniportCreate,
55 _In_opt_ PUNKNOWN UnknownAdapter,
57 _In_opt_ REFGUID PortInterfaceId,
58 _Out_opt_ PMINIPORT * OutMiniport,
59 _Out_opt_ PUNKNOWN * OutPortUnknown
60)
61{
62 PAGED_CODE ();
63
64 NTSTATUS ntStatus;
65 PPORT port;
66 PMINIPORT miniport;
67
68 DOUT (DBG_PRINT, ("[InstallSubdevice]"));
69
70#ifndef __REACTOS__
71 UNREFERENCED_PARAMETER(PortInterfaceId);
72#endif
73
74 //
75 // Create the port driver object
76 //
77 ntStatus = PcNewPort (&port,PortClassId);
78
79 //
80 // return immediately in case of an error
81 //
82 if (!NT_SUCCESS (ntStatus))
83 return ntStatus;
84
85 //
86 // Create the miniport object
87 //
88 if (MiniportCreate)
89 {
90 ntStatus = MiniportCreate ((PUNKNOWN*)&miniport, MiniportClassId,
92 }
93 else
94 {
95 ntStatus = PcNewMiniport (&miniport,MiniportClassId);
96 }
97
98 //
99 // return immediately in case of an error
100 //
101 if (!NT_SUCCESS (ntStatus))
102 {
103 port->Release ();
104 return ntStatus;
105 }
106
107 //
108 // Init the port driver and miniport in one go.
109 //
110#ifdef _MSC_VER
111#pragma warning(push)
112#endif
113 // IPort::Init's annotation on ResourceList requires it to be non-NULL. However,
114 // for dynamic devices, we may no longer have the resource list and this should
115 // still succeed.
116 //
117#ifdef _MSC_VER
118#pragma warning(disable:6387)
119#endif
120 ntStatus = port->Init (DeviceObject, Irp, miniport, UnknownAdapter,
122#ifdef _MSC_VER
123#pragma warning(pop)
124#endif
125
126 if (NT_SUCCESS (ntStatus))
127 {
128 //
129 // Register the subdevice (port/miniport combination).
130 //
132
133 //
134 // Deposit the port as an unknown if it's needed.
135 //
136 if (OutPortUnknown && NT_SUCCESS (ntStatus))
137 {
138 ntStatus = port->QueryInterface (IID_IUnknown,
139 (PVOID *)OutPortUnknown);
140 }
141
142 //
143 // Deposit the miniport as an IMiniport if it's needed.
144 //
145 if ( OutMiniport && NT_SUCCESS (ntStatus) )
146 {
147 ntStatus = miniport->QueryInterface (IID_IMiniport,
148 (PVOID *)OutMiniport);
149 }
150 }
151
152 //
153 // Release the reference for the port and miniport. This is the right
154 // thing to do, regardless of the outcome.
155 //
156 miniport->Release ();
157 port->Release ();
158
159
160 return ntStatus;
161}
162
163
164/*****************************************************************************
165 * ValidateResources
166 *****************************************************************************
167 * This function validates the list of resources for the various functions on
168 * the card. This code is specific to the adapter.
169 * This function doesn't check the ResourceList parameter and returns
170 * STATUS_SUCCESS when the resources are valid.
171 */
173(
174 IN PRESOURCELIST ResourceList // All resources.
175)
176{
177 PAGED_CODE ();
178
179 DOUT (DBG_PRINT, ("[ValidateResources]"));
180
181 //
182 // Get counts for the types of resources.
183 //
184 ULONG countIO = ResourceList->NumberOfPorts ();
185 ULONG countIRQ = ResourceList->NumberOfInterrupts ();
186 ULONG countDMA = ResourceList->NumberOfDmas ();
187
188 // validate resources
189 if ((countIO != 2) || (countIRQ != 1) || (countDMA != 0))
190 {
191 DOUT (DBG_ERROR, ("Unknown configuration:\n"
192 " IO count: %d\n"
193 " IRQ count: %d\n"
194 " DMA count: %d",
195 countIO, countIRQ, countDMA));
197 }
198
199 return STATUS_SUCCESS;
200}
201
202/*****************************************************************************
203 * StartDevice
204 *****************************************************************************
205 * This function is called by the operating system when the device is started.
206 * It is responsible for starting the miniports. This code is specific to
207 * the adapter because it calls out miniports for functions that are specific
208 * to the adapter.
209 */
211(
212 IN PDEVICE_OBJECT DeviceObject, // Device object.
213 IN PIRP Irp, // IO request packet.
214 IN PRESOURCELIST ResourceList // List of hardware resources.
215)
216{
217 PAGED_CODE ();
218
220 ASSERT (Irp);
222
223 NTSTATUS ntStatus;
224
225 DOUT (DBG_PRINT, ("[StartDevice]"));
226
227 //
228 // Determine which version of the OS we are running under. We don't want
229 // to run under Win98G.
230 //
231
232 // create a wave cyclic port
233 PPORT pPort = 0;
234 ntStatus = PcNewPort (&pPort,CLSID_PortWaveCyclic);
235
236 // check error code
237 if (NT_SUCCESS (ntStatus))
238 {
239 // query for the event interface which is not supported in Win98 gold.
240 PPORTEVENTS pPortEvents = 0;
241 ntStatus = pPort->QueryInterface (IID_IPortEvents,
242 (PVOID *)&pPortEvents);
243 if (!NT_SUCCESS (ntStatus))
244 {
245 DOUT (DBG_ERROR, ("This driver is not for Win98 Gold!"));
246 ntStatus = STATUS_UNSUCCESSFUL; // change error code.
247 }
248 else
249 {
250 pPortEvents->Release ();
251 }
252 pPort->Release ();
253 }
254
255 // now return in case it was Win98 Gold.
256 if (!NT_SUCCESS (ntStatus))
257 return ntStatus;
258
259 //
260 // Validate the resources.
261 // We don't have to split the resources into several resource lists cause
262 // the topology miniport doesn't need a resource list, the wave pci miniport
263 // needs all resources like the adapter common object.
264 //
265 ntStatus = ValidateResources (ResourceList);
266
267 //
268 // return immediately in case of an error
269 //
270 if (!NT_SUCCESS (ntStatus))
271 return ntStatus;
272
273 //
274 // If the adapter has the right resources...
275 //
276 PADAPTERCOMMON pAdapterCommon = NULL;
277 PUNKNOWN pUnknownCommon;
278
279 // create a new adapter common object
280 ntStatus = NewAdapterCommon (&pUnknownCommon, IID_IAC97AdapterCommon,
282
283 if (NT_SUCCESS (ntStatus))
284 {
285 // query for the IAC97AdapterCommon interface
286 ntStatus = pUnknownCommon->QueryInterface (IID_IAC97AdapterCommon,
287 (PVOID *)&pAdapterCommon);
288 if (NT_SUCCESS (ntStatus))
289 {
290 // Initialize the object
291 ntStatus = pAdapterCommon->Init (ResourceList, DeviceObject);
292
293 if (NT_SUCCESS (ntStatus))
294 {
295 // register with PortCls for power-management services
296 ntStatus = PcRegisterAdapterPowerManagement ((PUNKNOWN)pAdapterCommon,
298 }
299 }
300
301 // release the IID_IAC97AdapterCommon on adapter common
302 pUnknownCommon->Release ();
303 }
304
305 // print error message.
306 if (!NT_SUCCESS (ntStatus))
307 {
308 DOUT (DBG_ERROR, ("Could not create or query AdapterCommon."));
309 }
310
311 //
312 // These are the port driver pointers we are keeping around for registering
313 // physical connections.
314 //
315 PMINIPORT miniTopology = NULL;
316 PUNKNOWN unknownWave = NULL;
317 PUNKNOWN unknownTopology = NULL;
318 PAC97MINIPORTTOPOLOGY pMiniportTopology = NULL;
319
320 //
321 // Start the topology miniport.
322 //
323 if (NT_SUCCESS (ntStatus))
324 {
325 ntStatus = InstallSubdevice (DeviceObject,
326 Irp,
327 L"Topology",
328 CLSID_PortTopology,
329 CLSID_PortTopology, // not used
331 pAdapterCommon,
332 NULL,
333 GUID_NULL,
334 &miniTopology,
335 &unknownTopology);
336
337 if (NT_SUCCESS (ntStatus))
338 {
339 // query for the IAC97MiniportTopology interface
340 ntStatus = miniTopology->QueryInterface (IID_IAC97MiniportTopology,
341 (PVOID *)&pMiniportTopology);
342 miniTopology->Release ();
343 miniTopology = NULL;
344 }
345
346 // print error message.
347 if (!NT_SUCCESS (ntStatus))
348 {
349 DOUT (DBG_ERROR, ("Could not create or query TopologyICH"));
350 }
351 }
352
353 //
354 // Start the wave miniport.
355 //
356 if (NT_SUCCESS (ntStatus))
357 {
358#if (NTDDI_VERSION >= NTDDI_VISTA)
359 ntStatus = InstallSubdevice (DeviceObject,
360 Irp,
361 L"Wave",
362 CLSID_PortWaveRT,
363 CLSID_PortWaveRT, // not used
365 pAdapterCommon,
367 IID_IPortWaveRT,
368 NULL,
369 &unknownWave);
370
371 if (!NT_SUCCESS (ntStatus))
372 {
373#endif
374 //
375 // If creation of the RT port failed we can fall back to the WavePCI
376 // or WaveCyc port of portcls. In this case, we try the WavePCI port.
377 //
378#if 1
379 ntStatus = InstallSubdevice (DeviceObject,
380 Irp,
381 L"Wave",
382 CLSID_PortWaveCyclic,
383 CLSID_PortWaveCyclic, // not used
385 pAdapterCommon,
387 IID_IPortWaveCyclic,
388 NULL,
389 &unknownWave);
390#else
391 ntStatus = InstallSubdevice (DeviceObject,
392 Irp,
393 L"Wave",
394 CLSID_PortWavePci,
395 CLSID_PortWavePci, // not used
397 pAdapterCommon,
399 IID_IPortWavePci,
400 NULL,
401 &unknownWave);
402#endif
403
404
405#if (NTDDI_VERSION >= NTDDI_VISTA)
406 }
407#endif
408 // print error message.
409 if (!NT_SUCCESS (ntStatus))
410 {
411 DOUT (DBG_ERROR, ("WaveRT and WavePCI miniport installation failed!"));
412 }
413 }
414
415 //
416 // Establish physical connections between filters as shown.
417 //
418 // +------+ +------+
419 // | Wave | | Topo |
420 // Capture <---|2 3|<===|x |<--- CD
421 // | | | |
422 // Render --->|0 1|===>|y |<--- Line In
423 // | | | |
424 // Mic <---|4 5|<===|z |<--- Mic
425 // +------+ | |
426 // | |---> Line Out
427 // +------+
428 //
429 // Note that the pin numbers for the nodes to be connected
430 // vary depending on the hardware/codec configuration.
431 // Also, the mic input may or may not be present.
432 //
433 // So,
434 // Do a QI on unknownTopology to get an interface to call
435 // a method on to get the topology miniport pin IDs.
436
437 if (NT_SUCCESS (ntStatus))
438 {
439 ULONG ulWaveOut, ulWaveIn, ulMicIn;
440
441 // get the pin numbers.
442 DOUT (DBG_PRINT, ("Connecting topo and wave."));
443 ntStatus = pMiniportTopology->GetPhysicalConnectionPins (&ulWaveOut,
444 &ulWaveIn, &ulMicIn);
445
446 // register wave render connection
447 if (NT_SUCCESS (ntStatus))
448 {
450 unknownWave,
452 unknownTopology,
453 ulWaveOut);
454 // print error message.
455 if (!NT_SUCCESS (ntStatus))
456 {
457 DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
458 " (render)!"));
459 }
460 }
461
462
463 if (NT_SUCCESS (ntStatus))
464 {
465 // register wave capture connection
467 unknownTopology,
468 ulWaveIn,
469 unknownWave,
471 // print error message.
472 if (!NT_SUCCESS (ntStatus))
473 {
474 DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
475 " (capture)!"));
476 }
477 }
478
479 if (NT_SUCCESS (ntStatus))
480 {
481 // register mic capture connection
482 if (pAdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
483 {
485 unknownTopology,
486 ulMicIn,
487 unknownWave,
489 // print error message.
490 if (!NT_SUCCESS (ntStatus))
491 {
492 DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
493 " (MIC)!"));
494 }
495 }
496 }
497 }
498
499 //
500 // Release the adapter common object. It either has other references,
501 // or we need to delete it anyway.
502 //
503 if (pAdapterCommon)
504 pAdapterCommon->Release ();
505
506 //
507 // Release the unknowns.
508 //
509 if (unknownTopology)
510 unknownTopology->Release ();
511 if (unknownWave)
512 unknownWave->Release ();
513
514 // and the AC97 miniport.
515 if (pMiniportTopology)
516 pMiniportTopology->Release ();
517
518
519 return ntStatus; // whatever this is ...
520}
521
522/*****************************************************************************
523 * AddDevice
524 *****************************************************************************
525 * This function is called by the operating system when the device is added.
526 * All adapter drivers can use this code without change.
527 */
528// disable prefast warning 28152 because
529// DO_DEVICE_INITIALIZING is cleared in PcAddAdapterDevice
530#ifdef _MSC_VER
531#pragma warning(disable:28152)
532#endif
534(
537)
538{
539 PAGED_CODE ();
540
541 DOUT (DBG_PRINT, ("[AddDevice]"));
542
543
544 //
545 // Tell portcls (the class driver) to add the device.
546 //
551 0);
552}
553
554/*****************************************************************************
555 * DriverEntry
556 *****************************************************************************
557 * This function is called by the operating system when the driver is loaded.
558 * All adapter drivers can use this code without change.
559 */
560extern "C" DRIVER_INITIALIZE DriverEntry;
562(
564 IN PUNICODE_STRING RegistryPathName
565)
566{
567 PAGED_CODE ();
568
569 DOUT (DBG_PRINT, ("[DriverEntry]"));
570
571 //
572 // Tell the class driver to initialize the driver.
573 //
575 RegistryPathName,
577
578
579 return RetValue;
580}
581
582
583
#define PAGED_CODE()
NTSTATUS NewAdapterCommon(OUT PUNKNOWN *Unknown, IN REFCLSID, IN PUNKNOWN UnknownOuter OPTIONAL, _When_((PoolType &NonPagedPoolMustSucceed) !=0, __drv_reportError("Must succeed pool allocations are forbidden. " "Allocation failures cause a system crash")) IN POOL_TYPE PoolType)
Definition: common.cpp:117
NTSTATUS NTAPI PcAddAdapterDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject, IN PCPFNSTARTDEVICE StartDevice, IN ULONG MaxObjects, IN ULONG DeviceExtensionSize)
Definition: adapter.cpp:73
NTSTATUS NTAPI PcInitializeAdapterDriver(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPathName, IN PDRIVER_ADD_DEVICE AddDevice)
Definition: adapter.cpp:29
NTSTATUS NTAPI PcRegisterSubdevice(IN PDEVICE_OBJECT DeviceObject, IN PWCHAR Name, IN PUNKNOWN Unknown)
Definition: adapter.cpp:206
NTSTATUS NTAPI PcNewMiniport(OUT PMINIPORT *OutMiniport, IN REFCLSID ClassId)
Definition: miniport.cpp:45
LONG NTSTATUS
Definition: precomp.h:26
const GUID IID_IUnknown
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
NTSTATUS NTAPI PcRegisterPhysicalConnection(IN PDEVICE_OBJECT DeviceObject, IN PUNKNOWN FromUnknown, IN ULONG FromPin, IN PUNKNOWN ToUnknown, IN ULONG ToPin)
Definition: connection.cpp:259
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
USHORT port
Definition: uri.c:228
DRIVER_INITIALIZE DriverEntry
Definition: adapter.cpp:560
NTSTATUS InstallSubdevice(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PWSTR Name, _In_ REFGUID PortClassId, _In_ REFGUID MiniportClassId, _In_opt_ PFNCREATEMINIPORT MiniportCreate, _In_opt_ PUNKNOWN UnknownAdapter, _In_opt_ PRESOURCELIST ResourceList, _In_opt_ REFGUID PortInterfaceId, _Out_opt_ PMINIPORT *OutMiniport, _Out_opt_ PUNKNOWN *OutPortUnknown)
Definition: adapter.cpp:48
NTSTATUS ValidateResources(IN PRESOURCELIST ResourceList)
Definition: adapter.cpp:173
#define MAX_MINIPORTS
Definition: adapter.cpp:13
NTSTATUS NTAPI PcRegisterAdapterPowerManagement(IN PUNKNOWN pUnknown, IN PVOID pvContext)
Definition: power.cpp:16
NTSTATUS CreateAC97MiniportTopology(OUT PUNKNOWN *Unknown, IN REFCLSID, IN PUNKNOWN UnknownOuter OPTIONAL, IN POOL_TYPE PoolType)
NTSTATUS CreateAC97MiniportWaveCyclic(OUT PUNKNOWN *Unknown, IN REFCLSID, IN PUNKNOWN UnknownOuter OPTIONAL, IN POOL_TYPE PoolType)
NTSTATUS CreateAC97MiniportWaveRT(OUT PUNKNOWN *Unknown, IN REFCLSID, IN PUNKNOWN UnknownOuter OPTIONAL, IN POOL_TYPE PoolType)
NTSTATUS CreateAC97MiniportWavePCI(OUT PUNKNOWN *Unknown, IN REFCLSID, IN PUNKNOWN UnknownOuter OPTIONAL, IN POOL_TYPE PoolType)
HRESULT(* PFNCREATEMINIPORT)(OUT PUNKNOWN *Unknown, IN REFCLSID ClassId, IN PUNKNOWN OuterUnknown OPTIONAL, IN POOL_TYPE PoolType)
Definition: adapter.h:28
#define DOUT(lvl, strings)
Definition: debug.h:82
#define GZCALL
Definition: shared.h:46
@ PIN_WAVEOUT_BRIDGE
Definition: shared.h:319
@ PIN_WAVEIN_BRIDGE
Definition: shared.h:321
@ PIN_MICIN_BRIDGE
Definition: shared.h:323
@ PINC_MICIN_PRESENT
Definition: shared.h:70
IAC97MiniportTopology * PAC97MINIPORTTOPOLOGY
Definition: shared.h:380
IAC97AdapterCommon * PADAPTERCOMMON
Definition: shared.h:488
#define NonPagedPool
Definition: env_spec_w32.h:307
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
ULONG Release()
#define GUID_NULL
Definition: ks.h:106
#define ASSERT(a)
Definition: mode.c:44
#define _Out_opt_
Definition: ms_sal.h:346
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
static BOOL StartDevice(IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DevInfoData OPTIONAL, IN BOOL bEnable, IN DWORD HardwareProfile OPTIONAL, OUT BOOL *bNeedReboot OPTIONAL)
Definition: wizard.c:173
#define DBG_ERROR
Definition: nfs41_debug.h:78
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:619
#define L(x)
Definition: ntvdm.h:50
DRIVER_ADD_DEVICE AddDevice
Definition: parport.h:72
NTSTATUS NTAPI PcNewPort(OUT PPORT *OutPort, IN REFCLSID ClassId)
Definition: port.cpp:17
IResourceList * PRESOURCELIST
Definition: portcls.h:442
IPortEvents * PPORTEVENTS
Definition: portcls.h:2121
NTSTATUS(NTAPI * PCPFNSTARTDEVICE)(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PRESOURCELIST ResourceList)
Definition: portcls.h:2304
IPort * PPORT
Definition: portcls.h:1105
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: scsiwmi.h:51
uint16_t * PWSTR
Definition: typedefs.h:56
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFIORESREQLIST _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFIORESLIST * ResourceList
Definition: wdfresource.h:309
#define DBG_PRINT(ppi, ch, level)
Definition: win32kdebug.h:168
DRIVER_ADD_DEVICE * PDRIVER_ADD_DEVICE
Definition: iotypes.h:2216