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.

1072 lines
30 KiB

  1. /*****************************************************************************
  2. * adapter.cpp - SB16 adapter driver implementation.
  3. *****************************************************************************
  4. * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
  5. *
  6. * This files does setup and resource allocation/verification for the SB16
  7. * card. It controls which miniports are started and which resources are
  8. * given to each miniport. It also deals with interrupt sharing between
  9. * miniports by hooking the interrupt and calling the correct DPC.
  10. */
  11. //
  12. // All the GUIDS for all the miniports end up in this object.
  13. //
  14. #define PUT_GUIDS_HERE
  15. #define STR_MODULENAME "sb16Adapter: "
  16. #include "common.h"
  17. /*****************************************************************************
  18. * Defines
  19. */
  20. #define MAX_MINIPORTS 5
  21. #if (DBG)
  22. #define SUCCEEDS(s) ASSERT(NT_SUCCESS(s))
  23. #else
  24. #define SUCCEEDS(s) (s)
  25. #endif
  26. /*****************************************************************************
  27. * Externals
  28. */
  29. NTSTATUS
  30. CreateMiniportWaveCyclicSB16
  31. (
  32. OUT PUNKNOWN * Unknown,
  33. IN REFCLSID,
  34. IN PUNKNOWN UnknownOuter OPTIONAL,
  35. IN POOL_TYPE PoolType
  36. );
  37. NTSTATUS
  38. CreateMiniportTopologySB16
  39. (
  40. OUT PUNKNOWN * Unknown,
  41. IN REFCLSID,
  42. IN PUNKNOWN UnknownOuter OPTIONAL,
  43. IN POOL_TYPE PoolType
  44. );
  45. /*****************************************************************************
  46. * Referenced forward
  47. */
  48. extern "C"
  49. NTSTATUS
  50. AddDevice
  51. (
  52. IN PDRIVER_OBJECT DriverObject,
  53. IN PDEVICE_OBJECT PhysicalDeviceObject
  54. );
  55. NTSTATUS
  56. StartDevice
  57. (
  58. IN PDEVICE_OBJECT DeviceObject, // Device object.
  59. IN PIRP Irp, // IO request packet.
  60. IN PRESOURCELIST ResourceList // List of hardware resources.
  61. );
  62. NTSTATUS
  63. AssignResources
  64. (
  65. IN PRESOURCELIST ResourceList, // All resources.
  66. OUT PRESOURCELIST * ResourceListWave, // Wave resources.
  67. OUT PRESOURCELIST * ResourceListWaveTable, // Wave table resources.
  68. OUT PRESOURCELIST * ResourceListFmSynth, // FM synth resources.
  69. OUT PRESOURCELIST * ResourceListUart, // UART resources.
  70. OUT PRESOURCELIST * ResourceListAdapter // a copy needed by the adapter
  71. );
  72. #ifdef DO_RESOURCE_FILTERING
  73. extern "C"
  74. NTSTATUS
  75. AdapterDispatchPnp
  76. (
  77. IN PDEVICE_OBJECT pDeviceObject,
  78. IN PIRP pIrp
  79. );
  80. #endif
  81. DWORD DeterminePlatform(PPORTTOPOLOGY Port);
  82. #pragma code_seg("INIT")
  83. /*****************************************************************************
  84. * DriverEntry()
  85. *****************************************************************************
  86. * This function is called by the operating system when the driver is loaded.
  87. * All adapter drivers can use this code without change.
  88. */
  89. extern "C"
  90. NTSTATUS
  91. DriverEntry
  92. (
  93. IN PDRIVER_OBJECT DriverObject,
  94. IN PUNICODE_STRING RegistryPathName
  95. )
  96. {
  97. PAGED_CODE();
  98. //
  99. // Tell the class driver to initialize the driver.
  100. //
  101. NTSTATUS ntStatus = PcInitializeAdapterDriver( DriverObject,
  102. RegistryPathName,
  103. AddDevice );
  104. #ifdef DO_RESOURCE_FILTERING
  105. //
  106. // We want to do resource filtering, so we'll install our own PnP IRP handler.
  107. //
  108. if(NT_SUCCESS(ntStatus))
  109. {
  110. DriverObject->MajorFunction[IRP_MJ_PNP] = AdapterDispatchPnp;
  111. }
  112. #endif
  113. return ntStatus;
  114. }
  115. #pragma code_seg("PAGE")
  116. /*****************************************************************************
  117. * AddDevice()
  118. *****************************************************************************
  119. * This function is called by the operating system when the device is added.
  120. * All adapter drivers can use this code without change.
  121. */
  122. extern "C"
  123. NTSTATUS
  124. AddDevice
  125. (
  126. IN PDRIVER_OBJECT DriverObject,
  127. IN PDEVICE_OBJECT PhysicalDeviceObject
  128. )
  129. {
  130. PAGED_CODE();
  131. //
  132. // Tell the class driver to add the device.
  133. //
  134. return PcAddAdapterDevice( DriverObject,
  135. PhysicalDeviceObject,
  136. PCPFNSTARTDEVICE( StartDevice ),
  137. MAX_MINIPORTS,
  138. 0 );
  139. }
  140. /*****************************************************************************
  141. * InstallSubdevice()
  142. *****************************************************************************
  143. * This function creates and registers a subdevice consisting of a port
  144. * driver, a minport driver and a set of resources bound together. It will
  145. * also optionally place a pointer to an interface on the port driver in a
  146. * specified location before initializing the port driver. This is done so
  147. * that a common ISR can have access to the port driver during initialization,
  148. * when the ISR might fire.
  149. */
  150. NTSTATUS
  151. InstallSubdevice
  152. (
  153. IN PDEVICE_OBJECT DeviceObject,
  154. IN PIRP Irp,
  155. IN PWCHAR Name,
  156. IN REFGUID PortClassId,
  157. IN REFGUID MiniportClassId,
  158. IN PFNCREATEINSTANCE MiniportCreate OPTIONAL,
  159. IN PUNKNOWN UnknownAdapter OPTIONAL,
  160. IN PRESOURCELIST ResourceList,
  161. IN REFGUID PortInterfaceId,
  162. OUT PUNKNOWN * OutPortInterface OPTIONAL,
  163. OUT PUNKNOWN * OutPortUnknown OPTIONAL
  164. )
  165. {
  166. PAGED_CODE();
  167. _DbgPrintF(DEBUGLVL_VERBOSE, ("InstallSubdevice"));
  168. ASSERT(DeviceObject);
  169. ASSERT(Irp);
  170. ASSERT(Name);
  171. //
  172. // Create the port driver object
  173. //
  174. PPORT port;
  175. NTSTATUS ntStatus = PcNewPort(&port,PortClassId);
  176. if (NT_SUCCESS(ntStatus))
  177. {
  178. //
  179. // Deposit the port somewhere if it's needed.
  180. //
  181. if (OutPortInterface)
  182. {
  183. //
  184. // Failure here doesn't cause the entire routine to fail.
  185. //
  186. (void) port->QueryInterface
  187. (
  188. PortInterfaceId,
  189. (PVOID *) OutPortInterface
  190. );
  191. }
  192. PUNKNOWN miniport;
  193. //
  194. // Create the miniport object
  195. //
  196. if (MiniportCreate)
  197. {
  198. ntStatus = MiniportCreate
  199. (
  200. &miniport,
  201. MiniportClassId,
  202. NULL,
  203. NonPagedPool
  204. );
  205. }
  206. else
  207. {
  208. ntStatus = PcNewMiniport((PMINIPORT*) &miniport,MiniportClassId);
  209. }
  210. if (NT_SUCCESS(ntStatus))
  211. {
  212. //
  213. // Init the port driver and miniport in one go.
  214. //
  215. ntStatus = port->Init( DeviceObject,
  216. Irp,
  217. miniport,
  218. UnknownAdapter,
  219. ResourceList );
  220. if (NT_SUCCESS(ntStatus))
  221. {
  222. //
  223. // Register the subdevice (port/miniport combination).
  224. //
  225. ntStatus = PcRegisterSubdevice( DeviceObject,
  226. Name,
  227. port );
  228. if (!(NT_SUCCESS(ntStatus)))
  229. {
  230. _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: PcRegisterSubdevice failed"));
  231. }
  232. }
  233. else
  234. {
  235. _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: port->Init failed"));
  236. }
  237. //
  238. // We don't need the miniport any more. Either the port has it,
  239. // or we've failed, and it should be deleted.
  240. //
  241. miniport->Release();
  242. }
  243. else
  244. {
  245. _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: PcNewMiniport failed"));
  246. }
  247. if (NT_SUCCESS(ntStatus))
  248. {
  249. //
  250. // Deposit the port as an unknown if it's needed.
  251. //
  252. if (OutPortUnknown)
  253. {
  254. //
  255. // Failure here doesn't cause the entire routine to fail.
  256. //
  257. (void) port->QueryInterface
  258. (
  259. IID_IUnknown,
  260. (PVOID *) OutPortUnknown
  261. );
  262. }
  263. }
  264. else
  265. {
  266. //
  267. // Retract previously delivered port interface.
  268. //
  269. if (OutPortInterface && (*OutPortInterface))
  270. {
  271. (*OutPortInterface)->Release();
  272. *OutPortInterface = NULL;
  273. }
  274. }
  275. //
  276. // Release the reference which existed when PcNewPort() gave us the
  277. // pointer in the first place. This is the right thing to do
  278. // regardless of the outcome.
  279. //
  280. port->Release();
  281. }
  282. else
  283. {
  284. _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: PcNewPort failed"));
  285. }
  286. return ntStatus;
  287. }
  288. /*****************************************************************************
  289. * StartDevice()
  290. *****************************************************************************
  291. * This function is called by the operating system when the device is started.
  292. * It is responsible for starting the miniports. This code is specific to
  293. * the adapter because it calls out miniports for functions that are specific
  294. * to the adapter.
  295. */
  296. NTSTATUS
  297. StartDevice
  298. (
  299. IN PDEVICE_OBJECT DeviceObject, // Device object.
  300. IN PIRP Irp, // IO request packet.
  301. IN PRESOURCELIST ResourceList // List of hardware resources.
  302. )
  303. {
  304. PAGED_CODE();
  305. ASSERT(DeviceObject);
  306. ASSERT(Irp);
  307. ASSERT(ResourceList);
  308. //
  309. // These are the sub-lists of resources that will be handed to the
  310. // miniports.
  311. //
  312. PRESOURCELIST resourceListWave = NULL;
  313. PRESOURCELIST resourceListWaveTable = NULL;
  314. PRESOURCELIST resourceListFmSynth = NULL;
  315. PRESOURCELIST resourceListUart = NULL;
  316. PRESOURCELIST resourceListAdapter = NULL;
  317. //
  318. // These are the port driver pointers we are keeping around for registering
  319. // physical connections.
  320. //
  321. PUNKNOWN unknownTopology = NULL;
  322. PUNKNOWN unknownWave = NULL;
  323. PUNKNOWN unknownWaveTable = NULL;
  324. PUNKNOWN unknownFmSynth = NULL;
  325. //
  326. // Assign resources to individual miniports. Each sub-list is a copy
  327. // of the resources from the master list. Each sublist must be released.
  328. //
  329. NTSTATUS ntStatus = AssignResources( ResourceList,
  330. &resourceListWave,
  331. &resourceListWaveTable,
  332. &resourceListFmSynth,
  333. &resourceListUart,
  334. &resourceListAdapter );
  335. //
  336. // if AssignResources succeeded...
  337. //
  338. if(NT_SUCCESS(ntStatus))
  339. {
  340. //
  341. // If the adapter has resources...
  342. //
  343. PADAPTERCOMMON pAdapterCommon = NULL;
  344. if (resourceListAdapter)
  345. {
  346. PUNKNOWN pUnknownCommon;
  347. // create a new adapter common object
  348. ntStatus = NewAdapterCommon( &pUnknownCommon,
  349. IID_IAdapterCommon,
  350. NULL,
  351. NonPagedPool );
  352. if (NT_SUCCESS(ntStatus))
  353. {
  354. ASSERT( pUnknownCommon );
  355. // query for the IAdapterCommon interface
  356. ntStatus = pUnknownCommon->QueryInterface( IID_IAdapterCommon,
  357. (PVOID *)&pAdapterCommon );
  358. if (NT_SUCCESS(ntStatus))
  359. {
  360. // Initialize the object
  361. ntStatus = pAdapterCommon->Init( resourceListAdapter,
  362. DeviceObject );
  363. if (NT_SUCCESS(ntStatus))
  364. {
  365. // register with PortCls for power-management services
  366. ntStatus = PcRegisterAdapterPowerManagement( (PUNKNOWN)pAdapterCommon,
  367. DeviceObject );
  368. }
  369. }
  370. // release the IUnknown on adapter common
  371. pUnknownCommon->Release();
  372. }
  373. // release the adapter common resource list
  374. resourceListAdapter->Release();
  375. }
  376. //
  377. // Start the topology miniport.
  378. //
  379. if (NT_SUCCESS(ntStatus))
  380. {
  381. ntStatus = InstallSubdevice( DeviceObject,
  382. Irp,
  383. L"Topology",
  384. CLSID_PortTopology,
  385. CLSID_PortTopology, // not used
  386. CreateMiniportTopologySB16,
  387. pAdapterCommon,
  388. NULL,
  389. GUID_NULL,
  390. NULL,
  391. &unknownTopology );
  392. }
  393. //
  394. // Start the SB wave miniport if it exists.
  395. //
  396. if (resourceListWave)
  397. {
  398. if (NT_SUCCESS(ntStatus))
  399. {
  400. ntStatus = InstallSubdevice( DeviceObject,
  401. Irp,
  402. L"Wave",
  403. CLSID_PortWaveCyclic,
  404. CLSID_PortWaveCyclic, // not used
  405. CreateMiniportWaveCyclicSB16,
  406. pAdapterCommon,
  407. resourceListWave,
  408. IID_IPortWaveCyclic,
  409. NULL,
  410. &unknownWave );
  411. }
  412. // release the wave resource list
  413. resourceListWave->Release();
  414. }
  415. // Start the wave table miniport if it exists.
  416. if (resourceListWaveTable)
  417. {
  418. //
  419. // NOTE: The wavetable is not currently supported in this sample driver.
  420. //
  421. // release the wavetable resource list
  422. resourceListWaveTable->Release();
  423. }
  424. //
  425. // Start the FM synth miniport if it exists.
  426. //
  427. if (resourceListFmSynth)
  428. {
  429. //
  430. // Synth not working yet.
  431. //
  432. if (NT_SUCCESS(ntStatus))
  433. {
  434. //
  435. // Failure here is not fatal.
  436. //
  437. InstallSubdevice( DeviceObject,
  438. Irp,
  439. L"FMSynth",
  440. CLSID_PortMidi,
  441. CLSID_MiniportDriverFmSynth,
  442. NULL,
  443. pAdapterCommon,
  444. resourceListFmSynth,
  445. GUID_NULL,
  446. NULL,
  447. &unknownFmSynth );
  448. }
  449. // release the FM synth resource list
  450. resourceListFmSynth->Release();
  451. }
  452. //
  453. // Start the UART miniport if it exists.
  454. //
  455. if (resourceListUart)
  456. {
  457. if (NT_SUCCESS(ntStatus))
  458. {
  459. //
  460. // Failure here is not fatal.
  461. //
  462. InstallSubdevice( DeviceObject,
  463. Irp,
  464. L"Uart",
  465. CLSID_PortDMus,
  466. CLSID_MiniportDriverDMusUART,
  467. NULL,
  468. pAdapterCommon->GetInterruptSync(),
  469. resourceListUart,
  470. IID_IPortDMus,
  471. NULL, // interface to port not needed
  472. NULL ); // not physically connected to anything
  473. }
  474. resourceListUart->Release();
  475. }
  476. //
  477. // Establish physical connections between filters as shown.
  478. //
  479. // +------+ +------+
  480. // | Wave | | Topo |
  481. // Capture <---|0 1|<===|6 2|<--- CD
  482. // | | | |
  483. // Render --->|2 3|===>|0 3|<--- Line In
  484. // +------+ | |
  485. // +------+ | 4|<--- Mic
  486. // | FM | | |
  487. // MIDI --->|0 1|===>|1 5|---> Line Out
  488. // +------+ +------+
  489. //
  490. if (unknownTopology)
  491. {
  492. DWORD version = DeterminePlatform((PPORTTOPOLOGY)unknownTopology);
  493. _DbgPrintF(DEBUGLVL_VERBOSE,("Detected platform version 0x%02X",version));
  494. if (unknownWave)
  495. {
  496. // register wave <=> topology connections
  497. PcRegisterPhysicalConnection( (PDEVICE_OBJECT)DeviceObject,
  498. unknownTopology,
  499. 6,
  500. unknownWave,
  501. 1 );
  502. PcRegisterPhysicalConnection( (PDEVICE_OBJECT)DeviceObject,
  503. unknownWave,
  504. 3,
  505. unknownTopology,
  506. 0 );
  507. }
  508. if (unknownFmSynth)
  509. {
  510. // register fmsynth <=> topology connection
  511. PcRegisterPhysicalConnection( (PDEVICE_OBJECT)DeviceObject,
  512. unknownFmSynth,
  513. 1,
  514. unknownTopology,
  515. 1 );
  516. }
  517. }
  518. //
  519. // Release the adapter common object. It either has other references,
  520. // or we need to delete it anyway.
  521. //
  522. if (pAdapterCommon)
  523. {
  524. pAdapterCommon->Release();
  525. }
  526. //
  527. // Release the unknowns.
  528. //
  529. if (unknownTopology)
  530. {
  531. unknownTopology->Release();
  532. }
  533. if (unknownWave)
  534. {
  535. unknownWave->Release();
  536. }
  537. if (unknownWaveTable)
  538. {
  539. unknownWaveTable->Release();
  540. }
  541. if (unknownFmSynth)
  542. {
  543. unknownFmSynth->Release();
  544. }
  545. }
  546. return ntStatus;
  547. }
  548. /*****************************************************************************
  549. * AssignResources()
  550. *****************************************************************************
  551. * This function assigns the list of resources to the various functions on
  552. * the card. This code is specific to the adapter. All the non-NULL resource
  553. * lists handed back must be released by the caller.
  554. */
  555. NTSTATUS
  556. AssignResources
  557. (
  558. IN PRESOURCELIST ResourceList, // All resources.
  559. OUT PRESOURCELIST * ResourceListWave, // Wave resources.
  560. OUT PRESOURCELIST * ResourceListWaveTable, // Wave table resources.
  561. OUT PRESOURCELIST * ResourceListFmSynth, // FM synth resources.
  562. OUT PRESOURCELIST * ResourceListUart, // Uart resources.
  563. OUT PRESOURCELIST * ResourceListAdapter // For the adapter
  564. )
  565. {
  566. PAGED_CODE();
  567. BOOLEAN detectedWaveTable = FALSE;
  568. BOOLEAN detectedUart = FALSE;
  569. BOOLEAN detectedFmSynth = FALSE;
  570. //
  571. // Get counts for the types of resources.
  572. //
  573. ULONG countIO = ResourceList->NumberOfPorts();
  574. ULONG countIRQ = ResourceList->NumberOfInterrupts();
  575. ULONG countDMA = ResourceList->NumberOfDmas();
  576. //
  577. // Determine the type of card based on port resources.
  578. // TODO: Detect wave table.
  579. //
  580. NTSTATUS ntStatus = STATUS_SUCCESS;
  581. switch (countIO)
  582. {
  583. case 1:
  584. //
  585. // No FM synth or UART.
  586. //
  587. if ( (ResourceList->FindTranslatedPort(0)->u.Port.Length < 16)
  588. || (countIRQ < 1)
  589. || (countDMA < 1)
  590. )
  591. {
  592. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  593. }
  594. break;
  595. case 2:
  596. //
  597. // MPU-401 or FM synth, not both.
  598. //
  599. if ( (ResourceList->FindTranslatedPort(0)->u.Port.Length < 16)
  600. || (countIRQ < 1)
  601. || (countDMA < 1)
  602. )
  603. {
  604. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  605. }
  606. else
  607. {
  608. //
  609. // Length of second port indicates which function.
  610. //
  611. switch (ResourceList->FindTranslatedPort(1)->u.Port.Length)
  612. {
  613. case 2:
  614. detectedUart = TRUE;
  615. break;
  616. case 4:
  617. detectedFmSynth = TRUE;
  618. break;
  619. default:
  620. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  621. break;
  622. }
  623. }
  624. break;
  625. case 3:
  626. //
  627. // Both MPU-401 and FM synth.
  628. //
  629. if ( (ResourceList->FindTranslatedPort(0)->u.Port.Length < 16)
  630. || (ResourceList->FindTranslatedPort(1)->u.Port.Length != 2)
  631. || (ResourceList->FindTranslatedPort(2)->u.Port.Length != 4)
  632. || (countIRQ < 1)
  633. || (countDMA < 1)
  634. )
  635. {
  636. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  637. }
  638. else
  639. {
  640. detectedUart = TRUE;
  641. detectedFmSynth = TRUE;
  642. }
  643. break;
  644. default:
  645. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  646. break;
  647. }
  648. //
  649. // Build the resource list for the SB wave I/O.
  650. //
  651. *ResourceListWave = NULL;
  652. if (NT_SUCCESS(ntStatus))
  653. {
  654. ntStatus =
  655. PcNewResourceSublist
  656. (
  657. ResourceListWave,
  658. NULL,
  659. PagedPool,
  660. ResourceList,
  661. countDMA + countIRQ + 1
  662. );
  663. if (NT_SUCCESS(ntStatus))
  664. {
  665. ULONG i;
  666. //
  667. // Add the base address
  668. //
  669. ntStatus = (*ResourceListWave)->
  670. AddPortFromParent(ResourceList,0);
  671. //
  672. // Add the DMA channel(s).
  673. //
  674. if (NT_SUCCESS(ntStatus))
  675. {
  676. for (i = 0; i < countDMA; i++)
  677. {
  678. ntStatus = (*ResourceListWave)->
  679. AddDmaFromParent(ResourceList,i);
  680. }
  681. }
  682. //
  683. // Add the IRQ lines.
  684. //
  685. if (NT_SUCCESS(ntStatus))
  686. {
  687. for (i = 0; i < countIRQ; i++)
  688. {
  689. SUCCEEDS((*ResourceListWave)->
  690. AddInterruptFromParent(ResourceList,i));
  691. }
  692. }
  693. }
  694. }
  695. //
  696. // Build list of resources for wave table.
  697. //
  698. *ResourceListWaveTable = NULL;
  699. if (NT_SUCCESS(ntStatus) && detectedWaveTable)
  700. {
  701. //
  702. // TODO: Assign wave table resources.
  703. //
  704. }
  705. //
  706. // Build list of resources for UART.
  707. //
  708. *ResourceListUart = NULL;
  709. if (NT_SUCCESS(ntStatus) && detectedUart)
  710. {
  711. ntStatus =
  712. PcNewResourceSublist
  713. (
  714. ResourceListUart,
  715. NULL,
  716. PagedPool,
  717. ResourceList,
  718. 2
  719. );
  720. if (NT_SUCCESS(ntStatus))
  721. {
  722. ntStatus = (*ResourceListUart)->
  723. AddPortFromParent(ResourceList,1);
  724. if (NT_SUCCESS(ntStatus))
  725. {
  726. ntStatus = (*ResourceListUart)->
  727. AddInterruptFromParent(ResourceList,0);
  728. }
  729. }
  730. }
  731. //
  732. // Build list of resources for FM synth.
  733. //
  734. *ResourceListFmSynth = NULL;
  735. if (NT_SUCCESS(ntStatus) && detectedFmSynth)
  736. {
  737. ntStatus =
  738. PcNewResourceSublist
  739. (
  740. ResourceListFmSynth,
  741. NULL,
  742. PagedPool,
  743. ResourceList,
  744. 1
  745. );
  746. if (NT_SUCCESS(ntStatus))
  747. {
  748. ntStatus = (*ResourceListFmSynth)->
  749. AddPortFromParent(ResourceList,detectedUart ? 2 : 1);
  750. }
  751. }
  752. //
  753. // Build list of resources for the adapter.
  754. //
  755. *ResourceListAdapter = NULL;
  756. if (NT_SUCCESS(ntStatus))
  757. {
  758. ntStatus =
  759. PcNewResourceSublist
  760. (
  761. ResourceListAdapter,
  762. NULL,
  763. PagedPool,
  764. ResourceList,
  765. 3
  766. );
  767. if (NT_SUCCESS(ntStatus))
  768. {
  769. //
  770. // The interrupt to share.
  771. //
  772. ntStatus = (*ResourceListAdapter)->
  773. AddInterruptFromParent(ResourceList,0);
  774. //
  775. // The base IO port (to tell who's interrupt it is)
  776. //
  777. if (NT_SUCCESS(ntStatus))
  778. {
  779. ntStatus = (*ResourceListAdapter)->
  780. AddPortFromParent(ResourceList,0);
  781. }
  782. if (detectedUart && NT_SUCCESS(ntStatus))
  783. {
  784. //
  785. // The Uart port
  786. //
  787. ntStatus = (*ResourceListAdapter)->
  788. AddPortFromParent(ResourceList,1);
  789. }
  790. }
  791. }
  792. //
  793. // Clean up if failure occurred.
  794. //
  795. if (! NT_SUCCESS(ntStatus))
  796. {
  797. if (*ResourceListWave)
  798. {
  799. (*ResourceListWave)->Release();
  800. *ResourceListWave = NULL;
  801. }
  802. if (*ResourceListWaveTable)
  803. {
  804. (*ResourceListWaveTable)->Release();
  805. *ResourceListWaveTable = NULL;
  806. }
  807. if (*ResourceListUart)
  808. {
  809. (*ResourceListUart)->Release();
  810. *ResourceListUart = NULL;
  811. }
  812. if (*ResourceListFmSynth)
  813. {
  814. (*ResourceListFmSynth)->Release();
  815. *ResourceListFmSynth = NULL;
  816. }
  817. if(*ResourceListAdapter)
  818. {
  819. (*ResourceListAdapter)->Release();
  820. *ResourceListAdapter = NULL;
  821. }
  822. }
  823. return ntStatus;
  824. }
  825. #ifdef DO_RESOURCE_FILTERING
  826. /*****************************************************************************
  827. * AdapterDispatchPnp()
  828. *****************************************************************************
  829. * Supplying your PnP resource filtering needs.
  830. */
  831. extern "C"
  832. NTSTATUS
  833. AdapterDispatchPnp
  834. (
  835. IN PDEVICE_OBJECT pDeviceObject,
  836. IN PIRP pIrp
  837. )
  838. {
  839. PAGED_CODE();
  840. ASSERT(pDeviceObject);
  841. ASSERT(pIrp);
  842. NTSTATUS ntStatus = STATUS_SUCCESS;
  843. PIO_STACK_LOCATION pIrpStack =
  844. IoGetCurrentIrpStackLocation(pIrp);
  845. if( pIrpStack->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS )
  846. {
  847. //
  848. // Do your resource requirements filtering here!!
  849. //
  850. _DbgPrintF(DEBUGLVL_VERBOSE,("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS"));
  851. // set the return status
  852. pIrp->IoStatus.Status = ntStatus;
  853. }
  854. //
  855. // Pass the IRPs on to PortCls
  856. //
  857. ntStatus = PcDispatchIrp( pDeviceObject,
  858. pIrp );
  859. return ntStatus;
  860. }
  861. #endif
  862. /*****************************************************************************
  863. * DeterminePlatform()
  864. *****************************************************************************
  865. * Figure out which WDM platform we are currently running on.
  866. * Note: the Port parameter could be WAVECYCLIC, WAVEPCI, DMUS or MIDI instead.
  867. *
  868. * TODO: Make this work on old DDK.
  869. *
  870. */
  871. DWORD DeterminePlatform(PPORTTOPOLOGY Port)
  872. {
  873. PAGED_CODE();
  874. ASSERT(Port);
  875. //
  876. // The generally accepted way of determining audio stack vintage:
  877. //
  878. PPORTCLSVERSION pPortClsVersion;
  879. PDRMPORT pDrmPort;
  880. PPORTEVENTS pPortEvents;
  881. DWORD dwVersion;
  882. (void) Port->QueryInterface( IID_IPortClsVersion, (PVOID *) &pPortClsVersion);
  883. (void) Port->QueryInterface( IID_IDrmPort, (PVOID *) &pDrmPort);
  884. (void) Port->QueryInterface( IID_IPortEvents, (PVOID *) &pPortEvents);
  885. //
  886. // Try for the exact release (Win98SE QFE3, WinME QFE, Win2KSP2, WinXP, or later).
  887. //
  888. if (pPortClsVersion)
  889. {
  890. dwVersion = pPortClsVersion->GetVersion();
  891. pPortClsVersion->Release();
  892. }
  893. //
  894. // Try for WinME
  895. //
  896. else if (pDrmPort)
  897. {
  898. dwVersion = kVersionWinME;
  899. ASSERT(IoIsWdmVersionAvailable(0x01,0x05));
  900. //
  901. // TODO: Look for registry entries that denote WinME QFEs
  902. // HKLM\Software\Microsoft\Windows\CurrentVersion\Setup\Updates\..., etc.
  903. //
  904. }
  905. //
  906. // Try for Win2K family.
  907. // Note that SP1 contains no real audio stack changes,
  908. // while SP2 contains non-PCM support and other fixes.
  909. //
  910. else if (IoIsWdmVersionAvailable(0x01,0x10))
  911. {
  912. dwVersion = kVersionWin2K;
  913. //
  914. // TODO: Detect whether SP1 or earlier.
  915. //
  916. }
  917. //
  918. // Must be Win98 or Win98SE.
  919. // IPortEvents was new in Win98SE.
  920. //
  921. else if (pPortEvents)
  922. {
  923. dwVersion = kVersionWin98SE; // or older QFEs
  924. //
  925. // TODO: Look for registry entries that denote older Win98SE QFEs
  926. // HKLM\Software\Microsoft\Windows\CurrentVersion\Setup\Updates\W98.SE\UPD\269601, etc.
  927. //
  928. }
  929. //
  930. // Process of elimination tells us it is Win98.
  931. //
  932. else
  933. {
  934. dwVersion = kVersionWin98;
  935. //
  936. // TODO: Look for registry entries that denote older Win98 QFEs
  937. // HKLM\Software\Microsoft\Windows\CurrentVersion\Setup\Updates\..., etc.
  938. //
  939. }
  940. // dwVersion contains enum with version of audio stack
  941. return dwVersion;
  942. }
  943. #pragma code_seg()
  944. /*****************************************************************************
  945. * _purecall()
  946. *****************************************************************************
  947. * The C++ compiler loves me.
  948. * TODO: Figure out how to put this into portcls.sys
  949. */
  950. int __cdecl
  951. _purecall( void )
  952. {
  953. ASSERT( !"Pure virutal function called" );
  954. return 0;
  955. }