Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

524 lines
16 KiB

  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 name that is printed in debug output messages
  9. //
  10. static char STR_MODULENAME[] = "ICH Adapter: ";
  11. //
  12. // All the GUIDs from portcls and your own defined GUIDs end up in this object.
  13. //
  14. #define PUT_GUIDS_HERE
  15. //
  16. // We want the global debug variables here.
  17. //
  18. #define DEFINE_DEBUG_VARS
  19. #include "adapter.h"
  20. #pragma code_seg("PAGE")
  21. /*****************************************************************************
  22. * InstallSubdevice
  23. *****************************************************************************
  24. * This function creates and registers a subdevice consisting of a port
  25. * driver, a minport driver and a set of resources bound together. It will
  26. * also optionally place a pointer to an interface on the port driver in a
  27. * specified location before initializing the port driver. This is done so
  28. * that a common ISR can have access to the port driver during initialization,
  29. * when the ISR might fire.
  30. * This function is internally used and validates no parameters.
  31. */
  32. NTSTATUS InstallSubdevice
  33. (
  34. IN PDEVICE_OBJECT DeviceObject,
  35. IN PIRP Irp,
  36. IN PWCHAR Name,
  37. IN REFGUID PortClassId,
  38. IN REFGUID MiniportClassId,
  39. IN PFNCREATEINSTANCE MiniportCreate OPTIONAL,
  40. IN PUNKNOWN UnknownAdapter OPTIONAL,
  41. IN PRESOURCELIST ResourceList,
  42. IN REFGUID PortInterfaceId,
  43. OUT PMINIPORT * OutMiniport OPTIONAL,
  44. OUT PUNKNOWN * OutPortUnknown OPTIONAL
  45. )
  46. {
  47. PAGED_CODE ();
  48. NTSTATUS ntStatus;
  49. PPORT port;
  50. PMINIPORT miniport;
  51. DOUT (DBG_PRINT, ("[InstallSubdevice]"));
  52. //
  53. // Create the port driver object
  54. //
  55. ntStatus = PcNewPort (&port,PortClassId);
  56. //
  57. // return immediately in case of an error
  58. //
  59. if (!NT_SUCCESS (ntStatus))
  60. return ntStatus;
  61. //
  62. // Create the miniport object
  63. //
  64. if (MiniportCreate)
  65. {
  66. ntStatus = MiniportCreate ((PUNKNOWN*)&miniport, MiniportClassId,
  67. NULL, NonPagedPool);
  68. }
  69. else
  70. {
  71. ntStatus = PcNewMiniport (&miniport,MiniportClassId);
  72. }
  73. //
  74. // return immediately in case of an error
  75. //
  76. if (!NT_SUCCESS (ntStatus))
  77. {
  78. port->Release ();
  79. return ntStatus;
  80. }
  81. //
  82. // Init the port driver and miniport in one go.
  83. //
  84. ntStatus = port->Init (DeviceObject, Irp, miniport, UnknownAdapter,
  85. ResourceList);
  86. if (NT_SUCCESS (ntStatus))
  87. {
  88. //
  89. // Register the subdevice (port/miniport combination).
  90. //
  91. ntStatus = PcRegisterSubdevice (DeviceObject, Name, port);
  92. //
  93. // Deposit the port as an unknown if it's needed.
  94. //
  95. if (OutPortUnknown && NT_SUCCESS (ntStatus))
  96. {
  97. ntStatus = port->QueryInterface (IID_IUnknown,
  98. (PVOID *)OutPortUnknown);
  99. }
  100. //
  101. // Deposit the miniport as an IMiniport if it's needed.
  102. //
  103. if ( OutMiniport && NT_SUCCESS (ntStatus) )
  104. {
  105. ntStatus = miniport->QueryInterface (IID_IMiniport,
  106. (PVOID *)OutMiniport);
  107. }
  108. }
  109. //
  110. // Release the reference for the port and miniport. This is the right
  111. // thing to do, regardless of the outcome.
  112. //
  113. miniport->Release ();
  114. port->Release ();
  115. return ntStatus;
  116. }
  117. /*****************************************************************************
  118. * ValidateResources
  119. *****************************************************************************
  120. * This function validates the list of resources for the various functions on
  121. * the card. This code is specific to the adapter.
  122. * This function doesn't check the ResourceList parameter and returns
  123. * STATUS_SUCCESS when the resources are valid.
  124. */
  125. NTSTATUS ValidateResources
  126. (
  127. IN PRESOURCELIST ResourceList // All resources.
  128. )
  129. {
  130. PAGED_CODE ();
  131. DOUT (DBG_PRINT, ("[ValidateResources]"));
  132. //
  133. // Get counts for the types of resources.
  134. //
  135. ULONG countIO = ResourceList->NumberOfPorts ();
  136. ULONG countIRQ = ResourceList->NumberOfInterrupts ();
  137. ULONG countDMA = ResourceList->NumberOfDmas ();
  138. // validate resources
  139. if ((countIO != 2) || (countIRQ != 1) || (countDMA != 0))
  140. {
  141. DOUT (DBG_ERROR, ("Unknown configuration:\n"
  142. " IO count: %d\n"
  143. " IRQ count: %d\n"
  144. " DMA count: %d",
  145. countIO, countIRQ, countDMA));
  146. return STATUS_DEVICE_CONFIGURATION_ERROR;
  147. }
  148. return STATUS_SUCCESS;
  149. }
  150. /*****************************************************************************
  151. * StartDevice
  152. *****************************************************************************
  153. * This function is called by the operating system when the device is started.
  154. * It is responsible for starting the miniports. This code is specific to
  155. * the adapter because it calls out miniports for functions that are specific
  156. * to the adapter.
  157. */
  158. NTSTATUS StartDevice
  159. (
  160. IN PDEVICE_OBJECT DeviceObject, // Device object.
  161. IN PIRP Irp, // IO request packet.
  162. IN PRESOURCELIST ResourceList // List of hardware resources.
  163. )
  164. {
  165. PAGED_CODE ();
  166. ASSERT (DeviceObject);
  167. ASSERT (Irp);
  168. ASSERT (ResourceList);
  169. NTSTATUS ntStatus;
  170. DOUT (DBG_PRINT, ("[StartDevice]"));
  171. //
  172. // Determine which version of the OS we are running under. We don't want
  173. // to run under Win98G.
  174. //
  175. // create a wave cyclic port
  176. PPORT pPort = 0;
  177. ntStatus = PcNewPort (&pPort,CLSID_PortWaveCyclic);
  178. // check error code
  179. if (NT_SUCCESS (ntStatus))
  180. {
  181. // query for the event interface which is not supported in Win98 gold.
  182. PPORTEVENTS pPortEvents = 0;
  183. ntStatus = pPort->QueryInterface (IID_IPortEvents,
  184. (PVOID *)&pPortEvents);
  185. if (!NT_SUCCESS (ntStatus))
  186. {
  187. DOUT (DBG_ERROR, ("This driver is not for Win98 Gold!"));
  188. ntStatus = STATUS_UNSUCCESSFUL; // change error code.
  189. }
  190. else
  191. {
  192. pPortEvents->Release ();
  193. }
  194. pPort->Release ();
  195. }
  196. // now return in case it was Win98 Gold.
  197. if (!NT_SUCCESS (ntStatus))
  198. return ntStatus;
  199. //
  200. // Validate the resources.
  201. // We don't have to split the resources into several resource lists cause
  202. // the topology miniport doesn't need a resource list, the wave pci miniport
  203. // needs all resources like the adapter common object.
  204. //
  205. ntStatus = ValidateResources (ResourceList);
  206. //
  207. // return immediately in case of an error
  208. //
  209. if (!NT_SUCCESS (ntStatus))
  210. return ntStatus;
  211. //
  212. // If the adapter has the right resources...
  213. //
  214. PADAPTERCOMMON pAdapterCommon = NULL;
  215. PUNKNOWN pUnknownCommon;
  216. // create a new adapter common object
  217. ntStatus = NewAdapterCommon (&pUnknownCommon, IID_IAdapterCommon,
  218. NULL, NonPagedPool);
  219. if (NT_SUCCESS (ntStatus))
  220. {
  221. // query for the IAdapterCommon interface
  222. ntStatus = pUnknownCommon->QueryInterface (IID_IAdapterCommon,
  223. (PVOID *)&pAdapterCommon);
  224. if (NT_SUCCESS (ntStatus))
  225. {
  226. // Initialize the object
  227. ntStatus = pAdapterCommon->Init (ResourceList, DeviceObject);
  228. if (NT_SUCCESS (ntStatus))
  229. {
  230. // register with PortCls for power-management services
  231. ntStatus = PcRegisterAdapterPowerManagement ((PUNKNOWN)pAdapterCommon,
  232. DeviceObject);
  233. }
  234. }
  235. // release the IID_IAdapterCommon on adapter common
  236. pUnknownCommon->Release ();
  237. }
  238. // print error message.
  239. if (!NT_SUCCESS (ntStatus))
  240. {
  241. DOUT (DBG_ERROR, ("Could not create or query AdapterCommon."));
  242. }
  243. //
  244. // These are the port driver pointers we are keeping around for registering
  245. // physical connections.
  246. //
  247. PMINIPORT miniWave = NULL;
  248. PMINIPORT miniTopology = NULL;
  249. PUNKNOWN unknownWave = NULL;
  250. PUNKNOWN unknownTopology = NULL;
  251. PMINIPORTTOPOLOGYICH pMiniportTopologyICH = NULL;
  252. //
  253. // Start the topology miniport.
  254. //
  255. if (NT_SUCCESS (ntStatus))
  256. {
  257. ntStatus = InstallSubdevice (DeviceObject,
  258. Irp,
  259. L"Topology",
  260. CLSID_PortTopology,
  261. CLSID_PortTopology, // not used
  262. CreateMiniportTopologyICH,
  263. pAdapterCommon,
  264. NULL,
  265. GUID_NULL,
  266. &miniTopology,
  267. &unknownTopology);
  268. if (NT_SUCCESS (ntStatus))
  269. {
  270. // query for the IMiniportTopologyICH interface
  271. ntStatus = miniTopology->QueryInterface (IID_IMiniportTopologyICH,
  272. (PVOID *)&pMiniportTopologyICH);
  273. miniTopology->Release ();
  274. miniTopology = NULL;
  275. }
  276. // print error message.
  277. if (!NT_SUCCESS (ntStatus))
  278. {
  279. DOUT (DBG_ERROR, ("Could not create or query TopologyICH"));
  280. }
  281. }
  282. //
  283. // Start the wave miniport.
  284. //
  285. if (NT_SUCCESS (ntStatus))
  286. {
  287. ntStatus = InstallSubdevice (DeviceObject,
  288. Irp,
  289. L"Wave",
  290. CLSID_PortWavePci,
  291. CLSID_PortWavePci, // not used
  292. CreateMiniportWaveICH,
  293. pAdapterCommon,
  294. ResourceList,
  295. IID_IPortWavePci,
  296. NULL,
  297. &unknownWave);
  298. // print error message.
  299. if (!NT_SUCCESS (ntStatus))
  300. {
  301. DOUT (DBG_ERROR, ("WavePCI miniport installation failed!"));
  302. }
  303. }
  304. //
  305. // Establish physical connections between filters as shown.
  306. //
  307. // +------+ +------+
  308. // | Wave | | Topo |
  309. // Capture <---|2 3|<===|x |<--- CD
  310. // | | | |
  311. // Render --->|0 1|===>|y |<--- Line In
  312. // | | | |
  313. // Mic <---|4 5|<===|z |<--- Mic
  314. // +------+ | |
  315. // | |---> Line Out
  316. // +------+
  317. //
  318. // Note that the pin numbers for the nodes to be connected
  319. // vary depending on the hardware/codec configuration.
  320. // Also, the mic input may or may not be present.
  321. //
  322. // So,
  323. // Do a QI on unknownTopology to get an interface to call
  324. // a method on to get the topology miniport pin IDs.
  325. if (NT_SUCCESS (ntStatus))
  326. {
  327. ULONG ulWaveOut, ulWaveIn, ulMicIn;
  328. // get the pin numbers.
  329. DOUT (DBG_PRINT, ("Connecting topo and wave."));
  330. ntStatus = pMiniportTopologyICH->GetPhysicalConnectionPins (&ulWaveOut,
  331. &ulWaveIn, &ulMicIn);
  332. // register wave render connection
  333. if (NT_SUCCESS (ntStatus))
  334. {
  335. ntStatus = PcRegisterPhysicalConnection (DeviceObject,
  336. unknownWave,
  337. PIN_WAVEOUT_BRIDGE,
  338. unknownTopology,
  339. ulWaveOut);
  340. // print error message.
  341. if (!NT_SUCCESS (ntStatus))
  342. {
  343. DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
  344. " (render)!"));
  345. }
  346. }
  347. if (NT_SUCCESS (ntStatus))
  348. {
  349. // register wave capture connection
  350. ntStatus = PcRegisterPhysicalConnection (DeviceObject,
  351. unknownTopology,
  352. ulWaveIn,
  353. unknownWave,
  354. PIN_WAVEIN_BRIDGE);
  355. // print error message.
  356. if (!NT_SUCCESS (ntStatus))
  357. {
  358. DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
  359. " (capture)!"));
  360. }
  361. }
  362. if (NT_SUCCESS (ntStatus))
  363. {
  364. // register mic capture connection
  365. if (pAdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
  366. {
  367. ntStatus = PcRegisterPhysicalConnection (DeviceObject,
  368. unknownTopology,
  369. ulMicIn,
  370. unknownWave,
  371. PIN_MICIN_BRIDGE);
  372. // print error message.
  373. if (!NT_SUCCESS (ntStatus))
  374. {
  375. DOUT (DBG_ERROR, ("Cannot connect topology and wave miniport"
  376. " (MIC)!"));
  377. }
  378. }
  379. }
  380. }
  381. //
  382. // Release the adapter common object. It either has other references,
  383. // or we need to delete it anyway.
  384. //
  385. if (pAdapterCommon)
  386. pAdapterCommon->Release ();
  387. //
  388. // Release the unknowns.
  389. //
  390. if (unknownTopology)
  391. unknownTopology->Release ();
  392. if (unknownWave)
  393. unknownWave->Release ();
  394. // and the ICH miniport.
  395. if (pMiniportTopologyICH)
  396. pMiniportTopologyICH->Release ();
  397. return ntStatus; // whatever this is ...
  398. }
  399. /*****************************************************************************
  400. * AddDevice
  401. *****************************************************************************
  402. * This function is called by the operating system when the device is added.
  403. * All adapter drivers can use this code without change.
  404. */
  405. extern "C" NTSTATUS AddDevice
  406. (
  407. IN PDRIVER_OBJECT DriverObject,
  408. IN PDEVICE_OBJECT PhysicalDeviceObject
  409. )
  410. {
  411. PAGED_CODE ();
  412. DOUT (DBG_PRINT, ("[AddDevice]"));
  413. //
  414. // Tell portcls (the class driver) to add the device.
  415. //
  416. return PcAddAdapterDevice (DriverObject,
  417. PhysicalDeviceObject,
  418. (PCPFNSTARTDEVICE)StartDevice,
  419. MAX_MINIPORTS,
  420. 0);
  421. }
  422. /*****************************************************************************
  423. * DriverEntry
  424. *****************************************************************************
  425. * This function is called by the operating system when the driver is loaded.
  426. * All adapter drivers can use this code without change.
  427. */
  428. extern "C" NTSTATUS DriverEntry
  429. (
  430. IN PDRIVER_OBJECT DriverObject,
  431. IN PUNICODE_STRING RegistryPathName
  432. )
  433. {
  434. PAGED_CODE ();
  435. DOUT (DBG_PRINT, ("[DriverEntry]"));
  436. //
  437. // Tell the class driver to initialize the driver.
  438. //
  439. NTSTATUS RetValue = PcInitializeAdapterDriver (DriverObject,
  440. RegistryPathName,
  441. AddDevice);
  442. return RetValue;
  443. }
  444. #pragma code_seg()
  445. /*****************************************************************************
  446. * _purecall()
  447. *****************************************************************************
  448. * The C++ compiler loves me.
  449. */
  450. int __cdecl _purecall (void)
  451. {
  452. ASSERT (!"Pure virtual function called");
  453. return 0;
  454. }