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.

1665 lines
59 KiB

  1. /********************************************************************************
  2. ** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  3. **
  4. ** Portions Copyright (c) 1998-1999 Intel Corporation
  5. **
  6. ********************************************************************************/
  7. // Every debug output has "Modulname text"
  8. static char STR_MODULENAME[] = "ICH Wave: ";
  9. #include "minwave.h"
  10. #include "ichwave.h"
  11. /*****************************************************************************
  12. * PinDataRangesPCMStream
  13. *****************************************************************************
  14. * The next 3 arrays contain information about the data ranges of the pin for
  15. * wave capture, wave render and mic capture.
  16. * These arrays are filled dynamically by BuildDataRangeInformation().
  17. */
  18. static KSDATARANGE_AUDIO PinDataRangesPCMStreamRender[WAVE_SAMPLERATES_TESTED];
  19. static KSDATARANGE_AUDIO PinDataRangesPCMStreamCapture[WAVE_SAMPLERATES_TESTED];
  20. static KSDATARANGE_AUDIO PinDataRangesMicStream[MIC_SAMPLERATES_TESTED];
  21. static KSDATARANGE PinDataRangesAnalogBridge[] =
  22. {
  23. {
  24. sizeof(KSDATARANGE),
  25. 0,
  26. 0,
  27. 0,
  28. STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
  29. STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
  30. STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
  31. }
  32. };
  33. /*****************************************************************************
  34. * PinDataRangesPointersPCMStream
  35. *****************************************************************************
  36. * The next 3 arrays contain the pointers to the data range information of
  37. * the pin for wave capture, wave render and mic capture.
  38. * These arrays are filled dynamically by BuildDataRangeInformation().
  39. */
  40. static PKSDATARANGE PinDataRangePointersPCMStreamRender[WAVE_SAMPLERATES_TESTED];
  41. static PKSDATARANGE PinDataRangePointersPCMStreamCapture[WAVE_SAMPLERATES_TESTED];
  42. static PKSDATARANGE PinDataRangePointersMicStream[MIC_SAMPLERATES_TESTED];
  43. /*****************************************************************************
  44. * PinDataRangePointerAnalogStream
  45. *****************************************************************************
  46. * This structure pointers to the data range structures for the wave pins.
  47. */
  48. static PKSDATARANGE PinDataRangePointersAnalogBridge[] =
  49. {
  50. (PKSDATARANGE) PinDataRangesAnalogBridge
  51. };
  52. /*****************************************************************************
  53. * Wave Miniport Topology
  54. *========================
  55. *
  56. * +-----------+
  57. * | |
  58. * Capture (PIN_WAVEIN) <---|2 --ADC-- 3|<=== (PIN_WAVEIN_BRIDGE)
  59. * | |
  60. * Render (PIN_WAVEOUT) --->|0 --DAC-- 1|===> (PIN_WAVEOUT_BRIDGE)
  61. * | |
  62. * Mic (PIN_MICIN) <---|4 --ADC-- 5|<=== (PIN_MICIN_BRIDGE)
  63. * +-----------+
  64. *
  65. * Note that the exposed pins (left side) have to be a multiple of 2
  66. * since there are some dependencies in the stream object.
  67. */
  68. /*****************************************************************************
  69. * MiniportPins
  70. *****************************************************************************
  71. * This structure describes pin (stream) types provided by this miniport.
  72. * The field that sets the number of data range entries (SIZEOF_ARRAY) is
  73. * overwritten by BuildDataRangeInformation().
  74. */
  75. static PCPIN_DESCRIPTOR MiniportPins[] =
  76. {
  77. // PIN_WAVEOUT
  78. {
  79. 1,1,0, // InstanceCount
  80. NULL, // AutomationTable
  81. { // KsPinDescriptor
  82. 0, // InterfacesCount
  83. NULL, // Interfaces
  84. 0, // MediumsCount
  85. NULL, // Mediums
  86. SIZEOF_ARRAY(PinDataRangePointersPCMStreamRender), // DataRangesCount
  87. PinDataRangePointersPCMStreamRender, // DataRanges
  88. KSPIN_DATAFLOW_IN, // DataFlow
  89. KSPIN_COMMUNICATION_SINK, // Communication
  90. (GUID *) &KSCATEGORY_AUDIO, // Category
  91. NULL, // Name
  92. 0 // Reserved
  93. }
  94. },
  95. // PIN_WAVEOUT_BRIDGE
  96. {
  97. 0,0,0, // InstanceCount
  98. NULL, // AutomationTable
  99. { // KsPinDescriptor
  100. 0, // InterfacesCount
  101. NULL, // Interfaces
  102. 0, // MediumsCount
  103. NULL, // Mediums
  104. SIZEOF_ARRAY(PinDataRangePointersAnalogBridge), // DataRangesCount
  105. PinDataRangePointersAnalogBridge, // DataRanges
  106. KSPIN_DATAFLOW_OUT, // DataFlow
  107. KSPIN_COMMUNICATION_NONE, // Communication
  108. (GUID *) &KSCATEGORY_AUDIO, // Category
  109. NULL, // Name
  110. 0 // Reserved
  111. }
  112. },
  113. // PIN_WAVEIN
  114. {
  115. 1,1,0, // InstanceCount
  116. NULL, // AutomationTable
  117. { // KsPinDescriptor
  118. 0, // InterfacesCount
  119. NULL, // Interfaces
  120. 0, // MediumsCount
  121. NULL, // Mediums
  122. SIZEOF_ARRAY(PinDataRangePointersPCMStreamCapture), // DataRangesCount
  123. PinDataRangePointersPCMStreamCapture, // DataRanges
  124. KSPIN_DATAFLOW_OUT, // DataFlow
  125. KSPIN_COMMUNICATION_SINK, // Communication
  126. (GUID *) &PINNAME_CAPTURE, // Category
  127. &KSAUDFNAME_RECORDING_CONTROL, // Name
  128. 0 // Reserved
  129. }
  130. },
  131. // PIN_WAVEIN_BRIDGE
  132. {
  133. 0,0,0, // InstanceCount
  134. NULL, // AutomationTable
  135. { // KsPinDescriptor
  136. 0, // InterfacesCount
  137. NULL, // Interfaces
  138. 0, // MediumsCount
  139. NULL, // Mediums
  140. SIZEOF_ARRAY(PinDataRangePointersAnalogBridge), // DataRangesCount
  141. PinDataRangePointersAnalogBridge, // DataRanges
  142. KSPIN_DATAFLOW_IN, // DataFlow
  143. KSPIN_COMMUNICATION_NONE, // Communication
  144. (GUID *) &KSCATEGORY_AUDIO, // Category
  145. NULL, // Name
  146. 0 // Reserved
  147. }
  148. },
  149. //
  150. // The Microphone pins are not used if PINC_MICIN_PRESENT is not set.
  151. // To remove them, Init() will reduce the "PinCount" in the
  152. // MiniportFilterDescriptor.
  153. //
  154. // PIN_MICIN
  155. {
  156. 1,1,0, // InstanceCount
  157. NULL, // AutomationTable
  158. { // KsPinDescriptor
  159. 0, // InterfacesCount
  160. NULL, // Interfaces
  161. 0, // MediumsCount
  162. NULL, // Mediums
  163. SIZEOF_ARRAY(PinDataRangePointersMicStream),// DataRangesCount
  164. PinDataRangePointersMicStream, // DataRanges
  165. KSPIN_DATAFLOW_OUT, // DataFlow
  166. KSPIN_COMMUNICATION_SINK, // Communication
  167. (GUID *) &KSCATEGORY_AUDIO, // Category
  168. NULL, // Name
  169. 0 // Reserved
  170. }
  171. },
  172. // PIN_MICIN_BRIDGE
  173. {
  174. 0,0,0, // InstanceCount
  175. NULL, // AutomationTable
  176. { // KsPinDescriptor
  177. 0, // InterfacesCount
  178. NULL, // Interfaces
  179. 0, // MediumsCount
  180. NULL, // Mediums
  181. SIZEOF_ARRAY(PinDataRangePointersAnalogBridge), // DataRangesCount
  182. PinDataRangePointersAnalogBridge, // DataRanges
  183. KSPIN_DATAFLOW_IN, // DataFlow
  184. KSPIN_COMMUNICATION_NONE, // Communication
  185. (GUID *) &KSCATEGORY_AUDIO, // Category
  186. NULL, // Name
  187. 0 // Reserved
  188. }
  189. }
  190. };
  191. /*****************************************************************************
  192. * PropertiesDAC
  193. *****************************************************************************
  194. * Properties for the DAC node.
  195. */
  196. static PCPROPERTY_ITEM PropertiesDAC[] =
  197. {
  198. {
  199. &KSPROPSETID_Audio,
  200. KSPROPERTY_AUDIO_CHANNEL_CONFIG,
  201. KSPROPERTY_TYPE_SET,
  202. CMiniportWaveICH::PropertyChannelConfig
  203. }
  204. };
  205. /*****************************************************************************
  206. * AutomationVolume
  207. *****************************************************************************
  208. * Automation table for volume controls.
  209. */
  210. DEFINE_PCAUTOMATION_TABLE_PROP (AutomationDAC, PropertiesDAC);
  211. /*****************************************************************************
  212. * TopologyNodes
  213. *****************************************************************************
  214. * List of nodes.
  215. */
  216. static PCNODE_DESCRIPTOR MiniportNodes[] =
  217. {
  218. // NODE_WAVEOUT_DAC
  219. {
  220. 0, // Flags
  221. &AutomationDAC, // AutomationTable
  222. &KSNODETYPE_DAC, // Type
  223. NULL // Name
  224. },
  225. // NODE_WAVEIN_ADC
  226. {
  227. 0, // Flags
  228. NULL, // AutomationTable
  229. &KSNODETYPE_ADC, // Type
  230. NULL // Name
  231. },
  232. //
  233. // The Microphone node is not used if PINC_MICIN_PRESENT is not set.
  234. // To remove them, Init() will reduce the "NodeCount" in the
  235. // MiniportFilterDescriptor.
  236. //
  237. // NODE_MICIN_ADC
  238. {
  239. 0, // Flags
  240. NULL, // AutomationTable
  241. &KSNODETYPE_ADC, // Type
  242. NULL // Name
  243. }
  244. };
  245. /*****************************************************************************
  246. * MiniportConnections
  247. *****************************************************************************
  248. * This structure identifies the connections between filter pins and
  249. * node pins.
  250. */
  251. static PCCONNECTION_DESCRIPTOR MiniportConnections[] =
  252. {
  253. //from_node from_pin to_node to_pin
  254. { PCFILTER_NODE, PIN_WAVEOUT, NODE_WAVEOUT_DAC, 1},
  255. { NODE_WAVEOUT_DAC, 0, PCFILTER_NODE, PIN_WAVEOUT_BRIDGE},
  256. { PCFILTER_NODE, PIN_WAVEIN_BRIDGE, NODE_WAVEIN_ADC, 1},
  257. { NODE_WAVEIN_ADC, 0, PCFILTER_NODE, PIN_WAVEIN},
  258. //
  259. // The Microphone connection is not used if PINC_MICIN_PRESENT is not set.
  260. // To remove them, Init() will reduce the "ConnectionCount" in the
  261. // MiniportFilterDescriptor.
  262. //
  263. { PCFILTER_NODE, PIN_MICIN_BRIDGE, NODE_MICIN_ADC, 1},
  264. { NODE_MICIN_ADC, 0, PCFILTER_NODE, PIN_MICIN}
  265. };
  266. /*****************************************************************************
  267. * MiniportFilterDescriptor
  268. *****************************************************************************
  269. * Complete miniport description.
  270. * Init() modifies the pin count, node count and connection count in absence
  271. * of the MicIn recording line.
  272. */
  273. static PCFILTER_DESCRIPTOR MiniportFilterDescriptor =
  274. {
  275. 0, // Version
  276. NULL, // AutomationTable
  277. sizeof(PCPIN_DESCRIPTOR), // PinSize
  278. SIZEOF_ARRAY(MiniportPins), // PinCount
  279. MiniportPins, // Pins
  280. sizeof(PCNODE_DESCRIPTOR), // NodeSize
  281. SIZEOF_ARRAY(MiniportNodes), // NodeCount
  282. MiniportNodes, // Nodes
  283. SIZEOF_ARRAY(MiniportConnections), // ConnectionCount
  284. MiniportConnections, // Connections
  285. 0, // CategoryCount
  286. NULL // Categories: NULL->use defaults (audio, render, capture)
  287. };
  288. #pragma code_seg("PAGE")
  289. /*****************************************************************************
  290. * CMiniportWaveICH::PropertyChannelConfig
  291. *****************************************************************************
  292. * This is the property handler for KSPROPERTY_AUDIO_CHANNEL_CONFIG of the
  293. * DAC node. It sets the channel configuration (how many channels, how user
  294. * was setting up the speakers).
  295. */
  296. NTSTATUS CMiniportWaveICH::PropertyChannelConfig
  297. (
  298. IN PPCPROPERTY_REQUEST PropertyRequest
  299. )
  300. {
  301. PAGED_CODE ();
  302. ASSERT (PropertyRequest);
  303. DOUT (DBG_PRINT, ("[CMiniportWaveICH::PropertyChannelConfig]"));
  304. NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
  305. // The major target is the object pointer to the wave miniport.
  306. CMiniportWaveICH *that =
  307. (CMiniportWaveICH *) (PMINIPORTWAVEPCI)PropertyRequest->MajorTarget;
  308. ASSERT (that);
  309. // We only have a set defined.
  310. if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
  311. {
  312. // validate buffer size.
  313. if (PropertyRequest->ValueSize < sizeof(LONG))
  314. return ntStatus;
  315. // The "Value" is the input buffer with the channel config.
  316. if (PropertyRequest->Value)
  317. {
  318. // We can accept different channel configurations, depending
  319. // on the number of channels we can play.
  320. if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
  321. {
  322. if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
  323. {
  324. // we accept 5.1
  325. if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1)
  326. {
  327. that->m_dwChannelMask = *(PLONG)PropertyRequest->Value;
  328. that->m_wChannels = 6;
  329. that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
  330. ntStatus = STATUS_SUCCESS;
  331. }
  332. }
  333. // accept also surround or quad.
  334. if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) ||
  335. (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND))
  336. {
  337. that->m_dwChannelMask = *(PLONG)PropertyRequest->Value;
  338. that->m_wChannels = 4;
  339. that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
  340. ntStatus = STATUS_SUCCESS;
  341. }
  342. }
  343. // accept also stereo speakers.
  344. if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO)
  345. {
  346. that->m_dwChannelMask = *(PLONG)PropertyRequest->Value;
  347. that->m_wChannels = 2;
  348. that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
  349. ntStatus = STATUS_SUCCESS;
  350. }
  351. }
  352. }
  353. return ntStatus;
  354. }
  355. /*****************************************************************************
  356. * CreateMiniportWaveICH
  357. *****************************************************************************
  358. * Creates a ICH wave miniport object for the ICH adapter.
  359. * This uses a macro from STDUNK.H to do all the work.
  360. */
  361. NTSTATUS CreateMiniportWaveICH
  362. (
  363. OUT PUNKNOWN *Unknown,
  364. IN REFCLSID,
  365. IN PUNKNOWN UnknownOuter OPTIONAL,
  366. IN POOL_TYPE PoolType
  367. )
  368. {
  369. PAGED_CODE ();
  370. ASSERT (Unknown);
  371. DOUT (DBG_PRINT, ("[CreateMiniportWaveICH]"));
  372. STD_CREATE_BODY_(CMiniportWaveICH,Unknown,UnknownOuter,PoolType,
  373. PMINIPORTWAVEPCI);
  374. }
  375. /*****************************************************************************
  376. * CMiniportWaveICH::NonDelegatingQueryInterface
  377. *****************************************************************************
  378. * Obtains an interface. This function works just like a COM QueryInterface
  379. * call and is used if the object is not being aggregated.
  380. */
  381. STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::NonDelegatingQueryInterface
  382. (
  383. IN REFIID Interface,
  384. OUT PVOID *Object
  385. )
  386. {
  387. PAGED_CODE ();
  388. ASSERT (Object);
  389. DOUT (DBG_PRINT, ("[CMiniportWaveICH::NonDelegatingQueryInterface]"));
  390. // Is it IID_IUnknown?
  391. if (IsEqualGUIDAligned (Interface, IID_IUnknown))
  392. {
  393. *Object = (PVOID)(PUNKNOWN)(PMINIPORTWAVEPCI)this;
  394. }
  395. // or IID_IMiniport ...
  396. else if (IsEqualGUIDAligned (Interface, IID_IMiniport))
  397. {
  398. *Object = (PVOID)(PMINIPORT)this;
  399. }
  400. // or IID_IMiniportWavePci ...
  401. else if (IsEqualGUIDAligned (Interface, IID_IMiniportWavePci))
  402. {
  403. *Object = (PVOID)(PMINIPORTWAVEPCI)this;
  404. }
  405. // or IID_IPowerNotify ...
  406. else if (IsEqualGUIDAligned (Interface, IID_IPowerNotify))
  407. {
  408. *Object = (PVOID)(PPOWERNOTIFY)this;
  409. }
  410. else
  411. {
  412. // nothing found, must be an unknown interface.
  413. *Object = NULL;
  414. return STATUS_INVALID_PARAMETER;
  415. }
  416. //
  417. // We reference the interface for the caller.
  418. //
  419. ((PUNKNOWN)(*Object))->AddRef();
  420. return STATUS_SUCCESS;
  421. }
  422. /*****************************************************************************
  423. * CMiniportWaveICH::~CMiniportWaveICH
  424. *****************************************************************************
  425. * Destructor.
  426. */
  427. CMiniportWaveICH::~CMiniportWaveICH ()
  428. {
  429. PAGED_CODE ();
  430. DOUT (DBG_PRINT, ("[CMiniportWaveICH::~CMiniportWaveICH]"));
  431. //
  432. // Release the DMA channel.
  433. //
  434. if (DmaChannel)
  435. {
  436. DmaChannel->Release ();
  437. DmaChannel = NULL;
  438. }
  439. //
  440. // Release the interrupt sync.
  441. //
  442. if (InterruptSync)
  443. {
  444. InterruptSync->Release ();
  445. InterruptSync = NULL;
  446. }
  447. //
  448. // Release adapter common object.
  449. //
  450. if (AdapterCommon)
  451. {
  452. AdapterCommon->Release ();
  453. AdapterCommon = NULL;
  454. }
  455. //
  456. // Release the port.
  457. //
  458. if (Port)
  459. {
  460. Port->Release ();
  461. Port = NULL;
  462. }
  463. }
  464. /*****************************************************************************
  465. * CMiniportWaveICH::Init
  466. *****************************************************************************
  467. * Initializes the miniport.
  468. * Initializes variables and modifies the wave topology if needed.
  469. */
  470. STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::Init
  471. (
  472. IN PUNKNOWN UnknownAdapter,
  473. IN PRESOURCELIST ResourceList,
  474. IN PPORTWAVEPCI Port_,
  475. OUT PSERVICEGROUP *ServiceGroup_
  476. )
  477. {
  478. PAGED_CODE ();
  479. ASSERT (UnknownAdapter);
  480. ASSERT (ResourceList);
  481. ASSERT (Port_);
  482. DOUT (DBG_PRINT, ("[CMiniportWaveICH::Init]"));
  483. //
  484. // AddRef() is required because we are keeping this pointer.
  485. //
  486. Port = Port_;
  487. Port->AddRef ();
  488. //
  489. // No miniport service group
  490. //
  491. *ServiceGroup_ = NULL;
  492. //
  493. // Set initial device power state
  494. //
  495. m_PowerState = PowerDeviceD0;
  496. NTSTATUS ntStatus = UnknownAdapter->
  497. QueryInterface (IID_IAdapterCommon, (PVOID *)&AdapterCommon);
  498. if (NT_SUCCESS (ntStatus))
  499. {
  500. //
  501. // Alter the topology for the wave miniport.
  502. //
  503. if (!(AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT) &&
  504. AdapterCommon->GetPinConfig (PINC_MIC_PRESENT)))
  505. {
  506. //
  507. // Remove the pins, nodes and connections for the MICIN.
  508. //
  509. MiniportFilterDescriptor.PinCount = SIZEOF_ARRAY(MiniportPins) - 2;
  510. MiniportFilterDescriptor.NodeCount = SIZEOF_ARRAY(MiniportNodes) - 1;
  511. MiniportFilterDescriptor.ConnectionCount = SIZEOF_ARRAY(MiniportConnections) - 2;
  512. }
  513. //
  514. // Process the resources.
  515. //
  516. ntStatus = ProcessResources (ResourceList);
  517. //
  518. // Get the default channel config
  519. //
  520. AdapterCommon->ReadChannelConfigDefault (&m_dwChannelMask, &m_wChannels);
  521. //
  522. // If we came till that point, check the CoDec for supported standard
  523. // sample rates. This function will then fill the data range information
  524. //
  525. if (NT_SUCCESS (ntStatus))
  526. ntStatus = BuildDataRangeInformation ();
  527. }
  528. //
  529. // If we fail we get destroyed anyway (that's where we clean up).
  530. //
  531. return ntStatus;
  532. }
  533. /*****************************************************************************
  534. * CMiniportWaveICH::ProcessResources
  535. *****************************************************************************
  536. * Processes the resource list, setting up helper objects accordingly.
  537. * Sets up the Interrupt + Service routine and DMA.
  538. */
  539. NTSTATUS CMiniportWaveICH::ProcessResources
  540. (
  541. IN PRESOURCELIST ResourceList
  542. )
  543. {
  544. PAGED_CODE ();
  545. ASSERT (ResourceList);
  546. DOUT (DBG_PRINT, ("[CMiniportWaveICH::ProcessResources]"));
  547. ULONG countIRQ = ResourceList->NumberOfInterrupts ();
  548. if (countIRQ < 1)
  549. {
  550. DOUT (DBG_ERROR, ("Unknown configuration for wave miniport!"));
  551. return STATUS_DEVICE_CONFIGURATION_ERROR;
  552. }
  553. //
  554. // Create an interrupt sync object
  555. //
  556. NTSTATUS ntStatus = STATUS_SUCCESS;
  557. ntStatus = PcNewInterruptSync (&InterruptSync,
  558. NULL,
  559. ResourceList,
  560. 0,
  561. InterruptSyncModeNormal);
  562. if (!NT_SUCCESS (ntStatus) || !InterruptSync)
  563. {
  564. DOUT (DBG_ERROR, ("Failed to create an interrupt sync!"));
  565. return STATUS_INSUFFICIENT_RESOURCES;
  566. }
  567. //
  568. // Register our ISR.
  569. //
  570. ntStatus = InterruptSync->RegisterServiceRoutine (InterruptServiceRoutine,
  571. (PVOID)this, FALSE);
  572. if (!NT_SUCCESS (ntStatus))
  573. {
  574. DOUT (DBG_ERROR, ("Failed to register ISR!"));
  575. return ntStatus;
  576. }
  577. //
  578. // Connect the interrupt.
  579. //
  580. ntStatus = InterruptSync->Connect ();
  581. if (!NT_SUCCESS (ntStatus))
  582. {
  583. DOUT (DBG_ERROR, ("Failed to connect the ISR with InterruptSync!"));
  584. return ntStatus;
  585. }
  586. //
  587. // Create the DMA Channel object.
  588. //
  589. ntStatus = Port->NewMasterDmaChannel (&DmaChannel, // OutDmaChannel
  590. NULL, // OuterUnknown (opt)
  591. NonPagedPool, // Pool Type
  592. NULL, // ResourceList (opt)
  593. TRUE, // ScatterGather
  594. TRUE, // Dma32BitAddresses
  595. FALSE, // Dma64BitAddresses
  596. FALSE, // IgnoreCount
  597. Width32Bits, // DmaWidth
  598. MaximumDmaSpeed, // DmaSpeed
  599. 0x1FFFE, // MaximumLength (128KByte -2)
  600. 0); // DmaPort
  601. if (!NT_SUCCESS (ntStatus))
  602. {
  603. DOUT (DBG_ERROR, ("Failed on NewMasterDmaChannel!"));
  604. return ntStatus;
  605. }
  606. //
  607. // Get the DMA adapter.
  608. //
  609. AdapterObject = DmaChannel->GetAdapterObject ();
  610. //
  611. // On failure object is destroyed which cleans up.
  612. //
  613. return STATUS_SUCCESS;
  614. }
  615. /*****************************************************************************
  616. * CAdapterCommon::BuildDataRangeInformation
  617. *****************************************************************************
  618. * This function dynamically build the data range information for the pins.
  619. * It also connects the static arrays with the data range information
  620. * structure.
  621. * If this function returns with an error the miniport should be destroyed.
  622. *
  623. * To build the data range information, we test the most popular sample rates,
  624. * the functions calls ProgramSampleRate in AdapterCommon object to actually
  625. * program the sample rate. After probing that way for multiple sample rates,
  626. * the original value, which is 48KHz is, gets restored.
  627. * We have to test the sample rates for playback, capture and microphone
  628. * separately. Every time we succeed, we update the data range information and
  629. * the pointers that point to it.
  630. */
  631. NTSTATUS CMiniportWaveICH::BuildDataRangeInformation (void)
  632. {
  633. PAGED_CODE ();
  634. NTSTATUS ntStatus;
  635. int nWavePlaybackEntries = 0;
  636. int nWaveRecordingEntries = 0;
  637. int nMicEntries = 0;
  638. int nChannels;
  639. int nLoop;
  640. DOUT (DBG_PRINT, ("[CMiniportWaveICH::BuildDataRangeInformation]"));
  641. //
  642. // Calculate the number of max. channels available in the codec.
  643. //
  644. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
  645. {
  646. if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
  647. {
  648. nChannels = 6;
  649. }
  650. else
  651. {
  652. nChannels = 4;
  653. }
  654. }
  655. else
  656. {
  657. nChannels = 2;
  658. }
  659. // Check for the render sample rates.
  660. for (nLoop = 0; nLoop < WAVE_SAMPLERATES_TESTED; nLoop++)
  661. {
  662. ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_FRONT_SAMPLERATE,
  663. dwWaveSampleRates[nLoop]);
  664. // We support the sample rate?
  665. if (NT_SUCCESS (ntStatus))
  666. {
  667. // Add it to the PinDataRange
  668. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
  669. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Flags = 0;
  670. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.SampleSize = nChannels * 2;
  671. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Reserved = 0;
  672. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
  673. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  674. PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
  675. PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumChannels = nChannels;
  676. PinDataRangesPCMStreamRender[nWavePlaybackEntries].MinimumBitsPerSample = 16;
  677. PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumBitsPerSample = 16;
  678. PinDataRangesPCMStreamRender[nWavePlaybackEntries].MinimumSampleFrequency = dwWaveSampleRates[nLoop];
  679. PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumSampleFrequency = dwWaveSampleRates[nLoop];
  680. // Add it to the PinDataRangePointer
  681. PinDataRangePointersPCMStreamRender[nWavePlaybackEntries] = (PKSDATARANGE)&PinDataRangesPCMStreamRender[nWavePlaybackEntries];
  682. // Increase count
  683. nWavePlaybackEntries++;
  684. }
  685. }
  686. // Check for the capture sample rates.
  687. for (nLoop = 0; nLoop < WAVE_SAMPLERATES_TESTED; nLoop++)
  688. {
  689. ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_RECORD_SAMPLERATE, dwWaveSampleRates[nLoop]);
  690. // We support the sample rate?
  691. if (NT_SUCCESS (ntStatus))
  692. {
  693. // Add it to the PinDataRange
  694. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
  695. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Flags = 0;
  696. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.SampleSize = 4;
  697. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Reserved = 0;
  698. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
  699. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  700. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
  701. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumChannels = 2;
  702. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MinimumBitsPerSample = 16;
  703. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumBitsPerSample = 16;
  704. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MinimumSampleFrequency = dwWaveSampleRates[nLoop];
  705. PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumSampleFrequency = dwWaveSampleRates[nLoop];
  706. // Add it to the PinDataRangePointer
  707. PinDataRangePointersPCMStreamCapture[nWaveRecordingEntries] = (PKSDATARANGE)&PinDataRangesPCMStreamCapture[nWaveRecordingEntries];
  708. // Increase count
  709. nWaveRecordingEntries++;
  710. }
  711. }
  712. // Check for the MIC sample rates.
  713. for (nLoop = 0; nLoop < MIC_SAMPLERATES_TESTED; nLoop++)
  714. {
  715. ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_MIC_SAMPLERATE, dwMicSampleRates[nLoop]);
  716. // We support the sample rate?
  717. if (NT_SUCCESS (ntStatus))
  718. {
  719. // Add it to the PinDataRange
  720. PinDataRangesMicStream[nMicEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
  721. PinDataRangesMicStream[nMicEntries].DataRange.Flags = 0;
  722. PinDataRangesMicStream[nMicEntries].DataRange.SampleSize = 2;
  723. PinDataRangesMicStream[nMicEntries].DataRange.Reserved = 0;
  724. PinDataRangesMicStream[nMicEntries].DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
  725. PinDataRangesMicStream[nMicEntries].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  726. PinDataRangesMicStream[nMicEntries].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
  727. PinDataRangesMicStream[nMicEntries].MaximumChannels = 1;
  728. PinDataRangesMicStream[nMicEntries].MinimumBitsPerSample = 16;
  729. PinDataRangesMicStream[nMicEntries].MaximumBitsPerSample = 16;
  730. PinDataRangesMicStream[nMicEntries].MinimumSampleFrequency = dwMicSampleRates[nLoop];
  731. PinDataRangesMicStream[nMicEntries].MaximumSampleFrequency = dwMicSampleRates[nLoop];
  732. // Add it to the PinDataRangePointer
  733. PinDataRangePointersMicStream[nMicEntries] = (PKSDATARANGE)&PinDataRangesMicStream[nMicEntries];
  734. // Increase count
  735. nMicEntries++;
  736. }
  737. }
  738. // Now go through the pin descriptor list and change the data range entries to the actual number.
  739. for (nLoop = 0; nLoop < SIZEOF_ARRAY(MiniportPins); nLoop++)
  740. {
  741. if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersPCMStreamRender)
  742. MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nWavePlaybackEntries;
  743. if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersPCMStreamCapture)
  744. MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nWaveRecordingEntries;
  745. if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersMicStream)
  746. MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nMicEntries;
  747. }
  748. return STATUS_SUCCESS;
  749. }
  750. /*****************************************************************************
  751. * CMiniportWaveICH::NewStream
  752. *****************************************************************************
  753. * Creates a new stream.
  754. * This function is called when a streaming pin is created.
  755. * It checks if the channel is already in use, tests the data format, creates
  756. * and initializes the stream object.
  757. */
  758. STDMETHODIMP CMiniportWaveICH::NewStream
  759. (
  760. OUT PMINIPORTWAVEPCISTREAM *Stream,
  761. IN PUNKNOWN OuterUnknown,
  762. IN POOL_TYPE PoolType,
  763. IN PPORTWAVEPCISTREAM PortStream,
  764. IN ULONG Channel_,
  765. IN BOOLEAN Capture,
  766. IN PKSDATAFORMAT DataFormat,
  767. OUT PDMACHANNEL *DmaChannel_,
  768. OUT PSERVICEGROUP *ServiceGroup
  769. )
  770. {
  771. PAGED_CODE ();
  772. ASSERT (Stream);
  773. ASSERT (PortStream);
  774. ASSERT (DataFormat);
  775. ASSERT (DmaChannel_);
  776. ASSERT (ServiceGroup);
  777. CMiniportWaveICHStream *pWaveICHStream = NULL;
  778. NTSTATUS ntStatus = STATUS_SUCCESS;
  779. DOUT (DBG_PRINT, ("[CMiniportWaveICH::NewStream]"));
  780. //
  781. // Validate the channel (pin id).
  782. //
  783. if ((Channel_ != PIN_WAVEOUT) && (Channel_ != PIN_WAVEIN) &&
  784. (Channel_ != PIN_MICIN))
  785. {
  786. DOUT (DBG_ERROR, ("[NewStream] Invalid channel passed!"));
  787. return STATUS_INVALID_PARAMETER;
  788. }
  789. //
  790. // Check if the pin is already in use
  791. //
  792. ULONG Channel = Channel_ >> 1;
  793. if (Streams[Channel])
  794. {
  795. DOUT (DBG_ERROR, ("[NewStream] Pin is already in use!"));
  796. return STATUS_UNSUCCESSFUL;
  797. }
  798. //
  799. // Check parameters.
  800. //
  801. ntStatus = TestDataFormat (DataFormat, (WavePins)Channel_);
  802. if (!NT_SUCCESS (ntStatus))
  803. {
  804. DOUT (DBG_VSR, ("[NewStream] TestDataFormat failed!"));
  805. return ntStatus;
  806. }
  807. //
  808. // Create a new stream.
  809. //
  810. ntStatus = CreateMiniportWaveICHStream (&pWaveICHStream, OuterUnknown,
  811. PoolType);
  812. //
  813. // Return in case of an error.
  814. //
  815. if (!NT_SUCCESS (ntStatus))
  816. {
  817. DOUT (DBG_ERROR, ("[NewStream] Failed to create stream!"));
  818. return ntStatus;
  819. }
  820. //
  821. // Initialize the stream.
  822. //
  823. ntStatus = pWaveICHStream->Init (this,
  824. PortStream,
  825. Channel,
  826. Capture,
  827. DataFormat,
  828. ServiceGroup);
  829. if (!NT_SUCCESS (ntStatus))
  830. {
  831. //
  832. // Release the stream and clean up.
  833. //
  834. DOUT (DBG_ERROR, ("[NewStream] Failed to init stream!"));
  835. pWaveICHStream->Release ();
  836. // In case the stream passed us a ServiceGroup, portcls will ignore all parameters
  837. // on a failure, so we have to release it here.
  838. if (*ServiceGroup)
  839. (*ServiceGroup)->Release();
  840. *ServiceGroup = NULL;
  841. *Stream = NULL;
  842. *DmaChannel_ = NULL;
  843. return ntStatus;
  844. }
  845. //
  846. // Save the pointers.
  847. //
  848. *Stream = (PMINIPORTWAVEPCISTREAM)pWaveICHStream;
  849. *DmaChannel_ = DmaChannel;
  850. return STATUS_SUCCESS;
  851. }
  852. /*****************************************************************************
  853. * CMiniportWaveICH::GetDescription
  854. *****************************************************************************
  855. * Gets the topology.
  856. */
  857. STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::GetDescription
  858. (
  859. OUT PPCFILTER_DESCRIPTOR *OutFilterDescriptor
  860. )
  861. {
  862. PAGED_CODE ();
  863. ASSERT (OutFilterDescriptor);
  864. DOUT (DBG_PRINT, ("[CMiniportWaveICH::GetDescription]"));
  865. *OutFilterDescriptor = &MiniportFilterDescriptor;
  866. return STATUS_SUCCESS;
  867. }
  868. /*****************************************************************************
  869. * CMiniportWaveICH::DataRangeIntersection
  870. *****************************************************************************
  871. * Tests a data range intersection.
  872. * Cause the AC97 controller does not support mono render or capture, we have
  873. * to check the max. channel field (unfortunately, there is no MinimumChannel
  874. * and MaximumChannel field, just a MaximumChannel field).
  875. * If the MaximumChannel is 2, then we can pass this to the default handler of
  876. * portcls which always chooses the most (SampleFrequency, Channel, Bits etc.)
  877. *
  878. * This DataRangeIntersection function is strictly only for the exposed formats
  879. * in this sample driver. If you intend to add other formats like AC3 then
  880. * you have to be make sure that you check the GUIDs and the data range, since
  881. * portcls only checks the data range for waveformatex.
  882. */
  883. STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::DataRangeIntersection
  884. (
  885. IN ULONG PinId,
  886. IN PKSDATARANGE ClientsDataRange,
  887. IN PKSDATARANGE MyDataRange,
  888. IN ULONG OutputBufferLength,
  889. OUT PVOID ResultantFormat,
  890. OUT PULONG ResultantFormatLength
  891. )
  892. {
  893. PAGED_CODE ();
  894. DOUT (DBG_PRINT, ("[CMiniportWaveICH::DataRangeIntersection]"));
  895. //
  896. // This function gets only called if the GUIDS in the KSDATARANGE_AUDIO
  897. // structure that we attached to the pin are equal with the requested
  898. // format (see "BuildDataRangeInformation).
  899. // Additionally, for waveformatex portcls checks that the requested sample
  900. // frequency range fits into our exposed sample frequency range. Since we
  901. // only have discrete sample frequencies in the pin's data range, we don't
  902. // have to check that either.
  903. // There is one exception to this rule: portcls clones all WAVEFORMATEX
  904. // data ranges to DSOUND dataranges, so we might get a data range
  905. // intersection that has a DSOUND specifier. We don't support that
  906. // since this is only used for HW acceleration
  907. //
  908. if (IsEqualGUIDAligned (ClientsDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND))
  909. {
  910. DOUT (DBG_PRINT, ("[DataRangeIntersection] We don't support DSOUND specifier"));
  911. return STATUS_NOT_SUPPORTED;
  912. }
  913. //
  914. // Start with checking the size of the output buffer.
  915. //
  916. if (!OutputBufferLength)
  917. {
  918. *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
  919. return STATUS_BUFFER_OVERFLOW;
  920. }
  921. if (OutputBufferLength < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)))
  922. {
  923. DOUT (DBG_WARNING, ("[DataRangeIntersection] Buffer too small"));
  924. return STATUS_BUFFER_TOO_SMALL;
  925. }
  926. //
  927. // We can only play or record multichannel (>=2 channels) except for the MIC
  928. // recording channel where we can only record mono. Portcls checked the channels
  929. // already, however, since we have no minimum channels field, the KSDATARANGE_AUDIO
  930. // could have MaximumChannels = 1.
  931. //
  932. if (PinId != PIN_MICIN)
  933. {
  934. // reject mono format for normal wave playback or capture.
  935. if (((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumChannels < 2)
  936. {
  937. DOUT (DBG_WARNING, ("[DataRangeIntersection] Mono requested for WaveIn or WaveOut"));
  938. return STATUS_NO_MATCH;
  939. }
  940. }
  941. //
  942. // Fill in the structure the datarange structure.
  943. // KSDATARANGE and KSDATAFORMAT are the same.
  944. //
  945. *(PKSDATAFORMAT)ResultantFormat = *MyDataRange;
  946. //
  947. // Modify the size of the data format structure to fit the WAVEFORMATPCMEX
  948. // structure.
  949. //
  950. ((PKSDATAFORMAT)ResultantFormat)->FormatSize =
  951. sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
  952. //
  953. // Append the WAVEFORMATPCMEX structur.
  954. //
  955. PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1);
  956. // We want a WAFEFORMATEXTENSIBLE which is equal to WAVEFORMATPCMEX.
  957. WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  958. // Set the number of channels
  959. if (PinId == PIN_WAVEOUT)
  960. {
  961. // Get the max. possible channels for playback.
  962. ULONG nMaxChannels = min (((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumChannels, m_wChannels);
  963. // We cannot play uneven number of channels
  964. if (nMaxChannels & 0x01)
  965. nMaxChannels--;
  966. // ... and also 0 channels wouldn't be a good request.
  967. if (!nMaxChannels)
  968. return STATUS_NO_MATCH;
  969. WaveFormat->Format.nChannels = (WORD)nMaxChannels;
  970. }
  971. else
  972. // This will be 2 for normal record and 1 for MIC record.
  973. WaveFormat->Format.nChannels = (WORD)((PKSDATARANGE_AUDIO)MyDataRange)->MaximumChannels;
  974. //
  975. // Hack for codecs that have only one sample rate converter that has both
  976. // playback and recording data.
  977. //
  978. if ((Streams[PIN_WAVEIN_OFFSET] || Streams[PIN_WAVEOUT_OFFSET]) &&
  979. !AdapterCommon->GetNodeConfig (NODEC_PCM_VSR_INDEPENDENT_RATES))
  980. {
  981. //
  982. // We have to return this sample rate that is used in the open stream.
  983. //
  984. ULONG ulFrequency;
  985. if (Streams[PIN_WAVEIN_OFFSET])
  986. ulFrequency = Streams[PIN_WAVEIN_OFFSET]->GetCurrentSampleRate();
  987. else
  988. ulFrequency = Streams[PIN_WAVEOUT_OFFSET]->GetCurrentSampleRate();
  989. //
  990. // Check if this sample rate is in the requested data range of the client.
  991. //
  992. if ((((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumSampleFrequency < ulFrequency) ||
  993. (((PKSDATARANGE_AUDIO)ClientsDataRange)->MinimumSampleFrequency > ulFrequency))
  994. {
  995. return STATUS_NO_MATCH;
  996. }
  997. WaveFormat->Format.nSamplesPerSec = ulFrequency;
  998. }
  999. else
  1000. {
  1001. // Since we have discrete frequencies in the data range, min = max.
  1002. WaveFormat->Format.nSamplesPerSec = ((PKSDATARANGE_AUDIO)MyDataRange)->MaximumSampleFrequency;
  1003. }
  1004. // Will be 16.
  1005. WaveFormat->Format.wBitsPerSample = (WORD)((PKSDATARANGE_AUDIO)MyDataRange)->MaximumBitsPerSample;
  1006. // Will be 2 * channels.
  1007. WaveFormat->Format.nBlockAlign = (WaveFormat->Format.wBitsPerSample * WaveFormat->Format.nChannels) / 8;
  1008. // That is played in a sec.
  1009. WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign;
  1010. // WAVEFORMATPCMEX
  1011. WaveFormat->Format.cbSize = 22;
  1012. // We have as many valid bits as the bit depth is (16).
  1013. WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample;
  1014. // Set the channel mask
  1015. if (PinId == PIN_WAVEOUT)
  1016. {
  1017. // If we can play in our configuration, then set the channel mask
  1018. if (WaveFormat->Format.nChannels == m_wChannels)
  1019. // Set the playback channel mask to the current speaker config.
  1020. WaveFormat->dwChannelMask = m_dwChannelMask;
  1021. else
  1022. {
  1023. //
  1024. // We have to set a channel mask.
  1025. // nChannles can only be 4 if we are in 6 channel mode. In that
  1026. // case it must be a QUAD configurations. The only other value
  1027. // allowed is 2 channels, which defaults to stereo.
  1028. //
  1029. if (WaveFormat->Format.nChannels == 4)
  1030. WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD;
  1031. else
  1032. WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
  1033. }
  1034. }
  1035. else
  1036. {
  1037. // This will be KSAUDIO_SPEAKER_STEREO for normal record and KSAUDIO_SPEAKER_MONO
  1038. // for MIC record.
  1039. if (PinId == PIN_MICIN)
  1040. // MicIn -> 1 channel
  1041. WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_MONO;
  1042. else
  1043. // normal record -> 2 channels
  1044. WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
  1045. }
  1046. // Here we specify the subtype of the WAVEFORMATEXTENSIBLE.
  1047. WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  1048. // Now overwrite also the sample size in the ksdataformat structure.
  1049. ((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign;
  1050. //
  1051. // That we will return.
  1052. //
  1053. *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
  1054. DOUT (DBG_STREAM, ("[DataRangeIntersection] Frequency: %d, Channels: %d, bps: %d, ChannelMask: %X",
  1055. WaveFormat->Format.nSamplesPerSec, WaveFormat->Format.nChannels,
  1056. WaveFormat->Format.wBitsPerSample, WaveFormat->dwChannelMask));
  1057. // Let portcls do some work ...
  1058. return STATUS_SUCCESS;
  1059. }
  1060. /*****************************************************************************
  1061. * CMiniportWaveICH::TestDataFormat
  1062. *****************************************************************************
  1063. * Checks if the passed data format is known to the driver and verifies that
  1064. * the number of channels, the width of one sample match to the AC97
  1065. * specification.
  1066. */
  1067. NTSTATUS CMiniportWaveICH::TestDataFormat
  1068. (
  1069. IN PKSDATAFORMAT Format,
  1070. IN WavePins Pin
  1071. )
  1072. {
  1073. PAGED_CODE ();
  1074. ASSERT (Format);
  1075. DOUT (DBG_PRINT, ("[CMiniportWaveICH::TestDataFormat]"));
  1076. //
  1077. // KSDATAFORMAT contains three GUIDs to support extensible format. The
  1078. // first two GUIDs identify the type of data. The third indicates the
  1079. // type of specifier used to indicate format specifics. We are only
  1080. // supporting PCM audio formats that use WAVEFORMATEX.
  1081. //
  1082. if (!IsEqualGUIDAligned (Format->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) ||
  1083. !IsEqualGUIDAligned (Format->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) ||
  1084. !IsEqualGUIDAligned (Format->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
  1085. {
  1086. DOUT (DBG_ERROR, ("[TestDataFormat] Invalid format type!"));
  1087. return STATUS_INVALID_PARAMETER;
  1088. }
  1089. PWAVEFORMATPCMEX waveFormat = (PWAVEFORMATPCMEX)(Format + 1);
  1090. //
  1091. // If the size doesn't match, then something is messed up.
  1092. //
  1093. if (Format->FormatSize < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX)))
  1094. {
  1095. DOUT (DBG_WARNING, ("[TestDataFormat] Invalid FormatSize!"));
  1096. return STATUS_INVALID_PARAMETER;
  1097. }
  1098. //
  1099. // We only support PCM, 16-bit.
  1100. //
  1101. if (waveFormat->Format.wBitsPerSample != 16)
  1102. {
  1103. DOUT (DBG_WARNING, ("[TestDataFormat] Bits Per Sample must be 16!"));
  1104. return STATUS_INVALID_PARAMETER;
  1105. }
  1106. //
  1107. // We support WaveFormatPCMEX (=WAVEFORMATEXTENSIBLE) or WaveFormatPCM.
  1108. //
  1109. if ((waveFormat->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) &&
  1110. (waveFormat->Format.wFormatTag != WAVE_FORMAT_PCM))
  1111. {
  1112. DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Format Tag!"));
  1113. return STATUS_INVALID_PARAMETER;
  1114. }
  1115. //
  1116. // Make additional checks for the WAVEFORMATEXTENSIBLE
  1117. //
  1118. if (waveFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
  1119. {
  1120. //
  1121. // If the size doesn't match, then something is messed up.
  1122. //
  1123. if (Format->FormatSize < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)))
  1124. {
  1125. DOUT (DBG_WARNING, ("[TestDataFormat] Invalid FormatSize!"));
  1126. return STATUS_INVALID_PARAMETER;
  1127. }
  1128. //
  1129. // Check also the subtype (PCM) and the size of the extended data.
  1130. //
  1131. if (!IsEqualGUIDAligned (waveFormat->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) ||
  1132. (waveFormat->Format.cbSize < (sizeof(WAVEFORMATPCMEX) - sizeof(WAVEFORMATEX))))
  1133. {
  1134. DOUT (DBG_WARNING, ("[TestDataFormat] Unsupported WAVEFORMATEXTENSIBLE!"));
  1135. return STATUS_INVALID_PARAMETER;
  1136. }
  1137. //
  1138. // Check the channel mask. We support 1, 2 channels or whatever was set
  1139. // with the Speaker config dialog.
  1140. //
  1141. if (((waveFormat->Format.nChannels == 1) &&
  1142. (waveFormat->dwChannelMask != KSAUDIO_SPEAKER_MONO)) ||
  1143. ((waveFormat->Format.nChannels == 2) &&
  1144. (waveFormat->dwChannelMask != KSAUDIO_SPEAKER_STEREO)) ||
  1145. ((waveFormat->Format.nChannels == m_wChannels) &&
  1146. (waveFormat->dwChannelMask != m_dwChannelMask)))
  1147. {
  1148. DOUT (DBG_WARNING, ("[TestDataFormat] Channel Mask!"));
  1149. return STATUS_INVALID_PARAMETER;
  1150. }
  1151. }
  1152. //
  1153. // Check the number of channels.
  1154. //
  1155. switch (Pin)
  1156. {
  1157. case PIN_MICIN: // 1 channel
  1158. if (waveFormat->Format.nChannels != 1)
  1159. {
  1160. DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Number of Channels for PIN_MICIN!"));
  1161. return STATUS_INVALID_PARAMETER;
  1162. }
  1163. break;
  1164. case PIN_WAVEIN: // 2 channels
  1165. if (waveFormat->Format.nChannels != 2)
  1166. {
  1167. DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Number of Channels for PIN_WAVEIN!"));
  1168. return STATUS_INVALID_PARAMETER;
  1169. }
  1170. break;
  1171. case PIN_WAVEOUT: // channel and mask from PropertyChannelConfig or standard.
  1172. if (waveFormat->Format.nChannels != m_wChannels)
  1173. {
  1174. DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Number of Channels for PIN_WAVEOUT!"));
  1175. return STATUS_INVALID_PARAMETER;
  1176. }
  1177. break;
  1178. }
  1179. //
  1180. // Print the information.
  1181. //
  1182. if (waveFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
  1183. {
  1184. DOUT (DBG_STREAM, ("[TestDataFormat] PCMEX - Frequency: %d, Channels: %d, bps: %d, ChannelMask: %X",
  1185. waveFormat->Format.nSamplesPerSec, waveFormat->Format.nChannels,
  1186. waveFormat->Format.wBitsPerSample, waveFormat->dwChannelMask));
  1187. }
  1188. else
  1189. {
  1190. DOUT (DBG_STREAM, ("[TestDataFormat] PCM - Frequency: %d, Channels: %d, bps: %d",
  1191. waveFormat->Format.nSamplesPerSec, waveFormat->Format.nChannels,
  1192. waveFormat->Format.wBitsPerSample));
  1193. }
  1194. return STATUS_SUCCESS;
  1195. }
  1196. /*****************************************************************************
  1197. * CMiniportWaveICH::PowerChangeNotify
  1198. *****************************************************************************
  1199. * This routine gets called as a result of hooking up the IPowerNotify
  1200. * interface. This interface indicates the driver's desire to receive explicit
  1201. * notification of power state changes. The interface provides a single method
  1202. * (or callback) that is called by the miniport's corresponding port driver in
  1203. * response to a power state change. Using wave audio as an example, when the
  1204. * device is requested to go to a sleep state the port driver pauses any
  1205. * active streams and then calls the power notify callback to inform the
  1206. * miniport of the impending power down. The miniport then has an opportunity
  1207. * to save any necessary context before the adapter's PowerChangeState method
  1208. * is called. The process is reversed when the device is powering up. PortCls
  1209. * first calls the adapter's PowerChangeState method to power up the adapter.
  1210. * The port driver then calls the miniport's callback to allow the miniport to
  1211. * restore its context. Finally, the port driver unpauses any previously paused
  1212. * active audio streams.
  1213. */
  1214. STDMETHODIMP_(void) CMiniportWaveICH::PowerChangeNotify
  1215. (
  1216. IN POWER_STATE NewState
  1217. )
  1218. {
  1219. PAGED_CODE ();
  1220. NTSTATUS ntStatus = STATUS_SUCCESS;
  1221. DOUT (DBG_PRINT, ("[CMiniportWaveICH::PowerChangeNotify]"));
  1222. //
  1223. // Check to see if this is the current power state.
  1224. //
  1225. if (NewState.DeviceState == m_PowerState)
  1226. {
  1227. DOUT (DBG_POWER, ("New device state equals old state."));
  1228. return;
  1229. }
  1230. //
  1231. // Check the new device state.
  1232. //
  1233. if ((NewState.DeviceState < PowerDeviceD0) ||
  1234. (NewState.DeviceState > PowerDeviceD3))
  1235. {
  1236. DOUT (DBG_ERROR, ("Unknown device state: D%d.",
  1237. (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
  1238. return;
  1239. }
  1240. DOUT (DBG_POWER, ("Changing state to D%d.", (ULONG)NewState.DeviceState -
  1241. (ULONG)PowerDeviceD0));
  1242. //
  1243. // In case we return to D0 power state from a D3 state, restore the
  1244. // interrupt connection.
  1245. //
  1246. if (NewState.DeviceState == PowerDeviceD0)
  1247. {
  1248. ntStatus = InterruptSync->Connect ();
  1249. if (!NT_SUCCESS (ntStatus))
  1250. {
  1251. DOUT (DBG_ERROR, ("Failed to connect the ISR with InterruptSync!"));
  1252. // We can do nothing else than just continue ...
  1253. }
  1254. }
  1255. //
  1256. // Call the stream routine which takes care of the DMA engine.
  1257. // That's all we have to do.
  1258. //
  1259. for (int loop = PIN_WAVEOUT_OFFSET; loop < PIN_MICIN_OFFSET; loop++)
  1260. {
  1261. if (Streams[loop])
  1262. {
  1263. ntStatus = Streams[loop]->PowerChangeNotify (NewState);
  1264. if (!NT_SUCCESS (ntStatus))
  1265. {
  1266. DOUT (DBG_ERROR, ("PowerChangeNotify D%d for the stream failed",
  1267. (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
  1268. }
  1269. }
  1270. }
  1271. //
  1272. // In case we go to any sleep state we disconnect the interrupt service
  1273. // reoutine from the interrupt.
  1274. // Normally this is not required to do, but for some reason this fixes
  1275. // a problem where we won't have any interrupts on specific motherboards
  1276. // after resume.
  1277. //
  1278. if (NewState.DeviceState != PowerDeviceD0)
  1279. {
  1280. InterruptSync->Disconnect ();
  1281. }
  1282. //
  1283. // Save the new state. This local value is used to determine when to
  1284. // cache property accesses and when to permit the driver from accessing
  1285. // the hardware.
  1286. //
  1287. m_PowerState = NewState.DeviceState;
  1288. DOUT (DBG_POWER, ("Entering D%d",
  1289. (ULONG)m_PowerState - (ULONG)PowerDeviceD0));
  1290. }
  1291. /*****************************************************************************
  1292. * Non paged code begins here
  1293. *****************************************************************************
  1294. */
  1295. #pragma code_seg()
  1296. /*****************************************************************************
  1297. * CMiniportWaveICH::Service
  1298. *****************************************************************************
  1299. * Processing routine for dealing with miniport interrupts. This routine is
  1300. * called at DISPATCH_LEVEL.
  1301. */
  1302. STDMETHODIMP_(void) CMiniportWaveICH::Service (void)
  1303. {
  1304. // not needed
  1305. }
  1306. /*****************************************************************************
  1307. * InterruptServiceRoutine
  1308. *****************************************************************************
  1309. * The task of the ISR is to clear an interrupt from this device so we don't
  1310. * get an interrupt storm and schedule a DPC which actually does the
  1311. * real work.
  1312. */
  1313. NTSTATUS CMiniportWaveICH::InterruptServiceRoutine
  1314. (
  1315. IN PINTERRUPTSYNC InterruptSync,
  1316. IN PVOID DynamicContext
  1317. )
  1318. {
  1319. ASSERT (InterruptSync);
  1320. ASSERT (DynamicContext);
  1321. ULONG GlobalStatus;
  1322. USHORT DMAStatusRegister;
  1323. //
  1324. // Get our context which is a pointer to class CMiniportWaveICH.
  1325. //
  1326. CMiniportWaveICH *that = (CMiniportWaveICH *)DynamicContext;
  1327. //
  1328. // Check for a valid AdapterCommon pointer.
  1329. //
  1330. if (!that->AdapterCommon)
  1331. {
  1332. //
  1333. // In case we didn't handle the interrupt, unsuccessful tells the system
  1334. // to call the next interrupt handler in the chain.
  1335. //
  1336. return STATUS_UNSUCCESSFUL;
  1337. }
  1338. //
  1339. // From this point down, basically in the complete ISR, we cannot use
  1340. // relative addresses (stream class base address + X_CR for example)
  1341. // cause we might get called when the stream class is destroyed or
  1342. // not existent. This doesn't make too much sense (that there is an
  1343. // interrupt for a non-existing stream) but could happen and we have
  1344. // to deal with the interrupt.
  1345. //
  1346. //
  1347. // Read the global register to check the interrupt bits
  1348. //
  1349. GlobalStatus = that->AdapterCommon->ReadBMControlRegister32 (GLOB_STA);
  1350. //
  1351. // Check for weird return values. Could happen if the PCI device is already
  1352. // disabled and another device that shares this interrupt generated an
  1353. // interrupt.
  1354. // The register should never have all bits cleared or set.
  1355. //
  1356. if (!GlobalStatus || (GlobalStatus == 0xFFFFFFFF))
  1357. {
  1358. return STATUS_UNSUCCESSFUL;
  1359. }
  1360. //
  1361. // Check for PCM out interrupt.
  1362. //
  1363. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  1364. if (GlobalStatus & GLOB_STA_POINT)
  1365. {
  1366. //
  1367. // Read PCM out DMA status registers.
  1368. //
  1369. DMAStatusRegister = (USHORT)that->AdapterCommon->
  1370. ReadBMControlRegister16 (PO_SR);
  1371. //
  1372. // We could now check for every possible error condition
  1373. // (like FIFO error) and monitor the different errors, but currently
  1374. // we have the same action for every INT and therefore we simplify
  1375. // this routine enormous with just clearing the bits.
  1376. //
  1377. if (that->Streams[PIN_WAVEOUT_OFFSET])
  1378. {
  1379. //
  1380. // ACK the interrupt.
  1381. //
  1382. that->AdapterCommon->WriteBMControlRegister (PO_SR, DMAStatusRegister);
  1383. ntStatus = STATUS_SUCCESS;
  1384. //
  1385. // Request DPC service for PCM out.
  1386. //
  1387. if ((that->Port) && (that->Streams[PIN_WAVEOUT_OFFSET]->ServiceGroup))
  1388. {
  1389. that->Port->Notify (that->Streams[PIN_WAVEOUT_OFFSET]->ServiceGroup);
  1390. }
  1391. else
  1392. {
  1393. //
  1394. // Bad, bad. Shouldn't print in an ISR!
  1395. //
  1396. DOUT (DBG_ERROR, ("WaveOut INT fired but no stream object there."));
  1397. }
  1398. }
  1399. }
  1400. //
  1401. // Check for PCM in interrupt.
  1402. //
  1403. if (GlobalStatus & GLOB_STA_PIINT)
  1404. {
  1405. //
  1406. // Read PCM in DMA status registers.
  1407. //
  1408. DMAStatusRegister = (USHORT)that->AdapterCommon->
  1409. ReadBMControlRegister16 (PI_SR);
  1410. //
  1411. // We could now check for every possible error condition
  1412. // (like FIFO error) and monitor the different errors, but currently
  1413. // we have the same action for every INT and therefore we simplify
  1414. // this routine enormous with just clearing the bits.
  1415. //
  1416. if (that->Streams[PIN_WAVEIN_OFFSET])
  1417. {
  1418. //
  1419. // ACK the interrupt.
  1420. //
  1421. that->AdapterCommon->WriteBMControlRegister (PI_SR, DMAStatusRegister);
  1422. ntStatus = STATUS_SUCCESS;
  1423. //
  1424. // Request DPC service for PCM in.
  1425. //
  1426. if ((that->Port) && (that->Streams[PIN_WAVEIN_OFFSET]->ServiceGroup))
  1427. {
  1428. that->Port->Notify (that->Streams[PIN_WAVEIN_OFFSET]->ServiceGroup);
  1429. }
  1430. else
  1431. {
  1432. //
  1433. // Bad, bad. Shouldn't print in an ISR!
  1434. //
  1435. DOUT (DBG_ERROR, ("WaveIn INT fired but no stream object there."));
  1436. }
  1437. }
  1438. }
  1439. //
  1440. // Check for MIC in interrupt.
  1441. //
  1442. if (GlobalStatus & GLOB_STA_MINT)
  1443. {
  1444. //
  1445. // Read MIC in DMA status registers.
  1446. //
  1447. DMAStatusRegister = (USHORT)that->AdapterCommon->
  1448. ReadBMControlRegister16 (MC_SR);
  1449. //
  1450. // We could now check for every possible error condition
  1451. // (like FIFO error) and monitor the different errors, but currently
  1452. // we have the same action for every INT and therefore we simplify
  1453. // this routine enormous with just clearing the bits.
  1454. //
  1455. if (that->Streams[PIN_MICIN_OFFSET])
  1456. {
  1457. //
  1458. // ACK the interrupt.
  1459. //
  1460. that->AdapterCommon->WriteBMControlRegister (MC_SR, DMAStatusRegister);
  1461. ntStatus = STATUS_SUCCESS;
  1462. //
  1463. // Request DPC service for PCM out.
  1464. //
  1465. if ((that->Port) && (that->Streams[PIN_MICIN_OFFSET]->ServiceGroup))
  1466. {
  1467. that->Port->Notify (that->Streams[PIN_MICIN_OFFSET]->ServiceGroup);
  1468. }
  1469. else
  1470. {
  1471. //
  1472. // Bad, bad. Shouldn't print in an ISR!
  1473. //
  1474. DOUT (DBG_ERROR, ("MicIn INT fired but no stream object there."));
  1475. }
  1476. }
  1477. }
  1478. return ntStatus;
  1479. }