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.

2294 lines
73 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 Common: ";
  9. #include "common.h"
  10. /*****************************************************************************
  11. * Static Members
  12. *****************************************************************************
  13. */
  14. //
  15. // This is the register cache including registry names and default values. The
  16. // first WORD contains the register value and the second WORD contains a flag.
  17. // Currently, we only set SHREG_INVALID if we have to read the register at
  18. // startup (that's true when there is no constant default value for the
  19. // register). Note that we cache the registers only to prevent read access to
  20. // the AC97 CoDec during runtime, because this is slow (40us).
  21. // We only set SHREG_INIT if we want to set the register to default at driver
  22. // startup. If needed, the third field contains the registry name and the
  23. // forth field contains a default value that is used when there is no registry
  24. // entry.
  25. // The flag SHREG_NOCACHE is used when we don't want to cache the register
  26. // at all. This is neccessary for status registers and sample rate registers.
  27. //
  28. tAC97Registers CAdapterCommon::m_stAC97Registers[] =
  29. {
  30. {0x0000, SHREG_INVALID, NULL, 0}, // AC97REG_RESET
  31. {0x8000, SHREG_INIT, L"MasterVolume", 0x0000}, // AC97REG_MASTER_VOLUME
  32. {0x8000, SHREG_INIT, L"HeadphoneVolume", 0x0000}, // AC97REG_HPHONE_VOLUME
  33. {0x8000, SHREG_INIT, L"MonooutVolume", 0x0000}, // AC97REG_MMONO_VOLUME
  34. {0x0F0F, SHREG_INIT, L"ToneControls", 0x0F0F}, // AC97REG_MASTER_TONE
  35. {0x0000, SHREG_INVALID |
  36. SHREG_INIT, L"BeepVolume", 0x0000}, // AC97REG_BEEP_VOLUME
  37. {0x8008, SHREG_INIT, L"PhoneVolume", 0x8008}, // AC97REG_PHONE_VOLUME
  38. {0x8008, SHREG_INIT, L"MicVolume", 0x8008}, // AC97REG_MIC_VOLUME
  39. {0x8808, SHREG_INIT, L"LineInVolume", 0x0808}, // AC97REG_LINE_IN_VOLUME
  40. {0x8808, SHREG_INIT, L"CDVolume", 0x0808}, // AC97REG_CD_VOLUME
  41. {0x8808, SHREG_INIT, L"VideoVolume", 0x0808}, // AC97REG_VIDEO_VOLUME
  42. {0x8808, SHREG_INIT, L"AUXVolume", 0x0808}, // AC97REG_AUX_VOLUME
  43. {0x8808, SHREG_INIT, L"WaveOutVolume", 0x0808}, // AC97REG_PCM_OUT_VOLUME
  44. {0x0000, SHREG_INIT, L"RecordSelect", 0x0404}, // AC97REG_RECORD_SELECT
  45. {0x8000, SHREG_INIT, L"RecordGain", 0x0000}, // AC97REG_RECORD_GAIN
  46. {0x8000, SHREG_INIT, L"RecordGainMic", 0x0000}, // AC97REG_RECORD_GAIN_MIC
  47. {0x0000, SHREG_INIT, L"GeneralPurpose", 0x0000}, // AC97REG_GENERAL
  48. {0x0000, SHREG_INIT, L"3DControl", 0x0000}, // AC97REG_3D_CONTROL
  49. {0x0000, SHREG_NOCACHE, NULL, 0}, // AC97REG_RESERVED
  50. {0x0000, SHREG_NOCACHE |
  51. SHREG_INIT, L"PowerDown", 0}, // AC97REG_POWERDOWN
  52. // AC97-2.0 registers
  53. {0x0000, SHREG_INVALID, NULL, 0}, // AC97REG_EXT_AUDIO_ID
  54. {0x0000, SHREG_NOCACHE |
  55. SHREG_INIT, L"ExtAudioCtrl", 0x4001}, // AC97REG_EXT_AUDIO_CTRL
  56. {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_FRONT_SAMPLERATE
  57. {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_SURROUND_SAMPLERATE
  58. {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_LFE_SAMPLERATE
  59. {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_RECORD_SAMPLERATE
  60. {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_MIC_SAMPLERATE
  61. {0x8080, SHREG_INIT, L"CenterLFEVolume", 0x0000}, // AC97REG_CENTER_LFE_VOLUME
  62. {0x8080, SHREG_INIT, L"SurroundVolume", 0x0000}, // AC97REG_SURROUND_VOLUME
  63. {0x0000, SHREG_NOCACHE, NULL, 0} // AC97REG_RESERVED2
  64. // We leave the other values blank. There would be a huge gap with 31
  65. // elements that are currently unused, and then there would be 2 other
  66. // (used) values, the vendor IDs. We just force a read from the vendor
  67. // IDs in the end of ProbeHWConfig to fill the cache.
  68. };
  69. //
  70. // This is the hardware configuration information. The first struct is for
  71. // nodes, which we default to FALSE. The second struct is for Pins, which
  72. // contains the configuration (FALSE) and the registry string which is the
  73. // reason for making a static struct so we can just fill in the name.
  74. //
  75. tHardwareConfig CAdapterCommon::m_stHardwareConfig =
  76. {
  77. // Nodes
  78. {{FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE},
  79. {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE},
  80. {FALSE}},
  81. // Pins
  82. {{FALSE, L"DisablePCBeep"}, // PINC_PCBEEP_PRESENT
  83. {FALSE, L"DisablePhone"}, // PINC_PHONE_PRESENT
  84. {FALSE, L"DisableMic2"}, // PINC_MIC2_PRESENT
  85. {FALSE, L"DisableVideo"}, // PINC_VIDEO_PRESENT
  86. {FALSE, L"DisableAUX"}, // PINC_AUX_PRESENT
  87. {FALSE, L"DisableHeadphone"}, // PINC_HPOUT_PRESENT
  88. {FALSE, L"DisableMonoOut"}, // PINC_MONOOUT_PRESENT
  89. {FALSE, L"DisableMicIn"}, // PINC_MICIN_PRESENT
  90. {FALSE, L"DisableMic"}, // PINC_MIC_PRESENT
  91. {FALSE, L"DisableLineIn"}, // PINC_LINEIN_PRESENT
  92. {FALSE, L"DisableCD"}, // PINC_CD_PRESENT
  93. {FALSE, L"DisableSurround"}, // PINC_SURROUND_PRESENT
  94. {FALSE, L"DisableCenterLFE"}} // PINC_CENTER_LFE_PRESENT
  95. };
  96. #pragma code_seg("PAGE")
  97. /*****************************************************************************
  98. * NewAdapterCommon
  99. *****************************************************************************
  100. * Create a new adapter common object.
  101. */
  102. NTSTATUS NewAdapterCommon
  103. (
  104. OUT PUNKNOWN *Unknown,
  105. IN REFCLSID,
  106. IN PUNKNOWN UnknownOuter OPTIONAL,
  107. IN POOL_TYPE PoolType
  108. )
  109. {
  110. PAGED_CODE ();
  111. ASSERT (Unknown);
  112. DOUT (DBG_PRINT, ("[NewAdapterCommon]"));
  113. STD_CREATE_BODY_
  114. (
  115. CAdapterCommon,
  116. Unknown,
  117. UnknownOuter,
  118. PoolType,
  119. PADAPTERCOMMON
  120. );
  121. }
  122. /*****************************************************************************
  123. * CAdapterCommon::Init
  124. *****************************************************************************
  125. * Initialize the adapter common object -> initialize and probe HW.
  126. * Pass only checked resources.
  127. */
  128. STDMETHODIMP_(NTSTATUS) CAdapterCommon::Init
  129. (
  130. IN PRESOURCELIST ResourceList,
  131. IN PDEVICE_OBJECT DeviceObject
  132. )
  133. {
  134. PAGED_CODE ();
  135. ASSERT (ResourceList);
  136. ASSERT (DeviceObject);
  137. NTSTATUS ntStatus = STATUS_SUCCESS;
  138. DOUT (DBG_PRINT, ("[CAdapterCommon::Init]"));
  139. //
  140. // Set the topology pointer to NULL.
  141. //
  142. m_Topology = NULL;
  143. //
  144. // Save the device object
  145. //
  146. m_pDeviceObject = DeviceObject;
  147. //
  148. // Get the base address for the AC97 codec and bus master.
  149. //
  150. ASSERT (ResourceList->FindTranslatedPort (0));
  151. m_pCodecBase = (PUSHORT)ResourceList->FindTranslatedPort (0)->
  152. u.Port.Start.QuadPart;
  153. ASSERT (ResourceList->FindTranslatedPort (1));
  154. m_pBusMasterBase = (PUCHAR)ResourceList->FindTranslatedPort (1)->
  155. u.Port.Start.QuadPart;
  156. DOUT (DBG_SYSINFO, ("Configuration:\n"
  157. " Bus Master = 0x%X\n"
  158. " Codec = 0x%X",
  159. m_pBusMasterBase, m_pCodecBase));
  160. //
  161. // Set m_bDirectRead to TRUE so that all AC97 register read and
  162. // writes are going directly to the HW
  163. //
  164. m_bDirectRead = TRUE;
  165. //
  166. // Initialize the hardware.
  167. //
  168. ntStatus = InitAC97 ();
  169. if (!NT_SUCCESS (ntStatus))
  170. return ntStatus;
  171. //
  172. // Probe hardware configuration
  173. //
  174. ntStatus = ProbeHWConfig ();
  175. if (!NT_SUCCESS (ntStatus))
  176. {
  177. DOUT (DBG_ERROR, ("Probing of hardware configuration failed!"));
  178. return ntStatus;
  179. }
  180. //
  181. // Now, every AC97 read access goes to the cache.
  182. //
  183. m_bDirectRead = FALSE;
  184. //
  185. // Restore the AC97 registers now.
  186. //
  187. #if (DBG)
  188. DumpConfig ();
  189. #endif
  190. ntStatus = SetAC97Default ();
  191. //
  192. // Initialize the device state.
  193. //
  194. m_PowerState = PowerDeviceD0;
  195. return ntStatus;
  196. }
  197. /*****************************************************************************
  198. * CAdapterCommon::~CAdapterCommon
  199. *****************************************************************************
  200. * Destructor.
  201. */
  202. CAdapterCommon::~CAdapterCommon ()
  203. {
  204. PAGED_CODE ();
  205. DOUT (DBG_PRINT, ("[CAdapterCommon::~CAdapterCommon]"));
  206. }
  207. #if (DBG)
  208. /*****************************************************************************
  209. * CAdapterCommon::DumpConfig
  210. *****************************************************************************
  211. * Dumps the HW configuration for the AC97 codec.
  212. */
  213. void CAdapterCommon::DumpConfig (void)
  214. {
  215. PAGED_CODE ();
  216. DOUT (DBG_PRINT, ("[CAdapterCommon::DumpConfig]"));
  217. //
  218. // Print debug output for MICIN.
  219. //
  220. if (GetPinConfig (PINC_MICIN_PRESENT))
  221. {
  222. DOUT (DBG_PROBE, ("MICIN found"));
  223. }
  224. else
  225. {
  226. DOUT (DBG_PROBE, ("No MICIN found"));
  227. }
  228. //
  229. // Print debug output for tone controls.
  230. //
  231. if (GetNodeConfig (NODEC_TONE_PRESENT))
  232. {
  233. DOUT (DBG_PROBE, ("Tone controls found"));
  234. }
  235. else
  236. {
  237. DOUT (DBG_PROBE, ("No tone controls found"));
  238. }
  239. //
  240. // Print debug output for mono out.
  241. //
  242. if (!GetPinConfig (PINC_MONOOUT_PRESENT))
  243. {
  244. DOUT (DBG_PROBE, ("No mono out found"));
  245. }
  246. //
  247. // Print debug output for headphones.
  248. //
  249. if (!GetPinConfig (PINC_HPOUT_PRESENT))
  250. {
  251. DOUT (DBG_PROBE, ("No headphone out found"));
  252. }
  253. //
  254. // Print debug output for loudness.
  255. //
  256. if (GetNodeConfig (NODEC_LOUDNESS_PRESENT))
  257. {
  258. DOUT (DBG_PROBE, ("Loudness found"));
  259. }
  260. else
  261. {
  262. DOUT (DBG_PROBE, ("No Loudness found"));
  263. }
  264. //
  265. // Print debug output for 3D.
  266. //
  267. if (GetNodeConfig (NODEC_3D_PRESENT))
  268. {
  269. DOUT (DBG_PROBE, ("3D controls found"));
  270. }
  271. else
  272. {
  273. DOUT (DBG_PROBE, ("No 3D controls found"));
  274. }
  275. //
  276. // Print debug output for pc beep.
  277. //
  278. if (GetPinConfig (PINC_PCBEEP_PRESENT))
  279. {
  280. DOUT (DBG_PROBE, ("PC beep found"));
  281. }
  282. else
  283. {
  284. DOUT (DBG_PROBE, ("No PC beep found"));
  285. }
  286. //
  287. // Print debug output for phone line (or mono line input).
  288. //
  289. if (GetPinConfig (PINC_PHONE_PRESENT))
  290. {
  291. DOUT (DBG_PROBE, ("Phone found"));
  292. }
  293. else
  294. {
  295. DOUT (DBG_PROBE, ("No Phone found"));
  296. }
  297. //
  298. // Print debug output for video.
  299. //
  300. if (GetPinConfig (PINC_VIDEO_PRESENT))
  301. {
  302. DOUT (DBG_PROBE, ("Video in found"));
  303. }
  304. else
  305. {
  306. DOUT (DBG_PROBE, ("No Video in found"));
  307. }
  308. //
  309. // Print debug output for AUX.
  310. //
  311. if (GetPinConfig (PINC_AUX_PRESENT))
  312. {
  313. DOUT (DBG_PROBE, ("AUX in found"));
  314. }
  315. else
  316. {
  317. DOUT (DBG_PROBE, ("No AUX in found"));
  318. }
  319. //
  320. // Print debug output for second miorophone.
  321. //
  322. if (GetPinConfig (PINC_MIC2_PRESENT))
  323. {
  324. DOUT (DBG_PROBE, ("MIC2 found"));
  325. }
  326. else
  327. {
  328. DOUT (DBG_PROBE, ("No MIC2 found"));
  329. }
  330. //
  331. // Print debug output for 3D stuff.
  332. //
  333. if (GetNodeConfig (NODEC_3D_PRESENT))
  334. {
  335. if (GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
  336. {
  337. DOUT (DBG_PROBE, ("Adjustable 3D center control found"));
  338. }
  339. if (GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE))
  340. {
  341. DOUT (DBG_PROBE, ("Nonadjustable 3D depth control found"));
  342. }
  343. }
  344. //
  345. // Print debug output for quality of master volume.
  346. //
  347. if (GetNodeConfig (NODEC_6BIT_MASTER_VOLUME))
  348. {
  349. DOUT (DBG_PROBE, ("6bit master out found"));
  350. }
  351. else
  352. {
  353. DOUT (DBG_PROBE, ("5bit master out found"));
  354. }
  355. //
  356. // Print debug output for quality of headphones volume.
  357. //
  358. if (GetPinConfig (PINC_HPOUT_PRESENT))
  359. {
  360. if (GetNodeConfig (NODEC_6BIT_HPOUT_VOLUME))
  361. {
  362. DOUT (DBG_PROBE, ("6bit headphone out found"));
  363. }
  364. else
  365. {
  366. DOUT (DBG_PROBE, ("5bit headphone out found"));
  367. }
  368. }
  369. //
  370. // Print debug output for quality of mono out volume.
  371. //
  372. if (GetPinConfig (PINC_MONOOUT_PRESENT))
  373. {
  374. if (GetNodeConfig (NODEC_6BIT_MONOOUT_VOLUME))
  375. {
  376. DOUT (DBG_PROBE, ("6bit mono out found"));
  377. }
  378. else
  379. {
  380. DOUT (DBG_PROBE, ("5bit mono out found"));
  381. }
  382. }
  383. //
  384. // Print sample rate information.
  385. //
  386. if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
  387. {
  388. DOUT (DBG_PROBE, ("PCM variable sample rate supported"));
  389. }
  390. else
  391. {
  392. DOUT (DBG_PROBE, ("only 48KHz PCM supported"));
  393. }
  394. //
  395. // Print double rate information.
  396. //
  397. if (GetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED))
  398. {
  399. DOUT (DBG_PROBE, ("PCM double sample rate supported"));
  400. }
  401. //
  402. // Print mic rate information.
  403. //
  404. if (GetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED))
  405. {
  406. DOUT (DBG_PROBE, ("MIC variable sample rate supported"));
  407. }
  408. else
  409. {
  410. DOUT (DBG_PROBE, ("only 48KHz MIC supported"));
  411. }
  412. // print DAC information
  413. if (GetNodeConfig (NODEC_CENTER_DAC_PRESENT))
  414. {
  415. DOUT (DBG_PROBE, ("center DAC found"));
  416. }
  417. if (GetNodeConfig (NODEC_SURROUND_DAC_PRESENT))
  418. {
  419. DOUT (DBG_PROBE, ("surround DAC found"));
  420. }
  421. if (GetNodeConfig (NODEC_LFE_DAC_PRESENT))
  422. {
  423. DOUT (DBG_PROBE, ("LFE DAC found"));
  424. }
  425. }
  426. #endif
  427. /*****************************************************************************
  428. * CAdapterCommon::NonDelegatingQueryInterface
  429. *****************************************************************************
  430. * Obtains an interface. This function works just like a COM QueryInterface
  431. * call and is used if the object is not being aggregated.
  432. * We basically just check any GUID we know and return this object in case we
  433. * know it.
  434. */
  435. STDMETHODIMP_(NTSTATUS) CAdapterCommon::NonDelegatingQueryInterface
  436. (
  437. IN REFIID Interface,
  438. OUT PVOID * Object
  439. )
  440. {
  441. PAGED_CODE ();
  442. ASSERT (Object);
  443. DOUT (DBG_PRINT, ("[CAdapterCommon::NonDelegatingQueryInterface]"));
  444. // Is it IID_IUnknown?
  445. if (IsEqualGUIDAligned (Interface, IID_IUnknown))
  446. {
  447. *Object = (PVOID)(PUNKNOWN)(PADAPTERCOMMON)this;
  448. }
  449. else
  450. // or IID_IAdapterCommon ...
  451. if (IsEqualGUIDAligned (Interface, IID_IAdapterCommon))
  452. {
  453. *Object = (PVOID)(PADAPTERCOMMON)this;
  454. }
  455. else
  456. // or IID_IAdapterPowerManagement ...
  457. if (IsEqualGUIDAligned (Interface, IID_IAdapterPowerManagement))
  458. {
  459. *Object = (PVOID)(PADAPTERPOWERMANAGEMENT)this;
  460. }
  461. else
  462. {
  463. // nothing found, must be an unknown interface.
  464. *Object = NULL;
  465. return STATUS_INVALID_PARAMETER;
  466. }
  467. //
  468. // We reference the interface for the caller.
  469. //
  470. ((PUNKNOWN)*Object)->AddRef ();
  471. return STATUS_SUCCESS;
  472. }
  473. /*****************************************************************************
  474. * CAdapterCommon::InitAC97
  475. *****************************************************************************
  476. * Initialize the ICH (without hosing the modem if it got installed first).
  477. */
  478. NTSTATUS CAdapterCommon::InitAC97 (void)
  479. {
  480. PAGED_CODE ();
  481. DOUT (DBG_PRINT, ("[CAdapterCommon::InitAC97]"));
  482. //
  483. // First check if there is an AC link to the primary CoDec.
  484. //
  485. NTSTATUS ntStatus = PrimaryCodecReady ();
  486. if (NT_SUCCESS (ntStatus))
  487. {
  488. //
  489. // Second, reset this primary CoDec; If this is a AMC97 CoDec, only
  490. // the audio registers are reset. If this is a MC97 CoDec, the CoDec
  491. // should ignore the reset (according to the spec).
  492. //
  493. WriteCodecRegister (AC97REG_RESET, 0x00, -1);
  494. ntStatus = PowerUpCodec ();
  495. }
  496. else
  497. {
  498. DOUT (DBG_ERROR, ("Initialization of AC97 CoDec failed."));
  499. }
  500. return ntStatus;
  501. }
  502. /*****************************************************************************
  503. * CAdapterCommon::Check6thBitSupport
  504. *****************************************************************************
  505. * Probes for 6th bit volume control support.
  506. * The passed parameters are the AC97 register that has the volume control and
  507. * the node config that should be set in this case.
  508. */
  509. NTSTATUS CAdapterCommon::Check6thBitSupport
  510. (
  511. IN AC97Register AC97Reg,
  512. IN TopoNodeConfig Config
  513. )
  514. {
  515. NTSTATUS ntStatus;
  516. WORD wCodecReg;
  517. WORD wOriginal;
  518. // Read the current value.
  519. ntStatus = ReadCodecRegister (AC97Reg, &wOriginal);
  520. if (!NT_SUCCESS (ntStatus))
  521. return ntStatus;
  522. // Write the 6th bit; for mono controls we write 0x20, for stereo
  523. // controls 0x2020.
  524. ntStatus = WriteCodecRegister (AC97Reg,
  525. (AC97Reg == AC97REG_MMONO_VOLUME) ? 0x0020 : 0x2020, -1);
  526. if (!NT_SUCCESS (ntStatus))
  527. return ntStatus;
  528. // And read back.
  529. ntStatus = ReadCodecRegister (AC97Reg, &wCodecReg);
  530. if (!NT_SUCCESS (ntStatus))
  531. return ntStatus;
  532. // Check return. For mono 0x20 and for stereo 0x2020.
  533. if (((wCodecReg & 0x0020) && (AC97Reg == AC97REG_MMONO_VOLUME)) ||
  534. (wCodecReg & 0x2020))
  535. {
  536. SetNodeConfig (Config, TRUE);
  537. }
  538. else
  539. {
  540. SetNodeConfig (Config, FALSE);
  541. }
  542. // Restore original value.
  543. WriteCodecRegister (AC97Reg, wOriginal, -1);
  544. return ntStatus;
  545. }
  546. /*****************************************************************************
  547. * CAdapterCommon::ProbeHWConfig
  548. *****************************************************************************
  549. * Probes the hardware configuration.
  550. * If this function returns with an error, then the configuration is not
  551. * complete! Probing the registers is done by reading them (and comparing with
  552. * the HW default value) or when the default is unknown, writing to them and
  553. * reading back + restoring.
  554. * Additionally, we read the registry so that a HW vendor can overwrite (means
  555. * disable) found registers in case the adapter (e.g. video) is not visible to
  556. * the user (he can't plug in a video audio there).
  557. *
  558. * This is a very long function with all of the error checking!
  559. */
  560. NTSTATUS CAdapterCommon::ProbeHWConfig (void)
  561. {
  562. PAGED_CODE ();
  563. NTSTATUS ntStatus = STATUS_SUCCESS;
  564. DWORD dwGlobalStatus;
  565. WORD wCodecID;
  566. WORD wCodecReg;
  567. DOUT (DBG_PRINT, ("[CAdapterCommon::ProbeHWConfig]"));
  568. //
  569. // Wait for the whatever 97 to complete reset and establish a link.
  570. //
  571. ntStatus = PrimaryCodecReady ();
  572. if (!NT_SUCCESS (ntStatus))
  573. return ntStatus;
  574. //
  575. // Master volume is one of the supported registers on an AC97
  576. //
  577. ntStatus = ReadCodecRegister (AC97REG_MASTER_VOLUME, &wCodecReg);
  578. if (!NT_SUCCESS (ntStatus))
  579. return ntStatus;
  580. // Default is x8000.
  581. if (wCodecReg != 0x8000)
  582. return STATUS_NO_SUCH_DEVICE;
  583. //
  584. // This gives us information about the AC97 CoDec
  585. //
  586. ntStatus = ReadCodecRegister (AC97REG_RESET, &wCodecID);
  587. if (!NT_SUCCESS (ntStatus))
  588. return ntStatus;
  589. //
  590. // Fill out the configuration stuff.
  591. //
  592. SetPinConfig (PINC_MICIN_PRESENT, wCodecID & 0x0001);
  593. // Check if OEM wants to disable MIC record line.
  594. if (DisableAC97Pin (PINC_MICIN_PRESENT))
  595. SetPinConfig (PINC_MICIN_PRESENT, FALSE);
  596. // If we still have MIC record line, enable the DAC in ext. audio register.
  597. if (GetPinConfig (PINC_MICIN_PRESENT))
  598. // Enable ADC MIC.
  599. WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, 0, 0x4000);
  600. else
  601. // Disable ADC MIC.
  602. WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, 0x4000, 0x4000);
  603. //
  604. // Continue setting configuration information.
  605. //
  606. SetNodeConfig (NODEC_TONE_PRESENT, wCodecID & 0x0004);
  607. SetNodeConfig (NODEC_SIMUL_STEREO_PRESENT, wCodecID & 0x0008);
  608. SetPinConfig (PINC_HPOUT_PRESENT, wCodecID & 0x0010);
  609. // Check if OEM wants to disable headphone output.
  610. if (DisableAC97Pin (PINC_HPOUT_PRESENT))
  611. SetPinConfig (PINC_HPOUT_PRESENT, FALSE);
  612. SetNodeConfig (NODEC_LOUDNESS_PRESENT, wCodecID & 0x0020);
  613. SetNodeConfig (NODEC_3D_PRESENT, wCodecID & 0x7C00);
  614. //
  615. // Test for the input pins that are always there but could be disabled
  616. // by the HW vender
  617. //
  618. // Check if OEM wants to disable mic input.
  619. SetPinConfig (PINC_MIC_PRESENT, !DisableAC97Pin (PINC_MIC_PRESENT));
  620. // Check if OEM wants to disable line input.
  621. SetPinConfig (PINC_LINEIN_PRESENT, !DisableAC97Pin (PINC_LINEIN_PRESENT));
  622. // Check if OEM wants to disable CD input.
  623. SetPinConfig (PINC_CD_PRESENT, !DisableAC97Pin (PINC_CD_PRESENT));
  624. //
  625. // For the rest, we have to probe the registers.
  626. //
  627. //
  628. // Test for Mono out.
  629. //
  630. ntStatus = ReadCodecRegister (AC97REG_MMONO_VOLUME, &wCodecReg);
  631. if (!NT_SUCCESS (ntStatus))
  632. return ntStatus;
  633. // Default is x8000.
  634. SetPinConfig (PINC_MONOOUT_PRESENT, (wCodecReg == 0x8000));
  635. // Check if OEM wants to disable mono output.
  636. if (DisableAC97Pin (PINC_MONOOUT_PRESENT))
  637. SetPinConfig (PINC_MONOOUT_PRESENT, FALSE);
  638. //
  639. // Test for PC beeper support.
  640. //
  641. ntStatus = ReadCodecRegister (AC97REG_BEEP_VOLUME, &wCodecReg);
  642. if (!NT_SUCCESS (ntStatus))
  643. return ntStatus;
  644. // default is x0 or x8000. If it's 0x8000 then we know for sure that the
  645. // CoDec has a PcBeep, otherwise we have to check the register
  646. if (wCodecReg == 0x8000)
  647. SetPinConfig (PINC_PCBEEP_PRESENT, TRUE);
  648. else if (!wCodecReg)
  649. {
  650. // mute the pc beeper.
  651. ntStatus = WriteCodecRegister (AC97REG_BEEP_VOLUME, 0x8000, -1);
  652. if (!NT_SUCCESS (ntStatus))
  653. return ntStatus;
  654. // read back
  655. ntStatus = ReadCodecRegister (AC97REG_BEEP_VOLUME, &wCodecReg);
  656. if (!NT_SUCCESS (ntStatus))
  657. return ntStatus;
  658. if (wCodecReg == 0x8000)
  659. {
  660. // yep, we have support.
  661. SetPinConfig (PINC_PCBEEP_PRESENT, TRUE);
  662. // reset to default value.
  663. WriteCodecRegister (AC97REG_BEEP_VOLUME, 0x0, -1);
  664. }
  665. else
  666. // nope, not present
  667. SetPinConfig (PINC_PCBEEP_PRESENT, FALSE);
  668. }
  669. else
  670. // any other value then 0x0 and 0x8000.
  671. SetPinConfig (PINC_PCBEEP_PRESENT, FALSE);
  672. // Check if OEM wants to disable beeper support.
  673. if (DisableAC97Pin (PINC_PCBEEP_PRESENT))
  674. SetPinConfig (PINC_PCBEEP_PRESENT, FALSE);
  675. //
  676. // Test for phone support.
  677. //
  678. ntStatus = ReadCodecRegister (AC97REG_PHONE_VOLUME, &wCodecReg);
  679. if (!NT_SUCCESS (ntStatus))
  680. return ntStatus;
  681. // Default is x8008.
  682. SetPinConfig (PINC_PHONE_PRESENT, (wCodecReg == 0x8008));
  683. // Check if OEM wants to disable phone input.
  684. if (DisableAC97Pin (PINC_PHONE_PRESENT))
  685. SetPinConfig (PINC_PHONE_PRESENT, FALSE);
  686. //
  687. // Test for video support.
  688. //
  689. ntStatus = ReadCodecRegister (AC97REG_VIDEO_VOLUME, &wCodecReg);
  690. if (!NT_SUCCESS (ntStatus))
  691. return ntStatus;
  692. // Default is x8808.
  693. SetPinConfig (PINC_VIDEO_PRESENT, (wCodecReg == 0x8808));
  694. // Check if OEM wants to disable video input.
  695. if (DisableAC97Pin (PINC_VIDEO_PRESENT))
  696. SetPinConfig (PINC_VIDEO_PRESENT, FALSE);
  697. //
  698. // Test for Aux support.
  699. //
  700. ntStatus = ReadCodecRegister (AC97REG_AUX_VOLUME, &wCodecReg);
  701. if (!NT_SUCCESS (ntStatus))
  702. return ntStatus;
  703. // Default is 0x8808.
  704. SetPinConfig (PINC_AUX_PRESENT, (wCodecReg == 0x8808));
  705. // Check if OEM wants to disable aux input.
  706. if (DisableAC97Pin (PINC_AUX_PRESENT))
  707. SetPinConfig (PINC_AUX_PRESENT, FALSE);
  708. //
  709. // Test for Mic2 source.
  710. //
  711. ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
  712. if (!NT_SUCCESS (ntStatus))
  713. return ntStatus;
  714. // Test for Mic2 select bit.
  715. if (wCodecReg & 0x0100)
  716. SetPinConfig (PINC_MIC2_PRESENT, TRUE);
  717. else
  718. {
  719. // Select Mic2 as source.
  720. ntStatus = WriteCodecRegister (AC97REG_GENERAL, 0x0100, 0x0100);
  721. if (!NT_SUCCESS (ntStatus))
  722. return ntStatus;
  723. // Read back.
  724. ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
  725. if (!NT_SUCCESS (ntStatus))
  726. return ntStatus;
  727. if (wCodecReg & 0x0100)
  728. {
  729. // Yep, we have support so set it to the default value.
  730. SetPinConfig (PINC_MIC2_PRESENT, TRUE);
  731. // reset to default value.
  732. WriteCodecRegister (AC97REG_GENERAL, 0, 0x0100);
  733. }
  734. else
  735. SetPinConfig (PINC_MIC2_PRESENT, FALSE);
  736. }
  737. // Check if OEM wants to disable mic2 input.
  738. if (DisableAC97Pin (PINC_MIC2_PRESENT))
  739. SetPinConfig (PINC_MIC2_PRESENT, FALSE);
  740. //
  741. // Test the 3D controls.
  742. //
  743. if (GetNodeConfig (NODEC_3D_PRESENT))
  744. {
  745. //
  746. // First test for fixed 3D controls. Write default value ...
  747. //
  748. ntStatus = WriteCodecRegister (AC97REG_3D_CONTROL, 0, -1);
  749. if (!NT_SUCCESS (ntStatus))
  750. return ntStatus;
  751. // Read 3D register. Default is 0 when adjustable, otherwise it is
  752. // a fixed value.
  753. ntStatus = ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
  754. if (!NT_SUCCESS (ntStatus))
  755. return ntStatus;
  756. //
  757. // Check center and depth separately.
  758. //
  759. // For center
  760. SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, !(wCodecReg & 0x0F00));
  761. // For depth
  762. SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, !(wCodecReg & 0x000F));
  763. //
  764. // Test for adjustable controls.
  765. //
  766. WriteCodecRegister (AC97REG_3D_CONTROL, 0x0A0A, -1);
  767. // Read 3D register. Now it should be 0x0A0A for adjustable controls,
  768. // otherwise it is a fixed control or simply not there.
  769. ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
  770. // Restore the default value
  771. WriteCodecRegister (AC97REG_3D_CONTROL, 0, -1);
  772. // Check the center control for beeing adjustable
  773. if (GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
  774. (wCodecReg & 0x0F00) != 0x0A00)
  775. {
  776. SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, FALSE);
  777. }
  778. // Check the depth control for beeing adjustable
  779. if (GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
  780. (wCodecReg & 0x000F) != 0x000A)
  781. {
  782. SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, FALSE);
  783. }
  784. }
  785. //
  786. // Check for 6th bit support in volume controls. To check the 6th bit,
  787. // we first have to write a value (with 6th bit set) and then read it
  788. // back. After that, we should restore the register to its default value.
  789. //
  790. //
  791. // Start with the master volume.
  792. //
  793. Check6thBitSupport (AC97REG_MASTER_VOLUME, NODEC_6BIT_MASTER_VOLUME);
  794. //
  795. // Check for a headphone volume control.
  796. //
  797. if (GetPinConfig (PINC_HPOUT_PRESENT))
  798. {
  799. Check6thBitSupport (AC97REG_HPHONE_VOLUME, NODEC_6BIT_HPOUT_VOLUME);
  800. }
  801. //
  802. // Mono out there?
  803. //
  804. if (GetPinConfig (PINC_MONOOUT_PRESENT))
  805. {
  806. Check6thBitSupport (AC97REG_MMONO_VOLUME, NODEC_6BIT_MONOOUT_VOLUME);
  807. }
  808. //
  809. // Get extended AC97 V2.0 information
  810. //
  811. ntStatus = ReadCodecRegister (AC97REG_EXT_AUDIO_ID, &wCodecReg);
  812. if (!NT_SUCCESS (ntStatus))
  813. return ntStatus;
  814. //
  815. // Store the information
  816. //
  817. SetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED, wCodecReg & 0x0001);
  818. SetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED, wCodecReg & 0x0002);
  819. SetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED, wCodecReg & 0x0008);
  820. SetNodeConfig (NODEC_CENTER_DAC_PRESENT, wCodecReg & 0x0040);
  821. SetNodeConfig (NODEC_SURROUND_DAC_PRESENT, wCodecReg & 0x0080);
  822. SetNodeConfig (NODEC_LFE_DAC_PRESENT, wCodecReg & 0x0100);
  823. //
  824. // In case we have some features get some more information and program
  825. // the codec.
  826. //
  827. if (wCodecReg)
  828. {
  829. //
  830. // Enable variable sample rate in the control register and disable
  831. // double rate. Also enable all DACs.
  832. //
  833. WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, wCodecReg & 0x0009, 0x380B);
  834. //
  835. // Check for codecs that have only one sample rate converter. These
  836. // codecs will stick registers AC97REG_FRONT_SAMPLERATE and
  837. // AC97REG_RECORD_SAMPLERATE together.
  838. //
  839. if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
  840. {
  841. // The default of the sample rate registers should be 0xBB80.
  842. WriteCodecRegister (AC97REG_FRONT_SAMPLERATE, 0xBB80, 0xFFFF);
  843. // Write 44.1KHz into record VSR, then check playback again.
  844. WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xAC44, 0xFFFF);
  845. ntStatus = ReadCodecRegister (AC97REG_FRONT_SAMPLERATE, &wCodecReg);
  846. WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xBB80, 0xFFFF);
  847. if (!NT_SUCCESS (ntStatus))
  848. return ntStatus;
  849. //
  850. // Set the flag accordingly
  851. //
  852. SetNodeConfig (NODEC_PCM_VSR_INDEPENDENT_RATES, (wCodecReg == 0xBB80));
  853. }
  854. //
  855. // Check multichanel support on the ICH.
  856. //
  857. if (GetNodeConfig (NODEC_SURROUND_DAC_PRESENT))
  858. {
  859. dwGlobalStatus = ReadBMControlRegister32 (GLOB_STA);
  860. //
  861. // Codec supports >2 chanel, does ICH too?
  862. //
  863. if ((GetNodeConfig (NODEC_CENTER_DAC_PRESENT) ||
  864. GetNodeConfig (NODEC_LFE_DAC_PRESENT)) &&
  865. (dwGlobalStatus & GLOB_STA_MC6))
  866. {
  867. SetPinConfig (PINC_CENTER_LFE_PRESENT, TRUE);
  868. }
  869. else
  870. {
  871. SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
  872. }
  873. //
  874. // Do we support at least 4 channels?
  875. //
  876. SetPinConfig (PINC_SURROUND_PRESENT, (dwGlobalStatus & GLOB_STA_MC4));
  877. }
  878. else
  879. {
  880. //
  881. // Only 2 channel (stereo) support.
  882. //
  883. SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
  884. SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
  885. }
  886. }
  887. // Check if OEM wants to disable surround output.
  888. if (DisableAC97Pin (PINC_SURROUND_PRESENT))
  889. SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
  890. // Check if OEM wants to disable center and LFE output.
  891. if (DisableAC97Pin (PINC_CENTER_LFE_PRESENT))
  892. SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
  893. //
  894. // Check the 6th bit support for the additional channels.
  895. //
  896. if (GetPinConfig (PINC_SURROUND_PRESENT))
  897. Check6thBitSupport (AC97REG_SURROUND_VOLUME, NODEC_6BIT_SURROUND_VOLUME);
  898. if (GetPinConfig (PINC_CENTER_LFE_PRESENT))
  899. Check6thBitSupport (AC97REG_CENTER_LFE_VOLUME, NODEC_6BIT_CENTER_LFE_VOLUME);
  900. //
  901. // We read these registers because they are dependent on the codec.
  902. //
  903. ReadCodecRegister (AC97REG_VENDOR_ID1, &wCodecReg);
  904. ReadCodecRegister (AC97REG_VENDOR_ID2, &wCodecReg);
  905. return STATUS_SUCCESS;
  906. }
  907. /*****************************************************************************
  908. * CAdapterCommon::AcquireCodecSemiphore
  909. *****************************************************************************
  910. * Acquires the AC97 semiphore. This can not be called at dispatch level
  911. * because it can timeout if a lower IRQL thread has the semaphore.
  912. */
  913. NTSTATUS CAdapterCommon::AcquireCodecSemiphore ()
  914. {
  915. PAGED_CODE ();
  916. DOUT (DBG_PRINT, ("[CAdapterCommon::AcquireCodecSemiphore]"));
  917. ULONG ulCount = 0;
  918. while (READ_PORT_UCHAR (m_pBusMasterBase + CAS) & CAS_CAS)
  919. {
  920. //
  921. // Do we want to give up??
  922. //
  923. if (ulCount++ > 100)
  924. {
  925. DOUT (DBG_ERROR, ("Cannot acquire semaphore."));
  926. return STATUS_IO_TIMEOUT;
  927. }
  928. //
  929. // Let's wait a little, 40us and then try again.
  930. //
  931. KeStallExecutionProcessor (40L);
  932. }
  933. return STATUS_SUCCESS;
  934. }
  935. /*****************************************************************************
  936. * CAdapterCommon::ReadCodecRegister
  937. *****************************************************************************
  938. * Reads a AC97 register. Don't call at PASSIVE_LEVEL.
  939. */
  940. STDMETHODIMP_(NTSTATUS) CAdapterCommon::ReadCodecRegister
  941. (
  942. IN AC97Register reg,
  943. OUT PWORD wData
  944. )
  945. {
  946. PAGED_CODE ();
  947. ASSERT (wData);
  948. ASSERT (reg < AC97REG_INVALID); // audio can only be in the primary codec
  949. NTSTATUS ntStatus;
  950. ULONG Status;
  951. DOUT (DBG_PRINT, ("[CAdapterCommon::ReadCodecRegister]"));
  952. //
  953. // Check if we have to access the HW directly.
  954. //
  955. if (m_bDirectRead || (m_stAC97Registers[reg].wFlags & SHREG_INVALID) ||
  956. (m_stAC97Registers[reg].wFlags & SHREG_NOCACHE))
  957. {
  958. //
  959. // Grab the codec access semiphore.
  960. //
  961. ntStatus = AcquireCodecSemiphore ();
  962. if (!NT_SUCCESS (ntStatus))
  963. {
  964. DOUT (DBG_ERROR, ("ReadCodecRegister couldn't acquire the semiphore"
  965. " for reg. %s", reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
  966. reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
  967. reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
  968. "REG_INVALID"));
  969. return ntStatus;
  970. }
  971. //
  972. // Read the data.
  973. //
  974. *wData = READ_PORT_USHORT (m_pCodecBase + reg);
  975. //
  976. // Check to see if the read was successful.
  977. //
  978. Status = READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA));
  979. if (Status & GLOB_STA_RCS)
  980. {
  981. //
  982. // clear the timeout bit
  983. //
  984. WRITE_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA), Status);
  985. *wData = 0;
  986. DOUT (DBG_ERROR, ("ReadCodecRegister timed out for register %s",
  987. reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
  988. reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
  989. reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
  990. "REG_INVALID"));
  991. return STATUS_IO_TIMEOUT;
  992. }
  993. //
  994. // Clear invalid flag
  995. //
  996. m_stAC97Registers[reg].wCache = *wData;
  997. m_stAC97Registers[reg].wFlags &= ~SHREG_INVALID;
  998. DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (HW)",
  999. reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
  1000. reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
  1001. reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
  1002. "REG_INVALID", *wData));
  1003. }
  1004. else
  1005. {
  1006. //
  1007. // Otherwise, use the value in the cache.
  1008. //
  1009. *wData = m_stAC97Registers[reg].wCache;
  1010. DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (C)",
  1011. reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
  1012. reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
  1013. reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
  1014. "REG_INVALID", *wData));
  1015. }
  1016. return STATUS_SUCCESS;
  1017. }
  1018. /*****************************************************************************
  1019. * CAdapterCommon::WriteCodecRegister
  1020. *****************************************************************************
  1021. * Writes to a AC97 register. This can only be done at passive level because
  1022. * the AcquireCodecSemiphore call could fail!
  1023. */
  1024. STDMETHODIMP_(NTSTATUS) CAdapterCommon::WriteCodecRegister
  1025. (
  1026. IN AC97Register reg,
  1027. IN WORD wData,
  1028. IN WORD wMask
  1029. )
  1030. {
  1031. PAGED_CODE ();
  1032. ASSERT (reg < AC97REG_INVALID); // audio can only be in the primary codec
  1033. WORD TempData = 0;
  1034. NTSTATUS ntStatus = STATUS_SUCCESS;
  1035. DOUT (DBG_PRINT, ("[CAdapterCommon::WriteCodecRegister]"));
  1036. //
  1037. // No mask? Could happen when you try to prg. left channel of a
  1038. // mono volume.
  1039. //
  1040. if (!wMask)
  1041. return STATUS_SUCCESS;
  1042. //
  1043. // Check to see if we are only writing specific bits. If so, we want
  1044. // to leave some bits in the register alone.
  1045. //
  1046. if (wMask != 0xffff)
  1047. {
  1048. //
  1049. // Read the current register contents.
  1050. //
  1051. ntStatus = ReadCodecRegister (reg, &TempData);
  1052. if (!NT_SUCCESS (ntStatus))
  1053. {
  1054. DOUT (DBG_ERROR, ("WriteCodecRegiser read for mask failed"));
  1055. return ntStatus;
  1056. }
  1057. //
  1058. // Do the masking.
  1059. //
  1060. TempData &= ~wMask;
  1061. TempData |= (wMask & wData);
  1062. }
  1063. else
  1064. {
  1065. TempData = wData;
  1066. }
  1067. //
  1068. // Grab the codec access semiphore.
  1069. //
  1070. ntStatus = AcquireCodecSemiphore ();
  1071. if (!NT_SUCCESS (ntStatus))
  1072. {
  1073. DOUT (DBG_ERROR, ("WriteCodecRegister failed for register %s",
  1074. reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
  1075. reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
  1076. reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" : "REG_INVALID"));
  1077. return ntStatus;
  1078. }
  1079. //
  1080. // Write the data.
  1081. //
  1082. WRITE_PORT_USHORT (m_pCodecBase + reg, TempData);
  1083. //
  1084. // Update cache.
  1085. //
  1086. m_stAC97Registers[reg].wCache = TempData;
  1087. DOUT (DBG_REGS, ("AC97WRITE: %s -> 0x%04x",
  1088. reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
  1089. reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
  1090. reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
  1091. "REG_INVALID", TempData));
  1092. return STATUS_SUCCESS;
  1093. }
  1094. /*****************************************************************************
  1095. * CAdapterCommon::PrimaryCodecReady
  1096. *****************************************************************************
  1097. * Checks whether the primary codec is present and ready. This may take
  1098. * awhile if we are bringing it up from a cold reset so give it a second
  1099. * before giving up.
  1100. */
  1101. NTSTATUS CAdapterCommon::PrimaryCodecReady (void)
  1102. {
  1103. PAGED_CODE ();
  1104. DOUT (DBG_PRINT, ("[CAdapterCommon::PrimaryCodecReady]"));
  1105. //
  1106. // Enable the AC link and raise the reset line.
  1107. //
  1108. DWORD dwRegValue = ReadBMControlRegister32 (GLOB_CNT);
  1109. // If someone enabled GPI Interrupt Enable, then he hopefully handles that
  1110. // too.
  1111. dwRegValue = (dwRegValue | GLOB_CNT_COLD) & ~(GLOB_CNT_ACLOFF | GLOB_CNT_PRIE);
  1112. WriteBMControlRegister (GLOB_CNT, dwRegValue);
  1113. //
  1114. // Wait for the Codec to be ready.
  1115. //
  1116. ULONG WaitCycles = 200;
  1117. LARGE_INTEGER WaitTime = RtlConvertLongToLargeInteger (-50000); // wait 5000us (5ms) relative
  1118. do
  1119. {
  1120. if (READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA)) &
  1121. GLOB_STA_PCR)
  1122. {
  1123. return STATUS_SUCCESS;
  1124. }
  1125. KeDelayExecutionThread (KernelMode, FALSE, &WaitTime);
  1126. } while (WaitCycles--);
  1127. DOUT (DBG_ERROR, ("PrimaryCodecReady timed out!"));
  1128. return STATUS_IO_TIMEOUT;
  1129. }
  1130. /*****************************************************************************
  1131. * CAdapterCommon::PowerUpCodec
  1132. *****************************************************************************
  1133. * Sets the Codec to the highest power state and waits until the Codec reports
  1134. * that the power state is reached.
  1135. */
  1136. NTSTATUS CAdapterCommon::PowerUpCodec (void)
  1137. {
  1138. PAGED_CODE ();
  1139. WORD wCodecReg;
  1140. NTSTATUS ntStatus;
  1141. DOUT (DBG_PRINT, ("[CAdapterCommon::PowerUpCodec]"));
  1142. //
  1143. // Power up the Codec.
  1144. //
  1145. WriteCodecRegister (AC97REG_POWERDOWN, 0x00, -1);
  1146. //
  1147. // Wait for the Codec to be powered up.
  1148. //
  1149. ULONG WaitCycles = 200;
  1150. LARGE_INTEGER WaitTime = RtlConvertLongToLargeInteger (-50000); // wait 5000us (5ms) relative
  1151. do
  1152. {
  1153. //
  1154. // Read the power management register.
  1155. //
  1156. ntStatus = ReadCodecRegister (AC97REG_POWERDOWN, &wCodecReg);
  1157. if (!NT_SUCCESS (ntStatus))
  1158. {
  1159. wCodecReg = 0; // Will cause an error.
  1160. break;
  1161. }
  1162. //
  1163. // Check the power state. Should be ready.
  1164. //
  1165. if ((wCodecReg & 0x0f) == 0x0f)
  1166. break;
  1167. //
  1168. // Let's wait a little, 5ms and then try again.
  1169. //
  1170. KeDelayExecutionThread (KernelMode, FALSE, &WaitTime);
  1171. } while (WaitCycles--);
  1172. // Check if we timed out.
  1173. if ((wCodecReg & 0x0f) != 0x0f)
  1174. {
  1175. DOUT (DBG_ERROR, ("PowerUpCodec timed out. CoDec not powered up."));
  1176. ntStatus = STATUS_DEVICE_NOT_READY;
  1177. }
  1178. return ntStatus;
  1179. }
  1180. /*****************************************************************************
  1181. * CAdapterCommon::ProgramSampleRate
  1182. *****************************************************************************
  1183. * Programs the sample rate. If the rate cannot be programmed, the routine
  1184. * restores the register and returns STATUS_UNSUCCESSFUL.
  1185. * We don't handle double rate sample rates here, because the Intel ICH con-
  1186. * troller cannot serve CoDecs with double rate or surround sound. If you want
  1187. * to modify this driver for another AC97 controller, then you might want to
  1188. * change this function too.
  1189. */
  1190. STDMETHODIMP_(NTSTATUS) CAdapterCommon::ProgramSampleRate
  1191. (
  1192. IN AC97Register Register,
  1193. IN DWORD dwSampleRate
  1194. )
  1195. {
  1196. PAGED_CODE ();
  1197. WORD wOldRateReg, wCodecReg;
  1198. NTSTATUS ntStatus;
  1199. DOUT (DBG_PRINT, ("[CAdapterCommon::ProgramSampleRate]"));
  1200. //
  1201. // Check if we support variable sample rate.
  1202. //
  1203. switch(Register)
  1204. {
  1205. case AC97REG_MIC_SAMPLERATE:
  1206. //
  1207. // Variable sample rate supported?
  1208. //
  1209. if (GetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED))
  1210. {
  1211. // Range supported?
  1212. if (dwSampleRate > 48000ul)
  1213. {
  1214. // Not possible.
  1215. DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
  1216. return STATUS_NOT_SUPPORTED;
  1217. }
  1218. }
  1219. else
  1220. {
  1221. // Only 48000KHz possible.
  1222. if (dwSampleRate != 48000ul)
  1223. {
  1224. DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
  1225. return STATUS_NOT_SUPPORTED;
  1226. }
  1227. return STATUS_SUCCESS;
  1228. }
  1229. break;
  1230. case AC97REG_FRONT_SAMPLERATE:
  1231. case AC97REG_SURROUND_SAMPLERATE:
  1232. case AC97REG_LFE_SAMPLERATE:
  1233. case AC97REG_RECORD_SAMPLERATE:
  1234. //
  1235. // Variable sample rate supported?
  1236. //
  1237. if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
  1238. {
  1239. //
  1240. // Check range supported
  1241. //
  1242. if (dwSampleRate > 48000ul)
  1243. {
  1244. DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
  1245. return STATUS_NOT_SUPPORTED;
  1246. }
  1247. }
  1248. else
  1249. {
  1250. // Only 48KHz possible.
  1251. if (dwSampleRate != 48000ul)
  1252. {
  1253. DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
  1254. return STATUS_NOT_SUPPORTED;
  1255. }
  1256. return STATUS_SUCCESS;
  1257. }
  1258. break;
  1259. default:
  1260. DOUT (DBG_ERROR, ("Invalid sample rate register!"));
  1261. return STATUS_UNSUCCESSFUL;
  1262. }
  1263. //
  1264. // Save the old sample rate register.
  1265. //
  1266. ntStatus = ReadCodecRegister (Register, &wOldRateReg);
  1267. if (!NT_SUCCESS (ntStatus))
  1268. return ntStatus;
  1269. //
  1270. // program the rate.
  1271. //
  1272. ntStatus = WriteCodecRegister (Register, (WORD)dwSampleRate, -1);
  1273. if (!NT_SUCCESS (ntStatus))
  1274. {
  1275. DOUT (DBG_ERROR, ("Cannot program sample rate."));
  1276. return ntStatus;
  1277. }
  1278. //
  1279. // Read it back.
  1280. //
  1281. ntStatus = ReadCodecRegister (Register, &wCodecReg);
  1282. if (!NT_SUCCESS (ntStatus))
  1283. {
  1284. DOUT (DBG_ERROR, ("Cannot read sample rate."));
  1285. return ntStatus;
  1286. }
  1287. //
  1288. // Validate.
  1289. //
  1290. if (wCodecReg != dwSampleRate)
  1291. {
  1292. //
  1293. // restore sample rate and ctrl register.
  1294. //
  1295. WriteCodecRegister (Register, wOldRateReg, -1);
  1296. DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
  1297. return STATUS_NOT_SUPPORTED;
  1298. }
  1299. DOUT (DBG_VSR, ("Samplerate changed to %d.", dwSampleRate));
  1300. return STATUS_SUCCESS;
  1301. }
  1302. /*****************************************************************************
  1303. * CAdapterCommon::PowerChangeState
  1304. *****************************************************************************
  1305. * Change power state for the device. We handle the codec, PowerChangeNotify
  1306. * in the wave miniport handles the DMA registers.
  1307. */
  1308. STDMETHODIMP_(void) CAdapterCommon::PowerChangeState
  1309. (
  1310. IN POWER_STATE NewState
  1311. )
  1312. {
  1313. PAGED_CODE ();
  1314. NTSTATUS ntStatus = STATUS_SUCCESS;
  1315. DOUT (DBG_PRINT, ("[CAdapterCommon::PowerChangeNotify]"));
  1316. //
  1317. // Check to see if this is the current power state.
  1318. //
  1319. if (NewState.DeviceState == m_PowerState)
  1320. {
  1321. DOUT (DBG_POWER, ("New device state equals old state."));
  1322. return;
  1323. }
  1324. //
  1325. // Check the new device state.
  1326. //
  1327. if ((NewState.DeviceState < PowerDeviceD0) ||
  1328. (NewState.DeviceState > PowerDeviceD3))
  1329. {
  1330. DOUT (DBG_ERROR, ("Unknown device state: D%d.",
  1331. (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
  1332. return;
  1333. }
  1334. DOUT (DBG_POWER, ("Changing state to D%d.", (ULONG)NewState.DeviceState -
  1335. (ULONG)PowerDeviceD0));
  1336. //
  1337. // Switch on new state.
  1338. //
  1339. switch (NewState.DeviceState)
  1340. {
  1341. case PowerDeviceD0:
  1342. //
  1343. // If we are coming from D2 or D3 we have to restore the registers cause
  1344. // there might have been a power loss.
  1345. //
  1346. if ((m_PowerState == PowerDeviceD3) || (m_PowerState == PowerDeviceD2))
  1347. {
  1348. //
  1349. // Reset AD3 to indicate that we are now awake.
  1350. // Because the system has only one power irp at a time, we are sure
  1351. // that the modem driver doesn't get called while we are restoring
  1352. // power.
  1353. //
  1354. WriteBMControlRegister (GLOB_STA,
  1355. ReadBMControlRegister32 (GLOB_STA) & ~GLOB_STA_AD3);
  1356. //
  1357. // Restore codec registers.
  1358. //
  1359. ntStatus = RestoreCodecRegisters ();
  1360. }
  1361. else // We are coming from power state D1
  1362. {
  1363. ntStatus = PowerUpCodec ();
  1364. }
  1365. // Print error code.
  1366. if (!NT_SUCCESS (ntStatus))
  1367. {
  1368. DOUT (DBG_ERROR, ("PowerChangeState failed to restore the codec."));
  1369. }
  1370. break;
  1371. case PowerDeviceD1:
  1372. //
  1373. // This sleep state is the lowest latency sleep state with respect
  1374. // to the latency time required to return to D0. If the
  1375. // driver is not being used an inactivity timer in portcls will
  1376. // place the driver in this state after a timeout period
  1377. // controllable via the registry.
  1378. //
  1379. // Let's power down the DAC/ADC's and analog mixer.
  1380. WriteCodecRegister (AC97REG_POWERDOWN, 0x0700, -1);
  1381. break;
  1382. case PowerDeviceD2:
  1383. case PowerDeviceD3:
  1384. //
  1385. // This is a full hibernation state and is the longest latency sleep
  1386. // state. In this modes the power could be removed or reduced that
  1387. // much that the AC97 controller looses information, so we save
  1388. // whatever we have to save.
  1389. //
  1390. //
  1391. // Powerdown ADC, DAC, Mixer, Vref, HP amp, and Exernal Amp but not
  1392. // AC-link and Clk
  1393. //
  1394. WriteCodecRegister (AC97REG_POWERDOWN, 0xCF00, -1);
  1395. //
  1396. // Only in D3 mode we set the AD3 bit and evtl. shut off the AC link.
  1397. //
  1398. if (NewState.DeviceState == PowerDeviceD3)
  1399. {
  1400. //
  1401. // Set the AD3 bit.
  1402. //
  1403. ULONG ulReg = ReadBMControlRegister32 (GLOB_STA);
  1404. WriteBMControlRegister (GLOB_STA, ulReg | GLOB_STA_AD3);
  1405. //
  1406. // We check if the modem is sleeping. If it is, we can shut off the
  1407. // AC link also. We shut off the AC link also if the modem is not
  1408. // there.
  1409. //
  1410. if ((ulReg & GLOB_STA_MD3) || !(ulReg & GLOB_STA_SCR))
  1411. {
  1412. // Set Codec to super sleep
  1413. WriteCodecRegister (AC97REG_POWERDOWN, 0xFF00, -1);
  1414. // Disable the AC-link signals
  1415. ulReg = ReadBMControlRegister32 (GLOB_CNT);
  1416. WriteBMControlRegister (GLOB_CNT, (ulReg | GLOB_CNT_ACLOFF) & ~GLOB_CNT_COLD);
  1417. }
  1418. }
  1419. break;
  1420. }
  1421. //
  1422. // Save the new state. This local value is used to determine when to
  1423. // cache property accesses and when to permit the driver from accessing
  1424. // the hardware.
  1425. //
  1426. m_PowerState = NewState.DeviceState;
  1427. DOUT (DBG_POWER, ("Entering D%d", (ULONG)m_PowerState -
  1428. (ULONG)PowerDeviceD0));
  1429. }
  1430. /*****************************************************************************
  1431. * CAdapterCommon::QueryPowerChangeState
  1432. *****************************************************************************
  1433. * Query to see if the device can change to this power state
  1434. */
  1435. STDMETHODIMP_(NTSTATUS) CAdapterCommon::QueryPowerChangeState
  1436. (
  1437. IN POWER_STATE NewState
  1438. )
  1439. {
  1440. PAGED_CODE ();
  1441. DOUT (DBG_PRINT, ("[CAdapterCommon::QueryPowerChangeState]"));
  1442. // Check here to see of a legitimate state is being requested
  1443. // based on the device state and fail the call if the device/driver
  1444. // cannot support the change requested. Otherwise, return STATUS_SUCCESS.
  1445. // Note: A QueryPowerChangeState() call is not guaranteed to always preceed
  1446. // a PowerChangeState() call.
  1447. // check the new state being requested
  1448. switch (NewState.DeviceState)
  1449. {
  1450. case PowerDeviceD0:
  1451. case PowerDeviceD1:
  1452. case PowerDeviceD2:
  1453. case PowerDeviceD3:
  1454. return STATUS_SUCCESS;
  1455. default:
  1456. DOUT (DBG_ERROR, ("Unknown device state: D%d.",
  1457. (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
  1458. return STATUS_NOT_IMPLEMENTED;
  1459. }
  1460. }
  1461. /*****************************************************************************
  1462. * CAdapterCommon::QueryDeviceCapabilities
  1463. *****************************************************************************
  1464. * Called at startup to get the caps for the device. This structure provides
  1465. * the system with the mappings between system power state and device power
  1466. * state. This typically will not need modification by the driver.
  1467. * If the driver modifies these mappings then the driver is not allowed to
  1468. * change the mapping to a weaker power state (e.g. from S1->D3 to S1->D1).
  1469. *
  1470. */
  1471. STDMETHODIMP_(NTSTATUS) CAdapterCommon::QueryDeviceCapabilities
  1472. (
  1473. IN PDEVICE_CAPABILITIES PowerDeviceCaps
  1474. )
  1475. {
  1476. PAGED_CODE ();
  1477. DOUT (DBG_PRINT, ("[CAdapterCommon::QueryDeviceCapabilities]"));
  1478. return STATUS_SUCCESS;
  1479. }
  1480. /*****************************************************************************
  1481. * CAdapterCommon::RestoreAC97Registers
  1482. *****************************************************************************
  1483. * Preset the AC97 registers with default values. The routine first checks if
  1484. * There are registry entries for the default values. If not, we have hard
  1485. * coded values too ;)
  1486. */
  1487. NTSTATUS CAdapterCommon::SetAC97Default (void)
  1488. {
  1489. PAGED_CODE ();
  1490. PREGISTRYKEY DriverKey;
  1491. PREGISTRYKEY SettingsKey;
  1492. UNICODE_STRING sKeyName;
  1493. ULONG ulDisposition;
  1494. ULONG ulResultLength;
  1495. PVOID KeyInfo = NULL;
  1496. DOUT (DBG_PRINT, ("[CAdapterCommon::SetAC97Default]"));
  1497. // open the driver registry key
  1498. NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
  1499. NULL, // OuterUnknown
  1500. DriverRegistryKey, // Registry key type
  1501. KEY_READ, // Access flags
  1502. m_pDeviceObject, // Device object
  1503. NULL, // Subdevice
  1504. NULL, // ObjectAttributes
  1505. 0, // Create options
  1506. NULL); // Disposition
  1507. if (NT_SUCCESS (ntStatus))
  1508. {
  1509. // make a unicode string for the subkey name
  1510. RtlInitUnicodeString (&sKeyName, L"Settings");
  1511. // open the settings subkey
  1512. ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
  1513. NULL, // OuterUnknown
  1514. KEY_READ, // Access flags
  1515. &sKeyName, // Subkey name
  1516. REG_OPTION_NON_VOLATILE, // Create options
  1517. &ulDisposition);
  1518. if (NT_SUCCESS (ntStatus))
  1519. {
  1520. // allocate data to hold key info
  1521. KeyInfo = ExAllocatePool (PagedPool,
  1522. sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1523. sizeof(WORD));
  1524. if (NULL != KeyInfo)
  1525. {
  1526. // loop through all mixer settings
  1527. for (AC97Register i = AC97REG_RESET; i <= AC97REG_RESERVED2;
  1528. i = (AC97Register)(i + 1))
  1529. {
  1530. if (m_stAC97Registers[i].wFlags & SHREG_INIT)
  1531. {
  1532. // init key name
  1533. RtlInitUnicodeString (&sKeyName,
  1534. m_stAC97Registers[i].sRegistryName);
  1535. // query the value key
  1536. ntStatus = SettingsKey->QueryValueKey (&sKeyName,
  1537. KeyValuePartialInformation,
  1538. KeyInfo,
  1539. sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1540. sizeof(WORD),
  1541. &ulResultLength);
  1542. if (NT_SUCCESS (ntStatus))
  1543. {
  1544. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
  1545. (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
  1546. if (PartialInfo->DataLength == sizeof(WORD))
  1547. {
  1548. // set mixer register to registry value
  1549. WriteCodecRegister
  1550. (i, *(PWORD)PartialInfo->Data, -1);
  1551. }
  1552. else // write the hard coded default
  1553. {
  1554. // if key access failed, set to default
  1555. WriteCodecRegister
  1556. (i, m_stAC97Registers[i].wWantedDefault, -1);
  1557. }
  1558. }
  1559. else // write the hard coded default
  1560. {
  1561. // if key access failed, set to default
  1562. WriteCodecRegister
  1563. (i, m_stAC97Registers[i].wWantedDefault, -1);
  1564. }
  1565. }
  1566. }
  1567. // we want to return status success even if the last QueryValueKey
  1568. // failed.
  1569. ntStatus = STATUS_SUCCESS;
  1570. // free the key info
  1571. ExFreePool (KeyInfo);
  1572. }
  1573. // release the settings key
  1574. SettingsKey->Release ();
  1575. }
  1576. // release the driver key
  1577. DriverKey->Release ();
  1578. }
  1579. // in case we did not query the registry (cause of lack of resources)
  1580. // restore default values and return insufficient resources.
  1581. if (!NT_SUCCESS (ntStatus) || !KeyInfo)
  1582. {
  1583. // copy hard coded default settings
  1584. for (AC97Register i = AC97REG_RESET; i < AC97REG_RESERVED2;
  1585. i = (AC97Register)(i + 1))
  1586. {
  1587. if (m_stAC97Registers[i].wFlags & SHREG_INIT)
  1588. {
  1589. WriteCodecRegister (i, m_stAC97Registers[i].wWantedDefault, -1);
  1590. }
  1591. }
  1592. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1593. }
  1594. return ntStatus;
  1595. }
  1596. /*****************************************************************************
  1597. * CAdapterCommon::DisableAC97Pin
  1598. *****************************************************************************
  1599. * Returns TRUE when the HW vendor wants to disable the pin. A disabled pin is
  1600. * not shown to the user (means it is not included in the topology). The
  1601. * reason for doing this could be that some of the input lines like Aux or
  1602. * Video are not available to the user (to plug in something) but the codec
  1603. * can handle those lines.
  1604. */
  1605. BOOL CAdapterCommon::DisableAC97Pin
  1606. (
  1607. IN TopoPinConfig pin
  1608. )
  1609. {
  1610. PAGED_CODE ();
  1611. PREGISTRYKEY DriverKey;
  1612. PREGISTRYKEY SettingsKey;
  1613. UNICODE_STRING sKeyName;
  1614. ULONG ulDisposition;
  1615. ULONG ulResultLength;
  1616. PVOID KeyInfo = NULL;
  1617. BOOL bDisable = FALSE;
  1618. DOUT (DBG_PRINT, ("[CAdapterCommon::DisableAC97Pin]"));
  1619. // open the driver registry key
  1620. NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
  1621. NULL, // OuterUnknown
  1622. DriverRegistryKey, // Registry key type
  1623. KEY_READ, // Access flags
  1624. m_pDeviceObject, // Device object
  1625. NULL, // Subdevice
  1626. NULL, // ObjectAttributes
  1627. 0, // Create options
  1628. NULL); // Disposition
  1629. if (NT_SUCCESS (ntStatus))
  1630. {
  1631. // make a unicode string for the subkey name
  1632. RtlInitUnicodeString (&sKeyName, L"Settings");
  1633. // open the settings subkey
  1634. ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
  1635. NULL, // OuterUnknown
  1636. KEY_READ, // Access flags
  1637. &sKeyName, // Subkey name
  1638. REG_OPTION_NON_VOLATILE, // Create options
  1639. &ulDisposition);
  1640. if (NT_SUCCESS (ntStatus))
  1641. {
  1642. // allocate data to hold key info
  1643. KeyInfo = ExAllocatePool (PagedPool,
  1644. sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1645. sizeof(BYTE));
  1646. if (NULL != KeyInfo)
  1647. {
  1648. // init key name
  1649. RtlInitUnicodeString (&sKeyName, m_stHardwareConfig.
  1650. Pins[pin].sRegistryName);
  1651. // query the value key
  1652. ntStatus = SettingsKey->QueryValueKey (&sKeyName,
  1653. KeyValuePartialInformation,
  1654. KeyInfo,
  1655. sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1656. sizeof(BYTE),
  1657. &ulResultLength );
  1658. if (NT_SUCCESS (ntStatus))
  1659. {
  1660. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
  1661. (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
  1662. if (PartialInfo->DataLength == sizeof(BYTE))
  1663. {
  1664. // store the value
  1665. if (*(PBYTE)PartialInfo->Data)
  1666. bDisable = TRUE;
  1667. else
  1668. bDisable = FALSE;
  1669. }
  1670. }
  1671. // free the key info
  1672. ExFreePool (KeyInfo);
  1673. }
  1674. // release the settings key
  1675. SettingsKey->Release ();
  1676. }
  1677. // release the driver key
  1678. DriverKey->Release ();
  1679. }
  1680. // if one of the stuff above fails we return the default, which is FALSE.
  1681. return bDisable;
  1682. }
  1683. /*****************************************************************************
  1684. * CAdapterCommon::RestoreCodecRegisters
  1685. *****************************************************************************
  1686. * write back cached mixer values to codec registers
  1687. */
  1688. NTSTATUS CAdapterCommon::RestoreCodecRegisters (void)
  1689. {
  1690. PAGED_CODE ();
  1691. DOUT (DBG_PRINT, ("[CAdapterCommon::RestoreCodecRegisters]"));
  1692. //
  1693. // Initialize the AC97 codec.
  1694. //
  1695. NTSTATUS ntStatus = InitAC97 ();
  1696. if (!NT_SUCCESS (ntStatus))
  1697. return ntStatus;
  1698. //
  1699. // Restore all codec registers. Failure is not critical.
  1700. //
  1701. for (AC97Register i = AC97REG_MASTER_VOLUME; i < AC97REG_RESERVED2;
  1702. i = (AC97Register)(i + 1))
  1703. {
  1704. WriteCodecRegister (i, m_stAC97Registers[i].wCache, -1);
  1705. }
  1706. return STATUS_SUCCESS;
  1707. }
  1708. /*****************************************************************************
  1709. * CAdapterCommon::ReadChannelConfigDefault
  1710. *****************************************************************************
  1711. * This function reads the default channel config from the registry. The
  1712. * registry entry "ChannelConfig" is set every every time we get a
  1713. * KSPROPERTY_AUDIO_CHANNEL_CONFIG for the DAC node.
  1714. * In case the key doesn't exist we assume a channel config of stereo speakers,
  1715. * cause that is the default of DSOUND.
  1716. */
  1717. STDMETHODIMP_(void) CAdapterCommon::ReadChannelConfigDefault
  1718. (
  1719. PDWORD pdwChannelConfig,
  1720. PWORD pwChannels
  1721. )
  1722. {
  1723. PAGED_CODE ();
  1724. PREGISTRYKEY DriverKey;
  1725. PREGISTRYKEY SettingsKey;
  1726. UNICODE_STRING sKeyName;
  1727. ULONG ulDisposition;
  1728. ULONG ulResultLength;
  1729. PVOID KeyInfo = NULL;
  1730. DOUT (DBG_PRINT, ("[CAdapterCommon::ReadChannelConfigDefault]"));
  1731. // This is the default: 2 speakers, stereo.
  1732. *pdwChannelConfig = KSAUDIO_SPEAKER_STEREO;
  1733. *pwChannels = 2;
  1734. // open the driver registry key
  1735. NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
  1736. NULL, // OuterUnknown
  1737. DriverRegistryKey, // Registry key type
  1738. KEY_READ, // Access flags
  1739. m_pDeviceObject, // Device object
  1740. NULL, // Subdevice
  1741. NULL, // ObjectAttributes
  1742. 0, // Create options
  1743. NULL); // Disposition
  1744. if (NT_SUCCESS (ntStatus))
  1745. {
  1746. // make a unicode string for the subkey name
  1747. RtlInitUnicodeString (&sKeyName, L"Settings");
  1748. // open the settings subkey
  1749. ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
  1750. NULL, // OuterUnknown
  1751. KEY_READ, // Access flags
  1752. &sKeyName, // Subkey name
  1753. REG_OPTION_NON_VOLATILE, // Create options
  1754. &ulDisposition);
  1755. if (NT_SUCCESS (ntStatus))
  1756. {
  1757. // allocate data to hold key info
  1758. KeyInfo = ExAllocatePool (PagedPool,
  1759. sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1760. sizeof(DWORD));
  1761. if (NULL != KeyInfo)
  1762. {
  1763. // init key name
  1764. RtlInitUnicodeString (&sKeyName, L"ChannelConfig");
  1765. // query the value key
  1766. ntStatus = SettingsKey->QueryValueKey (&sKeyName,
  1767. KeyValuePartialInformation,
  1768. KeyInfo,
  1769. sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
  1770. sizeof(DWORD),
  1771. &ulResultLength );
  1772. if (NT_SUCCESS (ntStatus))
  1773. {
  1774. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
  1775. (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
  1776. if (PartialInfo->DataLength == sizeof(DWORD))
  1777. {
  1778. switch (*(PLONG)PartialInfo->Data)
  1779. {
  1780. case KSAUDIO_SPEAKER_QUAD:
  1781. case KSAUDIO_SPEAKER_SURROUND:
  1782. if (GetPinConfig (PINC_SURROUND_PRESENT))
  1783. {
  1784. *pdwChannelConfig = *(PDWORD)PartialInfo->Data;
  1785. *pwChannels = 4;
  1786. }
  1787. break;
  1788. case KSAUDIO_SPEAKER_5POINT1:
  1789. if (GetPinConfig (PINC_SURROUND_PRESENT) &&
  1790. GetPinConfig (PINC_CENTER_LFE_PRESENT))
  1791. {
  1792. *pdwChannelConfig = *(PDWORD)PartialInfo->Data;
  1793. *pwChannels = 6;
  1794. }
  1795. break;
  1796. }
  1797. }
  1798. }
  1799. // free the key info
  1800. ExFreePool (KeyInfo);
  1801. }
  1802. // release the settings key
  1803. SettingsKey->Release ();
  1804. }
  1805. // release the driver key
  1806. DriverKey->Release ();
  1807. }
  1808. }
  1809. /*****************************************************************************
  1810. * CAdapterCommon::WriteChannelConfigDefault
  1811. *****************************************************************************
  1812. * This function writes the default channel config to the registry. The
  1813. * registry entry "ChannelConfig" is set every every time we get a
  1814. * KSPROPERTY_AUDIO_CHANNEL_CONFIG for the DAC node.
  1815. */
  1816. STDMETHODIMP_(void) CAdapterCommon::WriteChannelConfigDefault (DWORD dwChannelConfig)
  1817. {
  1818. PAGED_CODE ();
  1819. PREGISTRYKEY DriverKey;
  1820. PREGISTRYKEY SettingsKey;
  1821. UNICODE_STRING sKeyName;
  1822. ULONG ulDisposition;
  1823. DOUT (DBG_PRINT, ("[CAdapterCommon::WriteChannelConfigDefault]"));
  1824. // open the driver registry key
  1825. NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
  1826. NULL, // OuterUnknown
  1827. DriverRegistryKey, // Registry key type
  1828. KEY_WRITE, // Access flags
  1829. m_pDeviceObject, // Device object
  1830. NULL, // Subdevice
  1831. NULL, // ObjectAttributes
  1832. 0, // Create options
  1833. NULL); // Disposition
  1834. if (NT_SUCCESS (ntStatus))
  1835. {
  1836. // make a unicode string for the subkey name
  1837. RtlInitUnicodeString (&sKeyName, L"Settings");
  1838. // open the settings subkey
  1839. ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
  1840. NULL, // OuterUnknown
  1841. KEY_WRITE, // Access flags
  1842. &sKeyName, // Subkey name
  1843. REG_OPTION_NON_VOLATILE, // Create options
  1844. &ulDisposition);
  1845. if (NT_SUCCESS (ntStatus))
  1846. {
  1847. // init key name
  1848. RtlInitUnicodeString (&sKeyName, L"ChannelConfig");
  1849. // query the value key
  1850. ntStatus = SettingsKey->SetValueKey (&sKeyName,
  1851. REG_DWORD,
  1852. &dwChannelConfig,
  1853. sizeof (DWORD));
  1854. if (!NT_SUCCESS (ntStatus))
  1855. {
  1856. DOUT (DBG_ERROR, ("Could not write the ChannelConfig to registry."));
  1857. }
  1858. // release the settings key
  1859. SettingsKey->Release ();
  1860. }
  1861. // release the driver key
  1862. DriverKey->Release ();
  1863. }
  1864. }
  1865. /*****************************************************************************
  1866. * Non paged code begins here
  1867. *****************************************************************************
  1868. */
  1869. #pragma code_seg()
  1870. /*****************************************************************************
  1871. * CAdapterCommon::WriteBMControlRegister
  1872. *****************************************************************************
  1873. * Writes a byte (UCHAR) to BusMaster Control register.
  1874. */
  1875. STDMETHODIMP_(void) CAdapterCommon::WriteBMControlRegister
  1876. (
  1877. IN ULONG ulOffset,
  1878. IN UCHAR ucValue
  1879. )
  1880. {
  1881. DOUT (DBG_PRINT, ("[CAdapterCommon::WriteBMControlRegister] (UCHAR)"));
  1882. WRITE_PORT_UCHAR ((PUCHAR)(m_pBusMasterBase + ulOffset), ucValue);
  1883. DOUT (DBG_REGS, ("WriteBMControlRegister wrote 0x%2x to 0x%4x.",
  1884. ucValue, m_pBusMasterBase + ulOffset));
  1885. }
  1886. /*****************************************************************************
  1887. * CAdapterCommon::WriteBMControlRegister
  1888. *****************************************************************************
  1889. * Writes a word (USHORT) to BusMaster Control register.
  1890. */
  1891. STDMETHODIMP_(void) CAdapterCommon::WriteBMControlRegister
  1892. (
  1893. IN ULONG ulOffset,
  1894. IN USHORT usValue
  1895. )
  1896. {
  1897. DOUT (DBG_PRINT, ("[CAdapterCommon::WriteBMControlRegister (USHORT)]"));
  1898. WRITE_PORT_USHORT ((PUSHORT)(m_pBusMasterBase + ulOffset), usValue);
  1899. DOUT (DBG_REGS, ("WriteBMControlRegister wrote 0x%4x to 0x%4x",
  1900. usValue, m_pBusMasterBase + ulOffset));
  1901. }
  1902. /*****************************************************************************
  1903. * CAdapterCommon::WriteBMControlRegister
  1904. *****************************************************************************
  1905. * Writes a DWORD (ULONG) to BusMaster Control register.
  1906. */
  1907. STDMETHODIMP_(void) CAdapterCommon::WriteBMControlRegister
  1908. (
  1909. IN ULONG ulOffset,
  1910. IN ULONG ulValue
  1911. )
  1912. {
  1913. DOUT (DBG_PRINT, ("[CAdapterCommon::WriteBMControlRegister (ULONG)]"));
  1914. WRITE_PORT_ULONG ((PULONG)(m_pBusMasterBase + ulOffset), ulValue);
  1915. DOUT (DBG_REGS, ("WriteBMControlRegister wrote 0x%8x to 0x%4x.",
  1916. ulValue, m_pBusMasterBase + ulOffset));
  1917. }
  1918. /*****************************************************************************
  1919. * CAdapterCommon::ReadBMControlRegister8
  1920. *****************************************************************************
  1921. * Read a byte (UCHAR) from BusMaster Control register.
  1922. */
  1923. STDMETHODIMP_(UCHAR) CAdapterCommon::ReadBMControlRegister8
  1924. (
  1925. IN ULONG ulOffset
  1926. )
  1927. {
  1928. UCHAR ucValue = UCHAR(-1);
  1929. DOUT (DBG_PRINT, ("[CAdapterCommon::ReadBMControlRegister8]"));
  1930. ucValue = READ_PORT_UCHAR ((PUCHAR)(m_pBusMasterBase + ulOffset));
  1931. DOUT (DBG_REGS, ("ReadBMControlRegister read 0x%2x from 0x%4x.", ucValue,
  1932. m_pBusMasterBase + ulOffset));
  1933. return ucValue;
  1934. }
  1935. /*****************************************************************************
  1936. * CAdapterCommon::ReadBMControlRegister16
  1937. *****************************************************************************
  1938. * Read a word (USHORT) from BusMaster Control register.
  1939. */
  1940. STDMETHODIMP_(USHORT) CAdapterCommon::ReadBMControlRegister16
  1941. (
  1942. IN ULONG ulOffset
  1943. )
  1944. {
  1945. USHORT usValue = USHORT(-1);
  1946. DOUT (DBG_PRINT, ("[CAdapterCommon::ReadBMControlRegister16]"));
  1947. usValue = READ_PORT_USHORT ((PUSHORT)(m_pBusMasterBase + ulOffset));
  1948. DOUT (DBG_REGS, ("ReadBMControlRegister read 0x%4x = 0x%4x", usValue,
  1949. m_pBusMasterBase + ulOffset));
  1950. return usValue;
  1951. }
  1952. /*****************************************************************************
  1953. * CAdapterCommon::ReadBMControlRegister32
  1954. *****************************************************************************
  1955. * Read a dword (ULONG) from BusMaster Control register.
  1956. */
  1957. STDMETHODIMP_(ULONG) CAdapterCommon::ReadBMControlRegister32
  1958. (
  1959. IN ULONG ulOffset
  1960. )
  1961. {
  1962. ULONG ulValue = ULONG(-1);
  1963. DOUT (DBG_PRINT, ("[CAdapterCommon::ReadBMControlRegister32]"));
  1964. ulValue = READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + ulOffset));
  1965. DOUT (DBG_REGS, ("ReadBMControlRegister read 0x%8x = 0x%4x", ulValue,
  1966. m_pBusMasterBase + ulOffset));
  1967. return ulValue;
  1968. }