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.

946 lines
30 KiB

  1. /*****************************************************************************
  2. * common.cpp - Common code used by all the sb16 miniports.
  3. *****************************************************************************
  4. * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
  5. *
  6. * Implmentation of the common code object. This class deals with interrupts
  7. * for the device, and is a collection of common code used by all the
  8. * miniports.
  9. */
  10. #include "common.h"
  11. #define STR_MODULENAME "sb16Adapter: "
  12. /*****************************************************************************
  13. * CAdapterCommon
  14. *****************************************************************************
  15. * Adapter common object.
  16. */
  17. class CAdapterCommon
  18. : public IAdapterCommon,
  19. public IAdapterPowerManagement,
  20. public CUnknown
  21. {
  22. private:
  23. PINTERRUPTSYNC m_pInterruptSync;
  24. PUCHAR m_pWaveBase;
  25. PWAVEMINIPORTSB16 m_WaveMiniportSB16;
  26. #ifdef EVENT_SUPPORT
  27. PTOPOMINIPORTSB16 m_TopoMiniportSB16; // Topology miniport of SB16.
  28. #endif
  29. PDEVICE_OBJECT m_pDeviceObject;
  30. DEVICE_POWER_STATE m_PowerState;
  31. BYTE MixerSettings[DSP_MIX_MAXREGS];
  32. void AcknowledgeIRQ
  33. ( void
  34. );
  35. public:
  36. DECLARE_STD_UNKNOWN();
  37. DEFINE_STD_CONSTRUCTOR(CAdapterCommon);
  38. ~CAdapterCommon();
  39. /*****************************************************************************
  40. * IAdapterCommon methods
  41. */
  42. STDMETHODIMP_(NTSTATUS) Init
  43. (
  44. IN PRESOURCELIST ResourceList,
  45. IN PDEVICE_OBJECT DeviceObject
  46. );
  47. STDMETHODIMP_(PINTERRUPTSYNC) GetInterruptSync
  48. ( void
  49. );
  50. STDMETHODIMP_(void) SetWaveMiniport (IN PWAVEMINIPORTSB16 Miniport)
  51. {
  52. m_WaveMiniportSB16 = Miniport;
  53. }
  54. STDMETHODIMP_(BYTE) ReadController
  55. ( void
  56. );
  57. STDMETHODIMP_(BOOLEAN) WriteController
  58. (
  59. IN BYTE Value
  60. );
  61. STDMETHODIMP_(NTSTATUS) ResetController
  62. ( void
  63. );
  64. STDMETHODIMP_(void) MixerRegWrite
  65. (
  66. IN BYTE Index,
  67. IN BYTE Value
  68. );
  69. STDMETHODIMP_(BYTE) MixerRegRead
  70. (
  71. IN BYTE Index
  72. );
  73. STDMETHODIMP_(void) MixerReset
  74. ( void
  75. );
  76. STDMETHODIMP RestoreMixerSettingsFromRegistry
  77. ( void
  78. );
  79. STDMETHODIMP SaveMixerSettingsToRegistry
  80. ( void
  81. );
  82. #ifdef EVENT_SUPPORT
  83. //
  84. // The topology miniport needs to tell us the pointer to the Event-interface.
  85. //
  86. STDMETHODIMP_(void) SetTopologyMiniport (IN PTOPOMINIPORTSB16 Miniport)
  87. {
  88. m_TopoMiniportSB16 = Miniport;
  89. };
  90. #endif
  91. /*************************************************************************
  92. * IAdapterPowerManagement implementation
  93. *
  94. * This macro is from PORTCLS.H. It lists all the interface's functions.
  95. */
  96. IMP_IAdapterPowerManagement;
  97. friend
  98. NTSTATUS
  99. InterruptServiceRoutine
  100. (
  101. IN PINTERRUPTSYNC InterruptSync,
  102. IN PVOID DynamicContext
  103. );
  104. };
  105. static
  106. MIXERSETTING DefaultMixerSettings[] =
  107. {
  108. { L"LeftMasterVol", DSP_MIX_MASTERVOLIDX_L, 0xD8 },
  109. { L"RightMasterVol", DSP_MIX_MASTERVOLIDX_R, 0xD8 },
  110. { L"LeftWaveVol", DSP_MIX_VOICEVOLIDX_L, 0xD8 },
  111. { L"RightWaveVol", DSP_MIX_VOICEVOLIDX_R, 0xD8 },
  112. { L"LeftMidiVol", DSP_MIX_FMVOLIDX_L, 0xD8 },
  113. { L"RightMidiVol", DSP_MIX_FMVOLIDX_R, 0xD8 },
  114. { L"LeftCDVol", DSP_MIX_CDVOLIDX_L, 0xD8 },
  115. { L"RightCDVol", DSP_MIX_CDVOLIDX_R, 0xD8 },
  116. { L"LeftLineInVol", DSP_MIX_LINEVOLIDX_L, 0xD8 },
  117. { L"RightLineInVol", DSP_MIX_LINEVOLIDX_R, 0xD8 },
  118. { L"MicVol", DSP_MIX_MICVOLIDX, 0xD8 },
  119. { L"PcSpkrVol", DSP_MIX_SPKRVOLIDX, 0x00 },
  120. { L"OutputMixer", DSP_MIX_OUTMIXIDX, 0x1E },
  121. { L"LeftInputMixer", DSP_MIX_ADCMIXIDX_L, 0x55 },
  122. { L"RightInputMixer", DSP_MIX_ADCMIXIDX_R, 0x2B },
  123. { L"LeftInputGain", DSP_MIX_INGAINIDX_L, 0x00 },
  124. { L"RightInputGain", DSP_MIX_INGAINIDX_R, 0x00 },
  125. { L"LeftOutputGain", DSP_MIX_OUTGAINIDX_L, 0x80 },
  126. { L"RightOutputGain", DSP_MIX_OUTGAINIDX_R, 0x80 },
  127. { L"MicAGC", DSP_MIX_AGCIDX, 0x01 },
  128. { L"LeftTreble", DSP_MIX_TREBLEIDX_L, 0x80 },
  129. { L"RightTreble", DSP_MIX_TREBLEIDX_R, 0x80 },
  130. { L"LeftBass", DSP_MIX_BASSIDX_L, 0x80 },
  131. { L"RightBass", DSP_MIX_BASSIDX_R, 0x80 },
  132. };
  133. #pragma code_seg("PAGE")
  134. /*****************************************************************************
  135. * NewAdapterCommon()
  136. *****************************************************************************
  137. * Create a new adapter common object.
  138. */
  139. NTSTATUS
  140. NewAdapterCommon
  141. (
  142. OUT PUNKNOWN * Unknown,
  143. IN REFCLSID,
  144. IN PUNKNOWN UnknownOuter OPTIONAL,
  145. IN POOL_TYPE PoolType
  146. )
  147. {
  148. PAGED_CODE();
  149. ASSERT(Unknown);
  150. STD_CREATE_BODY_
  151. (
  152. CAdapterCommon,
  153. Unknown,
  154. UnknownOuter,
  155. PoolType,
  156. PADAPTERCOMMON
  157. );
  158. }
  159. /*****************************************************************************
  160. * CAdapterCommon::Init()
  161. *****************************************************************************
  162. * Initialize an adapter common object.
  163. */
  164. NTSTATUS
  165. CAdapterCommon::
  166. Init
  167. (
  168. IN PRESOURCELIST ResourceList,
  169. IN PDEVICE_OBJECT DeviceObject
  170. )
  171. {
  172. PAGED_CODE();
  173. ASSERT(ResourceList);
  174. ASSERT(DeviceObject);
  175. //
  176. // Make sure we have the resources we expect
  177. //
  178. if ((ResourceList->NumberOfPorts() < 1) ||
  179. (ResourceList->NumberOfInterrupts() != 1))
  180. {
  181. _DbgPrintF (DEBUGLVL_TERSE, ("unknown configuration; check your code!"));
  182. // Bail out.
  183. return STATUS_INSUFFICIENT_RESOURCES;
  184. }
  185. m_pDeviceObject = DeviceObject;
  186. m_WaveMiniportSB16 = NULL;
  187. #ifdef EVENT_SUPPORT
  188. m_TopoMiniportSB16 = NULL;
  189. #endif
  190. //
  191. // Get the base address for the wave device.
  192. //
  193. ASSERT(ResourceList->FindTranslatedPort(0));
  194. m_pWaveBase = (PUCHAR)(ResourceList->FindTranslatedPort(0)->u.Port.Start.QuadPart);
  195. //
  196. // Set initial device power state
  197. //
  198. m_PowerState = PowerDeviceD0;
  199. //
  200. // Reset the hardware.
  201. //
  202. NTSTATUS ntStatus = ResetController();
  203. if(NT_SUCCESS(ntStatus))
  204. {
  205. _DbgPrintF(DEBUGLVL_VERBOSE,("ResetController Succeeded"));
  206. AcknowledgeIRQ();
  207. //
  208. // Hook up the interrupt.
  209. //
  210. ntStatus = PcNewInterruptSync( // See portcls.h
  211. &m_pInterruptSync, // Save object ptr
  212. NULL, // OuterUnknown(optional).
  213. ResourceList, // He gets IRQ from ResourceList.
  214. 0, // Resource Index
  215. InterruptSyncModeNormal // Run ISRs once until we get SUCCESS
  216. );
  217. if (NT_SUCCESS(ntStatus) && m_pInterruptSync)
  218. { // run this ISR first
  219. ntStatus = m_pInterruptSync->RegisterServiceRoutine(InterruptServiceRoutine,PVOID(this),FALSE);
  220. if (NT_SUCCESS(ntStatus))
  221. {
  222. ntStatus = m_pInterruptSync->Connect();
  223. }
  224. // if we could not connect or register the ISR, release the object.
  225. if (!NT_SUCCESS (ntStatus))
  226. {
  227. m_pInterruptSync->Release();
  228. m_pInterruptSync = NULL;
  229. }
  230. }
  231. } else
  232. {
  233. _DbgPrintF(DEBUGLVL_TERSE,("ResetController Failure"));
  234. }
  235. return ntStatus;
  236. }
  237. /*****************************************************************************
  238. * CAdapterCommon::~CAdapterCommon()
  239. *****************************************************************************
  240. * Destructor.
  241. */
  242. CAdapterCommon::
  243. ~CAdapterCommon
  244. ( void
  245. )
  246. {
  247. PAGED_CODE();
  248. _DbgPrintF(DEBUGLVL_VERBOSE,("[CAdapterCommon::~CAdapterCommon]"));
  249. if (m_pInterruptSync)
  250. {
  251. m_pInterruptSync->Disconnect();
  252. m_pInterruptSync->Release();
  253. m_pInterruptSync = NULL;
  254. }
  255. }
  256. /*****************************************************************************
  257. * CAdapterCommon::NonDelegatingQueryInterface()
  258. *****************************************************************************
  259. * Obtains an interface.
  260. */
  261. STDMETHODIMP
  262. CAdapterCommon::
  263. NonDelegatingQueryInterface
  264. (
  265. REFIID Interface,
  266. PVOID * Object
  267. )
  268. {
  269. PAGED_CODE();
  270. ASSERT(Object);
  271. if (IsEqualGUIDAligned(Interface,IID_IUnknown))
  272. {
  273. *Object = PVOID(PUNKNOWN(PADAPTERCOMMON(this)));
  274. }
  275. else
  276. if (IsEqualGUIDAligned(Interface,IID_IAdapterCommon))
  277. {
  278. *Object = PVOID(PADAPTERCOMMON(this));
  279. }
  280. else
  281. if (IsEqualGUIDAligned(Interface,IID_IAdapterPowerManagement))
  282. {
  283. *Object = PVOID(PADAPTERPOWERMANAGEMENT(this));
  284. }
  285. else
  286. {
  287. *Object = NULL;
  288. }
  289. if (*Object)
  290. {
  291. PUNKNOWN(*Object)->AddRef();
  292. return STATUS_SUCCESS;
  293. }
  294. return STATUS_INVALID_PARAMETER;
  295. }
  296. /*****************************************************************************
  297. * CAdapterCommon::GetInterruptSync()
  298. *****************************************************************************
  299. * Get a pointer to the interrupt synchronization object.
  300. */
  301. STDMETHODIMP_(PINTERRUPTSYNC)
  302. CAdapterCommon::
  303. GetInterruptSync
  304. ( void
  305. )
  306. {
  307. PAGED_CODE();
  308. return m_pInterruptSync;
  309. }
  310. #pragma code_seg()
  311. /*****************************************************************************
  312. * CAdapterCommon::ReadController()
  313. *****************************************************************************
  314. * Read a byte from the controller.
  315. */
  316. STDMETHODIMP_(BYTE)
  317. CAdapterCommon::
  318. ReadController
  319. ( void
  320. )
  321. {
  322. BYTE returnValue = BYTE(-1);
  323. ASSERT(m_pWaveBase);
  324. ULONGLONG startTime = PcGetTimeInterval(0);
  325. do {
  326. if (READ_PORT_UCHAR (m_pWaveBase + DSP_REG_DATAAVAIL) & 0x80)
  327. {
  328. returnValue = READ_PORT_UCHAR (m_pWaveBase + DSP_REG_READ);
  329. }
  330. } while ((PcGetTimeInterval(startTime) < GTI_MILLISECONDS(100)) &&
  331. (BYTE(-1) == returnValue));
  332. ASSERT((BYTE(-1) != returnValue) || !"ReadController timeout!");
  333. return returnValue;
  334. }
  335. /*****************************************************************************
  336. * CAdapterCommon::WriteController()
  337. *****************************************************************************
  338. * Write a byte to the controller.
  339. */
  340. STDMETHODIMP_(BOOLEAN)
  341. CAdapterCommon::
  342. WriteController
  343. (
  344. IN BYTE Value
  345. )
  346. {
  347. ASSERT(m_pWaveBase);
  348. BOOLEAN returnValue = FALSE;
  349. ULONGLONG startTime = PcGetTimeInterval(0);
  350. do
  351. {
  352. BYTE status = READ_PORT_UCHAR (m_pWaveBase + DSP_REG_WRITE);
  353. if ((status & 0x80) == 0)
  354. {
  355. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_WRITE, Value);
  356. returnValue = TRUE;
  357. }
  358. } while ((PcGetTimeInterval(startTime) < GTI_MILLISECONDS(100)) &&
  359. ! returnValue);
  360. ASSERT(returnValue || !"WriteController timeout");
  361. return returnValue;
  362. }
  363. /*****************************************************************************
  364. * CAdapterCommon::MixerRegWrite()
  365. *****************************************************************************
  366. * Writes a mixer register.
  367. */
  368. STDMETHODIMP_(void)
  369. CAdapterCommon::
  370. MixerRegWrite
  371. (
  372. IN BYTE Index,
  373. IN BYTE Value
  374. )
  375. {
  376. ASSERT( m_pWaveBase );
  377. BYTE actualIndex;
  378. // only hit the hardware if we're in an acceptable power state
  379. if( m_PowerState <= PowerDeviceD1 )
  380. {
  381. actualIndex = (BYTE) ((Index < 0x80) ? (Index + DSP_MIX_BASEIDX) : Index);
  382. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_MIXREG, actualIndex);
  383. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_MIXDATA, Value);
  384. }
  385. if(Index < DSP_MIX_MAXREGS)
  386. {
  387. MixerSettings[Index] = Value;
  388. }
  389. }
  390. /*****************************************************************************
  391. * CAdapterCommon::MixerRegRead()
  392. *****************************************************************************
  393. * Reads a mixer register.
  394. */
  395. STDMETHODIMP_(BYTE)
  396. CAdapterCommon::
  397. MixerRegRead
  398. (
  399. IN BYTE Index
  400. )
  401. {
  402. if(Index < DSP_MIX_MAXREGS)
  403. {
  404. return MixerSettings[Index];
  405. }
  406. //
  407. // Not in the cache? Read from HW directly.
  408. //
  409. // We need to make sure that we can access the HW directly for
  410. // the volumes that can change externally.
  411. // This is done here with passing an index outside of the cache.
  412. // Since the an index=0 is actually DSP_MIX_BASEIDX which is less
  413. // than the cache size (DSP_MIX_MAXREGS), you can access any volume
  414. // directly with passing DSP_MIX_BASEIDX + index.
  415. // You could also pass a flag - but we want to keep the changes
  416. // minimal - or create a new function like MixerRegReadDirect().
  417. //
  418. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_MIXREG, Index);
  419. return READ_PORT_UCHAR (m_pWaveBase + DSP_REG_MIXDATA);
  420. }
  421. /*****************************************************************************
  422. * CAdapterCommon::MixerReset()
  423. *****************************************************************************
  424. * Resets the mixer
  425. */
  426. STDMETHODIMP_(void)
  427. CAdapterCommon::
  428. MixerReset
  429. ( void
  430. )
  431. {
  432. ASSERT(m_pWaveBase);
  433. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_MIXREG, DSP_MIX_DATARESETIDX);
  434. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_MIXDATA, 0);
  435. RestoreMixerSettingsFromRegistry();
  436. }
  437. /*****************************************************************************
  438. * CAdapterCommon::AcknowledgeIRQ()
  439. *****************************************************************************
  440. * Acknowledge interrupt request.
  441. */
  442. void
  443. CAdapterCommon::
  444. AcknowledgeIRQ
  445. ( void
  446. )
  447. {
  448. ASSERT(m_pWaveBase);
  449. READ_PORT_UCHAR (m_pWaveBase + DSP_REG_ACK16BIT);
  450. READ_PORT_UCHAR (m_pWaveBase + DSP_REG_ACK8BIT);
  451. }
  452. /*****************************************************************************
  453. * CAdapterCommon::ResetController()
  454. *****************************************************************************
  455. * Resets the controller.
  456. */
  457. STDMETHODIMP_(NTSTATUS)
  458. CAdapterCommon::
  459. ResetController(void)
  460. {
  461. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  462. // write a 1 to the reset bit
  463. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_RESET,1);
  464. // wait for at least 3 microseconds
  465. KeStallExecutionProcessor (5L); // okay, 5us
  466. // write a 0 to the reset bit
  467. WRITE_PORT_UCHAR (m_pWaveBase + DSP_REG_RESET,0);
  468. // hang out for 100us
  469. KeStallExecutionProcessor (100L);
  470. // read the controller
  471. BYTE ReadVal = ReadController ();
  472. // check return value
  473. if( ReadVal == BYTE(0xAA) )
  474. {
  475. ntStatus = STATUS_SUCCESS;
  476. }
  477. return ntStatus;
  478. }
  479. /*****************************************************************************
  480. * CAdapterCommon::RestoreMixerSettingsFromRegistry()
  481. *****************************************************************************
  482. * Restores the mixer settings based on settings stored in the registry.
  483. */
  484. STDMETHODIMP
  485. CAdapterCommon::
  486. RestoreMixerSettingsFromRegistry
  487. ( void
  488. )
  489. {
  490. PREGISTRYKEY DriverKey;
  491. PREGISTRYKEY SettingsKey;
  492. _DbgPrintF(DEBUGLVL_VERBOSE,("[RestoreMixerSettingsFromRegistry]"));
  493. // open the driver registry key
  494. NTSTATUS ntStatus = PcNewRegistryKey( &DriverKey, // IRegistryKey
  495. NULL, // OuterUnknown
  496. DriverRegistryKey, // Registry key type
  497. KEY_ALL_ACCESS, // Access flags
  498. m_pDeviceObject, // Device object
  499. NULL, // Subdevice
  500. NULL, // ObjectAttributes
  501. 0, // Create options
  502. NULL ); // Disposition
  503. if(NT_SUCCESS(ntStatus))
  504. {
  505. UNICODE_STRING KeyName;
  506. ULONG Disposition;
  507. // make a unicode strong for the subkey name
  508. RtlInitUnicodeString( &KeyName, L"Settings" );
  509. // open the settings subkey
  510. ntStatus = DriverKey->NewSubKey( &SettingsKey, // Subkey
  511. NULL, // OuterUnknown
  512. KEY_ALL_ACCESS, // Access flags
  513. &KeyName, // Subkey name
  514. REG_OPTION_NON_VOLATILE, // Create options
  515. &Disposition );
  516. if(NT_SUCCESS(ntStatus))
  517. {
  518. ULONG ResultLength;
  519. if(Disposition == REG_CREATED_NEW_KEY)
  520. {
  521. // copy default settings
  522. for(ULONG i = 0; i < SIZEOF_ARRAY(DefaultMixerSettings); i++)
  523. {
  524. MixerRegWrite( DefaultMixerSettings[i].RegisterIndex,
  525. DefaultMixerSettings[i].RegisterSetting );
  526. }
  527. } else
  528. {
  529. // allocate data to hold key info
  530. PVOID KeyInfo = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD));
  531. if(NULL != KeyInfo)
  532. {
  533. // loop through all mixer settings
  534. for(UINT i = 0; i < SIZEOF_ARRAY(DefaultMixerSettings); i++)
  535. {
  536. // init key name
  537. RtlInitUnicodeString( &KeyName, DefaultMixerSettings[i].KeyName );
  538. // query the value key
  539. ntStatus = SettingsKey->QueryValueKey( &KeyName,
  540. KeyValuePartialInformation,
  541. KeyInfo,
  542. sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD),
  543. &ResultLength );
  544. if(NT_SUCCESS(ntStatus))
  545. {
  546. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo);
  547. if(PartialInfo->DataLength == sizeof(DWORD))
  548. {
  549. // set mixer register to registry value
  550. MixerRegWrite( DefaultMixerSettings[i].RegisterIndex,
  551. BYTE(*(PDWORD(PartialInfo->Data))) );
  552. }
  553. } else
  554. {
  555. // if key access failed, set to default
  556. MixerRegWrite( DefaultMixerSettings[i].RegisterIndex,
  557. DefaultMixerSettings[i].RegisterSetting );
  558. }
  559. }
  560. // free the key info
  561. ExFreePool(KeyInfo);
  562. } else
  563. {
  564. // copy default settings
  565. for(ULONG i = 0; i < SIZEOF_ARRAY(DefaultMixerSettings); i++)
  566. {
  567. MixerRegWrite( DefaultMixerSettings[i].RegisterIndex,
  568. DefaultMixerSettings[i].RegisterSetting );
  569. }
  570. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  571. }
  572. }
  573. // release the settings key
  574. SettingsKey->Release();
  575. }
  576. // release the driver key
  577. DriverKey->Release();
  578. }
  579. return ntStatus;
  580. }
  581. /*****************************************************************************
  582. * CAdapterCommon::SaveMixerSettingsToRegistry()
  583. *****************************************************************************
  584. * Saves the mixer settings to the registry.
  585. */
  586. STDMETHODIMP
  587. CAdapterCommon::
  588. SaveMixerSettingsToRegistry
  589. ( void
  590. )
  591. {
  592. PREGISTRYKEY DriverKey;
  593. PREGISTRYKEY SettingsKey;
  594. _DbgPrintF(DEBUGLVL_VERBOSE,("[SaveMixerSettingsToRegistry]"));
  595. // open the driver registry key
  596. NTSTATUS ntStatus = PcNewRegistryKey( &DriverKey, // IRegistryKey
  597. NULL, // OuterUnknown
  598. DriverRegistryKey, // Registry key type
  599. KEY_ALL_ACCESS, // Access flags
  600. m_pDeviceObject, // Device object
  601. NULL, // Subdevice
  602. NULL, // ObjectAttributes
  603. 0, // Create options
  604. NULL ); // Disposition
  605. if(NT_SUCCESS(ntStatus))
  606. {
  607. UNICODE_STRING KeyName;
  608. // make a unicode strong for the subkey name
  609. RtlInitUnicodeString( &KeyName, L"Settings" );
  610. // open the settings subkey
  611. ntStatus = DriverKey->NewSubKey( &SettingsKey, // Subkey
  612. NULL, // OuterUnknown
  613. KEY_ALL_ACCESS, // Access flags
  614. &KeyName, // Subkey name
  615. REG_OPTION_NON_VOLATILE, // Create options
  616. NULL );
  617. if(NT_SUCCESS(ntStatus))
  618. {
  619. // loop through all mixer settings
  620. for(UINT i = 0; i < SIZEOF_ARRAY(MixerSettings); i++)
  621. {
  622. // init key name
  623. RtlInitUnicodeString( &KeyName, DefaultMixerSettings[i].KeyName );
  624. // set the key
  625. DWORD KeyValue = DWORD(MixerSettings[DefaultMixerSettings[i].RegisterIndex]);
  626. ntStatus = SettingsKey->SetValueKey( &KeyName, // Key name
  627. REG_DWORD, // Key type
  628. PVOID(&KeyValue),
  629. sizeof(DWORD) );
  630. if(!NT_SUCCESS(ntStatus))
  631. {
  632. break;
  633. }
  634. }
  635. // release the settings key
  636. SettingsKey->Release();
  637. }
  638. // release the driver key
  639. DriverKey->Release();
  640. }
  641. return ntStatus;
  642. }
  643. /*****************************************************************************
  644. * CAdapterCommon::PowerChangeState()
  645. *****************************************************************************
  646. * Change power state for the device.
  647. */
  648. STDMETHODIMP_(void)
  649. CAdapterCommon::
  650. PowerChangeState
  651. (
  652. IN POWER_STATE NewState
  653. )
  654. {
  655. UINT i;
  656. _DbgPrintF( DEBUGLVL_VERBOSE, ("[CAdapterCommon::PowerChangeState]"));
  657. // Is this actually a state change?
  658. if( NewState.DeviceState != m_PowerState )
  659. {
  660. // switch on new state
  661. switch( NewState.DeviceState )
  662. {
  663. case PowerDeviceD0:
  664. // Insert your code here for entering the full power state (D0).
  665. // This code may be a function of the current power state. Note that
  666. // property accesses such as volume and mute changes may occur when
  667. // the device is in a sleep state (D1-D3) and should be cached in the
  668. // driver to be restored upon entering D0. However, it should also be
  669. // noted that new miniport and new streams will only be attempted at
  670. // D0 -- PortCls will place the device in D0 prior to the NewStream call.
  671. // Save the new state. This local value is used to determine when to cache
  672. // property accesses and when to permit the driver from accessing the hardware.
  673. m_PowerState = NewState.DeviceState;
  674. // restore mixer settings
  675. for(i = 0; i < DSP_MIX_MAXREGS - 1; i++)
  676. {
  677. if( i != DSP_MIX_MICVOLIDX )
  678. {
  679. MixerRegWrite( BYTE(i), MixerSettings[i] );
  680. }
  681. }
  682. if (m_WaveMiniportSB16)
  683. {
  684. m_WaveMiniportSB16->RestoreSampleRate();
  685. }
  686. break;
  687. case PowerDeviceD1:
  688. // This sleep state is the lowest latency sleep state with respect to the
  689. // latency time required to return to D0. The driver can still access
  690. // the hardware in this state if desired. If the driver is not being used
  691. // an inactivity timer in PortCls will place the driver in this state after
  692. // a timeout period controllable via the registry.
  693. case PowerDeviceD2:
  694. // This is a medium latency sleep state. In this state the device driver
  695. // cannot assume that it can touch the hardware so any accesses need to be
  696. // cached and the hardware restored upon entering D0 (or D1 conceivably).
  697. case PowerDeviceD3:
  698. // This is a full hibernation state and is the longest latency sleep state.
  699. // The driver cannot access the hardware in this state and must cache any
  700. // hardware accesses and restore the hardware upon returning to D0 (or D1).
  701. // Save the new state.
  702. m_PowerState = NewState.DeviceState;
  703. _DbgPrintF(DEBUGLVL_VERBOSE,(" Entering D%d",ULONG(m_PowerState)-ULONG(PowerDeviceD0)));
  704. break;
  705. default:
  706. _DbgPrintF(DEBUGLVL_VERBOSE,(" Unknown Device Power State"));
  707. break;
  708. }
  709. }
  710. }
  711. /*****************************************************************************
  712. * CAdapterCommon::QueryPowerChangeState()
  713. *****************************************************************************
  714. * Query to see if the device can
  715. * change to this power state
  716. */
  717. STDMETHODIMP_(NTSTATUS)
  718. CAdapterCommon::
  719. QueryPowerChangeState
  720. (
  721. IN POWER_STATE NewStateQuery
  722. )
  723. {
  724. _DbgPrintF( DEBUGLVL_TERSE, ("[CAdapterCommon::QueryPowerChangeState]"));
  725. // Check here to see of a legitimate state is being requested
  726. // based on the device state and fail the call if the device/driver
  727. // cannot support the change requested. Otherwise, return STATUS_SUCCESS.
  728. // Note: A QueryPowerChangeState() call is not guaranteed to always preceed
  729. // a PowerChangeState() call.
  730. return STATUS_SUCCESS;
  731. }
  732. /*****************************************************************************
  733. * CAdapterCommon::QueryDeviceCapabilities()
  734. *****************************************************************************
  735. * Called at startup to get the caps for the device. This structure provides
  736. * the system with the mappings between system power state and device power
  737. * state. This typically will not need modification by the driver.
  738. *
  739. */
  740. STDMETHODIMP_(NTSTATUS)
  741. CAdapterCommon::
  742. QueryDeviceCapabilities
  743. (
  744. IN PDEVICE_CAPABILITIES PowerDeviceCaps
  745. )
  746. {
  747. _DbgPrintF( DEBUGLVL_TERSE, ("[CAdapterCommon::QueryDeviceCapabilities]"));
  748. return STATUS_SUCCESS;
  749. }
  750. /*****************************************************************************
  751. * InterruptServiceRoutine()
  752. *****************************************************************************
  753. * ISR.
  754. */
  755. NTSTATUS
  756. InterruptServiceRoutine
  757. (
  758. IN PINTERRUPTSYNC InterruptSync,
  759. IN PVOID DynamicContext
  760. )
  761. {
  762. ASSERT(InterruptSync);
  763. ASSERT(DynamicContext);
  764. CAdapterCommon *that = (CAdapterCommon *) DynamicContext;
  765. //
  766. // We are here because the MPU tried and failed, so
  767. // must be a wave interrupt.
  768. //
  769. ASSERT(that->m_pWaveBase);
  770. //
  771. // Read the Interrupt status register.
  772. //
  773. BYTE IntrStatus = that->MixerRegRead (0x82);
  774. //
  775. // In case we really read the interrupt status register, we should
  776. // also USE it and make sure that we really have a wave interrupt
  777. // and not something else!
  778. //
  779. if (IntrStatus & 0x03) // Voice8 or Voice16 Interrupt
  780. {
  781. //
  782. // Make sure there is a wave miniport.
  783. //
  784. if (that->m_WaveMiniportSB16)
  785. {
  786. //
  787. // Tell it it needs to do some work.
  788. //
  789. that->m_WaveMiniportSB16->ServiceWaveISR ();
  790. }
  791. //
  792. // ACK the ISR.
  793. //
  794. that->AcknowledgeIRQ();
  795. }
  796. #ifdef EVENT_SUPPORT
  797. //
  798. // This code will fire a volume event in case the HW volume has changed.
  799. //
  800. else if (IntrStatus & 0x10) // Volume interrupt on C16X-mixers
  801. {
  802. //
  803. // Ack vol interrupt
  804. //
  805. IntrStatus &= ~0x10;
  806. that->MixerRegWrite (0x82, IntrStatus);
  807. //
  808. // Generate an event for the master volume (as an example)
  809. //
  810. if (that->m_TopoMiniportSB16)
  811. {
  812. that->m_TopoMiniportSB16->ServiceEvent ();
  813. }
  814. }
  815. #endif
  816. return STATUS_SUCCESS;
  817. }