Leaked source code of windows server 2003
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.

1373 lines
32 KiB

  1. /*****************************************************************************
  2. * waveclk.cpp - wave clock implementation
  3. *****************************************************************************
  4. * Copyright (c) 1998-2000 Microsoft Corporation. All rights reserved.
  5. */
  6. #include "private.h"
  7. /*****************************************************************************
  8. * IIrpTargetInit
  9. *****************************************************************************
  10. * IIrpTargetInit plus CWaveClock's Init.
  11. */
  12. DECLARE_INTERFACE_(IIrpTargetInit,IIrpTarget)
  13. {
  14. DEFINE_ABSTRACT_UNKNOWN() // For IUnknown
  15. DEFINE_ABSTRACT_IRPTARGETFACTORY() // For IIrpTargetFactory
  16. DEFINE_ABSTRACT_IRPTARGET() // For IIrpTarget
  17. STDMETHOD_(NTSTATUS,Init)
  18. ( THIS_
  19. IN PIRPSTREAMCONTROL pIrpStreamControl,
  20. IN PKSPIN_LOCK pKSpinLock,
  21. IN PLIST_ENTRY pListEntry
  22. ) PURE;
  23. };
  24. typedef IIrpTargetInit *PIRPTARGETINIT;
  25. /*****************************************************************************
  26. * CWaveClock
  27. *****************************************************************************
  28. * Wave clock implementation.
  29. */
  30. class CWaveClock :
  31. public IIrpTargetInit,
  32. public IWaveClock,
  33. public CUnknown
  34. {
  35. private:
  36. WAVECLOCKNODE m_waveClockNode;
  37. PKSPIN_LOCK m_pKSpinLock;
  38. PIRPSTREAMCONTROL m_pIrpStreamControl;
  39. KSPIN_LOCK m_ClockLock,
  40. m_EventLock;
  41. LIST_ENTRY m_EventList;
  42. KMUTEX m_StateMutex;
  43. LONGLONG m_LastTime,
  44. m_LastPhysicalTime,
  45. m_LastPhysicalPosition;
  46. KSSTATE m_DeviceState;
  47. LONGLONG
  48. m_GetCurrentTime
  49. ( void
  50. );
  51. public:
  52. DECLARE_STD_UNKNOWN();
  53. DEFINE_STD_CONSTRUCTOR(CWaveClock);
  54. ~CWaveClock();
  55. IMP_IIrpTarget;
  56. IMP_IWaveClock;
  57. STDMETHODIMP_(NTSTATUS) Init
  58. ( IN PIRPSTREAMCONTROL pIrpStreamControl,
  59. IN PKSPIN_LOCK pKSpinLock,
  60. IN PLIST_ENTRY pListEntry
  61. );
  62. //
  63. // helper functions (also the DPC interface)
  64. //
  65. static
  66. LONGLONG
  67. FASTCALL
  68. GetCurrentTime(
  69. IN PFILE_OBJECT FileObject
  70. );
  71. static
  72. LONGLONG
  73. FASTCALL
  74. GetCurrentPhysicalTime(
  75. IN PFILE_OBJECT FileObject
  76. );
  77. static
  78. LONGLONG
  79. FASTCALL
  80. GetCurrentCorrelatedTime(
  81. IN PFILE_OBJECT FileObject,
  82. OUT PLONGLONG SystemTime
  83. );
  84. static
  85. LONGLONG
  86. FASTCALL
  87. GetCurrentCorrelatedPhysicalTime(
  88. IN PFILE_OBJECT FileObject,
  89. OUT PLONGLONG SystemTime
  90. );
  91. //
  92. // property handlers and event handlers
  93. //
  94. static
  95. NTSTATUS
  96. AddEvent(
  97. IN PIRP Irp,
  98. IN PKSEVENT_TIME_INTERVAL EventTime,
  99. IN PKSEVENT_ENTRY EventEntry
  100. );
  101. static
  102. NTSTATUS
  103. GetFunctionTable(
  104. IN PIRP Irp,
  105. IN PKSPROPERTY Property,
  106. OUT PKSCLOCK_FUNCTIONTABLE FunctionTable
  107. );
  108. static
  109. NTSTATUS
  110. GetCorrelatedTime(
  111. IN PIRP Irp,
  112. IN PKSPROPERTY Property,
  113. OUT PKSCORRELATED_TIME CorrelatedTime
  114. );
  115. static
  116. NTSTATUS
  117. GetTime(
  118. IN PIRP Irp,
  119. IN PKSPROPERTY Property,
  120. OUT PLONGLONG Time
  121. );
  122. static
  123. NTSTATUS
  124. GetCorrelatedPhysicalTime(
  125. IN PIRP Irp,
  126. IN PKSPROPERTY Property,
  127. OUT PKSCORRELATED_TIME CorrelatedTime
  128. );
  129. static
  130. NTSTATUS
  131. GetPhysicalTime(
  132. IN PIRP Irp,
  133. IN PKSPROPERTY Property,
  134. OUT PLONGLONG Time
  135. );
  136. static
  137. NTSTATUS
  138. GetResolution(
  139. IN PIRP Irp,
  140. IN PKSPROPERTY Property,
  141. OUT PKSRESOLUTION Resolution
  142. );
  143. static
  144. NTSTATUS
  145. GetState(
  146. IN PIRP Irp,
  147. IN PKSPROPERTY Property,
  148. OUT PKSSTATE State
  149. );
  150. };
  151. DEFINE_KSPROPERTY_CLOCKSET(
  152. ClockPropertyHandlers,
  153. CWaveClock::GetTime,
  154. CWaveClock::GetPhysicalTime,
  155. CWaveClock::GetCorrelatedTime,
  156. CWaveClock::GetCorrelatedPhysicalTime,
  157. CWaveClock::GetResolution,
  158. CWaveClock::GetState,
  159. CWaveClock::GetFunctionTable );
  160. DEFINE_KSPROPERTY_SET_TABLE( ClockPropertyTable )
  161. {
  162. DEFINE_KSPROPERTY_SET(
  163. &KSPROPSETID_Clock,
  164. SIZEOF_ARRAY( ClockPropertyHandlers ),
  165. ClockPropertyHandlers,
  166. 0,
  167. NULL)
  168. };
  169. DEFINE_KSEVENT_TABLE( ClockEventHandlers )
  170. {
  171. DEFINE_KSEVENT_ITEM(
  172. KSEVENT_CLOCK_INTERVAL_MARK,
  173. sizeof( KSEVENT_TIME_INTERVAL ),
  174. sizeof( ULONGLONG ) + sizeof( ULONGLONG ),
  175. (PFNKSADDEVENT) CWaveClock::AddEvent,
  176. NULL,
  177. NULL),
  178. DEFINE_KSEVENT_ITEM(
  179. KSEVENT_CLOCK_POSITION_MARK,
  180. sizeof( KSEVENT_TIME_MARK ),
  181. sizeof( ULONGLONG ),
  182. (PFNKSADDEVENT) CWaveClock::AddEvent,
  183. NULL,
  184. NULL)
  185. };
  186. DEFINE_KSEVENT_SET_TABLE( ClockEventTable )
  187. {
  188. DEFINE_KSEVENT_SET(
  189. &KSEVENTSETID_Clock,
  190. SIZEOF_ARRAY( ClockEventHandlers ),
  191. ClockEventHandlers)
  192. };
  193. #pragma code_seg("PAGE")
  194. /*****************************************************************************
  195. * CreateWaveClock()
  196. *****************************************************************************
  197. * Creates a CWaveClock object.
  198. */
  199. NTSTATUS
  200. CreateWaveClock
  201. (
  202. OUT PUNKNOWN * pUnknown,
  203. IN REFCLSID,
  204. IN PUNKNOWN pUnknownOuter OPTIONAL,
  205. IN POOL_TYPE poolType
  206. )
  207. {
  208. PAGED_CODE();
  209. ASSERT(pUnknown);
  210. _DbgPrintF(DEBUGLVL_LIFETIME,("Creating WAVECLK"));
  211. STD_CREATE_BODY_
  212. (
  213. CWaveClock,
  214. pUnknown,
  215. pUnknownOuter,
  216. poolType,
  217. PIRPTARGET
  218. );
  219. }
  220. /*****************************************************************************
  221. * PcNewWaveClock()
  222. *****************************************************************************
  223. * Creates a new wave clock.
  224. */
  225. NTSTATUS
  226. PcNewWaveClock
  227. ( OUT PIRPTARGET * ppIrpTarget,
  228. IN PUNKNOWN pUnknownOuter,
  229. IN POOL_TYPE poolType,
  230. IN PIRPSTREAMCONTROL pIrpStreamControl,
  231. IN PKSPIN_LOCK pKSpinLock,
  232. IN PLIST_ENTRY pListEntry
  233. )
  234. {
  235. PAGED_CODE();
  236. ASSERT(pIrpStreamControl);
  237. ASSERT(pKSpinLock);
  238. ASSERT(pListEntry);
  239. PUNKNOWN pUnknown;
  240. NTSTATUS ntStatus =
  241. CreateWaveClock
  242. ( &pUnknown,
  243. GUID_NULL,
  244. pUnknownOuter,
  245. poolType
  246. );
  247. if (NT_SUCCESS(ntStatus))
  248. {
  249. PIRPTARGETINIT pIrpTargetInit;
  250. ntStatus =
  251. pUnknown->QueryInterface
  252. ( IID_IIrpTarget,
  253. (PVOID *) &pIrpTargetInit
  254. );
  255. if (NT_SUCCESS(ntStatus))
  256. {
  257. ntStatus =
  258. pIrpTargetInit->Init
  259. ( pIrpStreamControl,
  260. pKSpinLock,
  261. pListEntry
  262. );
  263. if (NT_SUCCESS(ntStatus))
  264. {
  265. *ppIrpTarget = pIrpTargetInit;
  266. }
  267. else
  268. {
  269. pIrpTargetInit->Release();
  270. }
  271. }
  272. pUnknown->Release();
  273. }
  274. return ntStatus;
  275. }
  276. /*****************************************************************************
  277. * CWaveClock::Init()
  278. *****************************************************************************
  279. * Initializes a wave clock.
  280. */
  281. NTSTATUS
  282. CWaveClock::
  283. Init
  284. ( IN PIRPSTREAMCONTROL pIrpStreamControl,
  285. IN PKSPIN_LOCK pKSpinLock,
  286. IN PLIST_ENTRY pListEntry
  287. )
  288. {
  289. PAGED_CODE();
  290. _DbgPrintF(DEBUGLVL_LIFETIME,("Initializing WAVECLK (0x%08x)",this));
  291. ASSERT(pIrpStreamControl);
  292. ASSERT(pKSpinLock);
  293. ASSERT(pListEntry);
  294. //
  295. // Save parameters.
  296. //
  297. m_pIrpStreamControl = pIrpStreamControl;
  298. m_pIrpStreamControl->AddRef();
  299. m_pKSpinLock = pKSpinLock;
  300. //
  301. // Initialize other members.
  302. //
  303. KeInitializeMutex(&m_StateMutex,0);
  304. KeInitializeSpinLock(&m_EventLock);
  305. KeInitializeSpinLock(&m_ClockLock);
  306. InitializeListHead(&m_EventList);
  307. //
  308. // Point the wave clock node to the IWaveClock interface.
  309. //
  310. m_waveClockNode.pWaveClock = PWAVECLOCK(this);
  311. //
  312. // Add this clock to the list of clocks. We don't need to keep the list
  313. // head because removal does not require it. The spinlock will come in
  314. // handy, though.
  315. //
  316. ExInterlockedInsertTailList
  317. ( pListEntry,
  318. &m_waveClockNode.listEntry,
  319. pKSpinLock
  320. );
  321. return STATUS_SUCCESS;
  322. }
  323. #pragma code_seg()
  324. /*****************************************************************************
  325. * MyInterlockedRemoveEntryList()
  326. *****************************************************************************
  327. * Interlocked RemoveEntryList.
  328. */
  329. void
  330. MyInterlockedRemoveEntryList
  331. ( IN PLIST_ENTRY pListEntry,
  332. IN PKSPIN_LOCK pKSpinLock
  333. )
  334. {
  335. KIRQL kIrqlOld;
  336. KeAcquireSpinLock(pKSpinLock,&kIrqlOld);
  337. RemoveEntryList(pListEntry);
  338. KeReleaseSpinLock(pKSpinLock,kIrqlOld);
  339. }
  340. #pragma code_seg("PAGE")
  341. /*****************************************************************************
  342. * CWaveClock::~CWaveClock()
  343. *****************************************************************************
  344. * Destructor.
  345. */
  346. CWaveClock::~CWaveClock()
  347. {
  348. _DbgPrintF(DEBUGLVL_LIFETIME,("Destroying WAVECLK (0x%08x)",this));
  349. //
  350. // Remove us from the list if we are in it.
  351. //
  352. if (m_waveClockNode.listEntry.Flink)
  353. {
  354. MyInterlockedRemoveEntryList(&m_waveClockNode.listEntry,m_pKSpinLock);
  355. }
  356. //
  357. // Release the control interface if we have a reference.
  358. //
  359. if (m_pIrpStreamControl)
  360. {
  361. m_pIrpStreamControl->Release();
  362. }
  363. }
  364. /*****************************************************************************
  365. * CWaveClock::NonDelegatingQueryInterface()
  366. *****************************************************************************
  367. * Get an interface.
  368. */
  369. STDMETHODIMP_(NTSTATUS)
  370. CWaveClock::NonDelegatingQueryInterface
  371. (
  372. IN REFIID riid,
  373. OUT PVOID * ppvObject
  374. )
  375. {
  376. PAGED_CODE();
  377. ASSERT(ppvObject);
  378. _DbgPrintF(DEBUGLVL_BLAB,("CWaveClock::NonDelegatingQueryInterface"));
  379. if
  380. ( IsEqualGUIDAligned(riid,IID_IUnknown)
  381. || IsEqualGUIDAligned(riid,IID_IIrpTarget)
  382. )
  383. {
  384. *ppvObject = PVOID(PIRPTARGETINIT(this));
  385. }
  386. else
  387. if (IsEqualGUIDAligned(riid,IID_IWaveClock))
  388. {
  389. *ppvObject = PVOID(PWAVECLOCK(this));
  390. }
  391. else
  392. {
  393. *ppvObject = NULL;
  394. }
  395. if (*ppvObject)
  396. {
  397. PUNKNOWN(*ppvObject)->AddRef();
  398. return STATUS_SUCCESS;
  399. }
  400. return STATUS_INVALID_PARAMETER;
  401. }
  402. STDMETHODIMP_(NTSTATUS)
  403. CWaveClock::DeviceIoControl
  404. (
  405. IN PDEVICE_OBJECT DeviceObject,
  406. IN PIRP Irp
  407. )
  408. /*++
  409. Routine Description:
  410. Processes device I/O control for this file object on this device object
  411. Arguments:
  412. IN PDEVICE_OBJECT DeviceObject -
  413. pointer to the device object
  414. IN PIRP Irp -
  415. pointer to I/O request packet
  416. Return:
  417. STATUS_SUCCESS or an appropriate error code
  418. --*/
  419. {
  420. NTSTATUS Status;
  421. PIO_STACK_LOCATION irpSp;
  422. PAGED_CODE();
  423. ASSERT( DeviceObject );
  424. ASSERT( Irp );
  425. _DbgPrintF( DEBUGLVL_BLAB, ("CWaveClock::DeviceIoControl"));
  426. irpSp = IoGetCurrentIrpStackLocation( Irp );
  427. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  428. case IOCTL_KS_PROPERTY:
  429. Status =
  430. KsPropertyHandler(
  431. Irp,
  432. SIZEOF_ARRAY( ClockPropertyTable ),
  433. (PKSPROPERTY_SET) ClockPropertyTable );
  434. break;
  435. case IOCTL_KS_ENABLE_EVENT:
  436. _DbgPrintF( DEBUGLVL_VERBOSE, ("CWaveClock::EnableEvent"));
  437. Status =
  438. KsEnableEvent(
  439. Irp,
  440. SIZEOF_ARRAY( ClockEventTable ),
  441. (PKSEVENT_SET) ClockEventTable,
  442. NULL,
  443. KSEVENTS_NONE,
  444. NULL);
  445. break;
  446. case IOCTL_KS_DISABLE_EVENT:
  447. _DbgPrintF( DEBUGLVL_VERBOSE, ("CWaveClock::DisableEvent"));
  448. Status =
  449. KsDisableEvent(
  450. Irp,
  451. &m_EventList,
  452. KSEVENTS_SPINLOCK,
  453. &m_EventLock );
  454. break;
  455. default:
  456. return KsDefaultDeviceIoCompletion( DeviceObject, Irp );
  457. }
  458. Irp->IoStatus.Status = Status;
  459. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  460. return Status;
  461. }
  462. STDMETHODIMP_(NTSTATUS)
  463. CWaveClock::Close(
  464. IN PDEVICE_OBJECT DeviceObject,
  465. IN PIRP Irp
  466. )
  467. /*++
  468. Routine Description:
  469. Close handler for the clock file object
  470. Arguments:
  471. IN PDEVICE_OBJECT DeviceObject -
  472. pointer to the device object
  473. IN PIRP Irp -
  474. pointer to the I/O request packet
  475. Return:
  476. STATUS success or an appropriate error code
  477. --*/
  478. {
  479. PIO_STACK_LOCATION irpSp;
  480. PAGED_CODE();
  481. ASSERT(DeviceObject);
  482. ASSERT(Irp);
  483. _DbgPrintF( DEBUGLVL_VERBOSE, ("CWaveClock::Close"));
  484. irpSp = IoGetCurrentIrpStackLocation(Irp);
  485. //
  486. // Free events associated with this pin.
  487. //
  488. KsFreeEventList(
  489. irpSp->FileObject,
  490. &m_EventList,
  491. KSEVENTS_SPINLOCK,
  492. &m_EventLock );
  493. Irp->IoStatus.Information = 0;
  494. Irp->IoStatus.Status = STATUS_SUCCESS;
  495. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  496. return STATUS_SUCCESS;
  497. }
  498. DEFINE_INVALID_CREATE(CWaveClock);
  499. DEFINE_INVALID_READ(CWaveClock);
  500. DEFINE_INVALID_WRITE(CWaveClock);
  501. DEFINE_INVALID_FLUSH(CWaveClock);
  502. DEFINE_INVALID_QUERYSECURITY(CWaveClock);
  503. DEFINE_INVALID_SETSECURITY(CWaveClock);
  504. DEFINE_INVALID_FASTDEVICEIOCONTROL(CWaveClock);
  505. DEFINE_INVALID_FASTREAD(CWaveClock);
  506. DEFINE_INVALID_FASTWRITE(CWaveClock);
  507. #pragma code_seg()
  508. STDMETHODIMP_(NTSTATUS)
  509. CWaveClock::
  510. GenerateEvents
  511. ( void
  512. )
  513. {
  514. LONGLONG Time;
  515. PLIST_ENTRY ListEntry;
  516. if (m_DeviceState == KSSTATE_RUN) {
  517. Time = m_GetCurrentTime();
  518. ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );
  519. KeAcquireSpinLockAtDpcLevel( &m_EventLock );
  520. for(ListEntry = m_EventList.Flink;
  521. ListEntry != &m_EventList;) {
  522. PKSEVENT_ENTRY EventEntry;
  523. PKSINTERVAL Interval;
  524. EventEntry =
  525. (PKSEVENT_ENTRY)
  526. CONTAINING_RECORD( ListEntry, KSEVENT_ENTRY, ListEntry );
  527. //
  528. // Pre-inc, KsGenerateEvent() can remove this item from the list.
  529. //
  530. ListEntry = ListEntry->Flink;
  531. //
  532. // The event-specific data was added onto the end of the entry.
  533. //
  534. Interval = (PKSINTERVAL)(EventEntry + 1);
  535. //
  536. // Time for this event to go off.
  537. //
  538. if (Interval->TimeBase <= Time) {
  539. _DbgPrintF(
  540. DEBUGLVL_VERBOSE, ("Generating event for time: %ld at time: %ld",
  541. Interval->TimeBase, Time) );
  542. if (EventEntry->EventItem->EventId !=
  543. KSEVENT_CLOCK_INTERVAL_MARK) {
  544. //
  545. // A single-shot should only go off once, so make
  546. // it a value which will never be reached again.
  547. //
  548. Interval->TimeBase = 0x7fffffffffffffff;
  549. } else {
  550. LONGLONG Intervals;
  551. //
  552. // An interval timer should only go off once per time,
  553. // so update it to the next timeout.
  554. //
  555. Intervals =
  556. (Time - Interval->TimeBase + Interval->Interval - 1) / Interval->Interval;
  557. Interval->TimeBase += Intervals * Interval->Interval;
  558. }
  559. KsGenerateEvent( EventEntry );
  560. }
  561. }
  562. KeReleaseSpinLockFromDpcLevel( &m_EventLock );
  563. }
  564. return STATUS_SUCCESS;
  565. }
  566. STDMETHODIMP_(NTSTATUS)
  567. CWaveClock::SetState(
  568. KSSTATE State
  569. )
  570. /*++
  571. Routine Description:
  572. This method is called by the port to notify of a state change.
  573. Arguments:
  574. KSSTATE State -
  575. New state
  576. Return:
  577. STATUS_SUCCESS
  578. --*/
  579. {
  580. //
  581. // Synchronize with GetState,
  582. //
  583. KeWaitForMutexObject(
  584. &m_StateMutex,
  585. Executive,
  586. KernelMode,
  587. FALSE,
  588. NULL );
  589. //
  590. // set the new state,
  591. //
  592. m_DeviceState = State;
  593. switch (State) {
  594. case KSSTATE_STOP:
  595. m_LastTime = m_LastPhysicalTime = m_LastPhysicalPosition = 0;
  596. break;
  597. case KSSTATE_RUN:
  598. break;
  599. }
  600. //
  601. // and then release the mutex.
  602. //
  603. KeReleaseMutex( &m_StateMutex, FALSE );
  604. return STATUS_SUCCESS;
  605. }
  606. NTSTATUS
  607. CWaveClock::AddEvent(
  608. IN PIRP Irp,
  609. IN PKSEVENT_TIME_INTERVAL EventTime,
  610. IN PKSEVENT_ENTRY EventEntry
  611. )
  612. /*++
  613. Routine Description:
  614. This is the AddEvent() handler for the clock events.
  615. NOTE: This routine acquires a spinlock, must be in non-paged code.
  616. Arguments:
  617. IN PIRP Irp -
  618. pointer to the I/O request packet
  619. IN PKSEVENT_TIME_INTERVAL EventTime -
  620. specified time interval or one shot
  621. IN PKSEVENT_ENTRY EventEntry -
  622. pointer to event entry structure
  623. Return Value:
  624. STATUS_SUCCESS
  625. --*/
  626. {
  627. KIRQL irqlOld;
  628. PKSINTERVAL Interval;
  629. CWaveClock *pCWaveClock =
  630. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  631. ASSERT( pCWaveClock );
  632. _DbgPrintF( DEBUGLVL_VERBOSE, ("CWaveClock::AddEvent"));
  633. //
  634. // Space for the interval is located at the end of the basic
  635. // event structure.
  636. //
  637. Interval = (PKSINTERVAL)(EventEntry + 1);
  638. //
  639. // Either just an event time was passed, or a time base plus an
  640. // interval. In both cases the first LONGLONG is present and saved.
  641. //
  642. Interval->TimeBase = EventTime->TimeBase;
  643. if (EventEntry->EventItem->EventId == KSEVENT_CLOCK_INTERVAL_MARK)
  644. {
  645. Interval->Interval = EventTime->Interval;
  646. }
  647. KeAcquireSpinLock( &pCWaveClock->m_EventLock, &irqlOld );
  648. InsertHeadList( &pCWaveClock->m_EventList, &EventEntry->ListEntry );
  649. KeReleaseSpinLock( &pCWaveClock->m_EventLock, irqlOld );
  650. //
  651. // If this event is passed, signal immediately.
  652. // Note, KS_CLOCK_POSITION_MARK is a single-shot event
  653. //
  654. pCWaveClock->GenerateEvents();
  655. return STATUS_SUCCESS;
  656. }
  657. LONGLONG
  658. FASTCALL
  659. CWaveClock::
  660. GetCurrentTime
  661. (
  662. PFILE_OBJECT FileObject
  663. )
  664. /*++
  665. Routine Description:
  666. Computes the current presentation time.
  667. NOTE: This routine acquires a spinlock, must be in non-paged code.
  668. Arguments:
  669. PFILE_OBJECT FileObject -
  670. this clock's file object
  671. Return:
  672. resultant presentation time normalized to 100ns units.
  673. --*/
  674. {
  675. CWaveClock *pCWaveClock =
  676. (CWaveClock *) KsoGetIrpTargetFromFileObject(FileObject);
  677. return pCWaveClock->m_GetCurrentTime();
  678. }
  679. LONGLONG
  680. CWaveClock::
  681. m_GetCurrentTime
  682. ( void
  683. )
  684. /*++
  685. Routine Description:
  686. Computes the current presentation time.
  687. NOTE: This routine acquires a spinlock, must be in non-paged code.
  688. Arguments:
  689. Return:
  690. resultant presentation time normalized to 100ns units.
  691. --*/
  692. {
  693. IRPSTREAMPACKETINFO irpStreamPacketInfoUnmapping;
  694. KIRQL irqlOld;
  695. LONGLONG StreamTime;
  696. NTSTATUS Status;
  697. PIRPSTREAMCONTROL pIrpStreamControl;
  698. StreamTime = 0;
  699. //
  700. // Query the position from the IRP stream.
  701. //
  702. pIrpStreamControl = m_pIrpStreamControl;
  703. ASSERT(pIrpStreamControl);
  704. IRPSTREAM_POSITION irpStreamPosition;
  705. Status = pIrpStreamControl->GetPosition(&irpStreamPosition);
  706. if (NT_SUCCESS(Status))
  707. {
  708. //
  709. // Never exceed current stream extent.
  710. //
  711. if
  712. ( irpStreamPosition.ullStreamPosition
  713. > irpStreamPosition.ullCurrentExtent
  714. )
  715. {
  716. StreamTime =
  717. irpStreamPosition.ullCurrentExtent;
  718. }
  719. else
  720. {
  721. StreamTime =
  722. irpStreamPosition.ullStreamPosition;
  723. }
  724. StreamTime =
  725. pIrpStreamControl->NormalizePosition(StreamTime);
  726. }
  727. KeAcquireSpinLock( &m_ClockLock, &irqlOld );
  728. if (NT_SUCCESS( Status )) {
  729. if (StreamTime < m_LastTime) {
  730. _DbgPrintF(
  731. DEBUGLVL_VERBOSE,
  732. ("new time is less than last reported time! (%I64d, %I64d)",
  733. StreamTime, m_LastTime) );
  734. StreamTime = m_LastTime;
  735. } else {
  736. m_LastTime = StreamTime;
  737. }
  738. } else {
  739. StreamTime = m_LastTime;
  740. }
  741. KeReleaseSpinLock( &m_ClockLock, irqlOld );
  742. return StreamTime;
  743. }
  744. LONGLONG
  745. FASTCALL
  746. CWaveClock::GetCurrentCorrelatedTime(
  747. PFILE_OBJECT FileObject,
  748. PLONGLONG SystemTime
  749. )
  750. /*++
  751. Routine Description:
  752. Arguments:
  753. PFILE_OBJECT FileObject -
  754. PLONGLONG SystemTime -
  755. pointer
  756. Return:
  757. current presentation time in 100ns
  758. --*/
  759. {
  760. LARGE_INTEGER Time, Frequency;
  761. Time = KeQueryPerformanceCounter( &Frequency );
  762. //
  763. // Convert ticks to 100ns units.
  764. //
  765. *SystemTime = KSCONVERT_PERFORMANCE_TIME(Frequency.QuadPart,Time);
  766. return GetCurrentTime( FileObject );
  767. }
  768. LONGLONG
  769. FASTCALL
  770. CWaveClock::GetCurrentPhysicalTime(
  771. PFILE_OBJECT FileObject
  772. )
  773. /*++
  774. Routine Description:
  775. Computes the current physical time.
  776. NOTE: This routine acquires a spinlock, must be in non-paged code.
  777. Arguments:
  778. PFILE_OBJECT FileObject -
  779. this clock's file object
  780. Return:
  781. current physical time in 100ns
  782. --*/
  783. {
  784. KIRQL irqlOld;
  785. LONGLONG PhysicalTime;
  786. NTSTATUS Status;
  787. ULONG CurrentPosition;
  788. CWaveClock *pCWaveClock =
  789. (CWaveClock *) KsoGetIrpTargetFromFileObject(FileObject);
  790. PhysicalTime = 0;
  791. //
  792. // Query the position from the IRP stream.
  793. //
  794. PIRPSTREAMCONTROL pIrpStreamControl =
  795. pCWaveClock->m_pIrpStreamControl;
  796. ASSERT( pIrpStreamControl );
  797. IRPSTREAM_POSITION irpStreamPosition;
  798. Status = pIrpStreamControl->GetPosition(&irpStreamPosition);
  799. if (NT_SUCCESS(Status))
  800. {
  801. PhysicalTime =
  802. pIrpStreamControl->NormalizePosition
  803. ( irpStreamPosition.ullStreamPosition
  804. + irpStreamPosition.ullPhysicalOffset
  805. );
  806. }
  807. KeAcquireSpinLock( &pCWaveClock->m_ClockLock, &irqlOld );
  808. if (NT_SUCCESS( Status )) {
  809. //
  810. // Verify that this new physical time is >= to the last
  811. // reported physical time. If not, set the time to the
  812. // last reported time. Flag this as an error in debug.
  813. //
  814. if (PhysicalTime < pCWaveClock->m_LastPhysicalTime) {
  815. _DbgPrintF(
  816. DEBUGLVL_VERBOSE,
  817. ("new physical time is less than last reported physical time! (%I64d, %I64d)",
  818. PhysicalTime, pCWaveClock->m_LastPhysicalTime) );
  819. PhysicalTime = pCWaveClock->m_LastPhysicalTime;
  820. } else {
  821. //
  822. // Set m_LastPhysicalTime to the updated time.
  823. //
  824. pCWaveClock->m_LastPhysicalTime = PhysicalTime;
  825. }
  826. } else {
  827. PhysicalTime = pCWaveClock->m_LastPhysicalTime;
  828. }
  829. KeReleaseSpinLock( &pCWaveClock->m_ClockLock, irqlOld );
  830. return PhysicalTime;
  831. }
  832. LONGLONG
  833. FASTCALL
  834. CWaveClock::GetCurrentCorrelatedPhysicalTime(
  835. PFILE_OBJECT FileObject,
  836. PLONGLONG SystemTime
  837. )
  838. /*++
  839. Routine Description:
  840. Retrieves the current physical time correlated with the system time.
  841. Arguments:
  842. PFILE_OBJECT FileObject -
  843. this clock's file object
  844. PLONGLONG SystemTime -
  845. pointer to the resultant system time
  846. Return:
  847. current physical time in 100ns
  848. --*/
  849. {
  850. LARGE_INTEGER Time, Frequency;
  851. Time = KeQueryPerformanceCounter( &Frequency );
  852. //
  853. // Convert ticks to 100ns units.
  854. //
  855. *SystemTime = KSCONVERT_PERFORMANCE_TIME(Frequency.QuadPart,Time);
  856. return GetCurrentTime( FileObject );
  857. }
  858. #pragma code_seg("PAGE")
  859. NTSTATUS
  860. CWaveClock::GetFunctionTable(
  861. IN PIRP Irp,
  862. IN PKSPROPERTY Property,
  863. OUT PKSCLOCK_FUNCTIONTABLE FunctionTable
  864. )
  865. /*++
  866. Routine Description:
  867. Retrieves the DPC interface function table for this clock.
  868. Arguments:
  869. IN PIRP Irp -
  870. pointer to the I/O request packet
  871. IN PKSPROPERTY Property -
  872. pointer to the property structure
  873. OUT PKSCLOCK_FUNCTIONTABLE FunctionTable -
  874. pointer to the resultant function table
  875. Return:
  876. --*/
  877. {
  878. PAGED_CODE();
  879. FunctionTable->GetTime = GetCurrentTime;
  880. FunctionTable->GetPhysicalTime = GetCurrentPhysicalTime;
  881. FunctionTable->GetCorrelatedTime = GetCurrentCorrelatedTime;
  882. FunctionTable->GetCorrelatedPhysicalTime = GetCurrentCorrelatedPhysicalTime;
  883. Irp->IoStatus.Information = sizeof(*FunctionTable);
  884. return STATUS_SUCCESS;
  885. }
  886. NTSTATUS
  887. CWaveClock::GetCorrelatedTime(
  888. IN PIRP Irp,
  889. IN PKSPROPERTY Property,
  890. OUT PKSCORRELATED_TIME CorrelatedTime
  891. )
  892. /*++
  893. Routine Description:
  894. Retrieves the current presentation time correlated with the system time.
  895. Arguments:
  896. IN PIRP Irp -
  897. pointer to the I/O request packet
  898. IN PKSPROPERTY Property -
  899. pointer to the property structure
  900. OUT PKSCORRELATED_TIME CorrelatedTime -
  901. resultant correlated presentation time
  902. Return:
  903. STATUS_SUCCESS else an appropriate error code
  904. --*/
  905. {
  906. PAGED_CODE();
  907. CWaveClock *pCWaveClock =
  908. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  909. CorrelatedTime->Time =
  910. pCWaveClock->GetCurrentCorrelatedTime(
  911. IoGetCurrentIrpStackLocation( Irp )->FileObject,
  912. &CorrelatedTime->SystemTime );
  913. Irp->IoStatus.Information = sizeof( KSCORRELATED_TIME );
  914. return STATUS_SUCCESS;
  915. }
  916. NTSTATUS
  917. CWaveClock::GetTime(
  918. IN PIRP Irp,
  919. IN PKSPROPERTY Property,
  920. OUT PLONGLONG Time
  921. )
  922. /*++
  923. Routine Description:
  924. Retrieves the current presentation time.
  925. Arguments:
  926. IN PIRP Irp -
  927. pointer to the I/O request packet
  928. IN PKSPROPERTY Property -
  929. pointer to the property structure
  930. OUT PLONGLONG Time -
  931. resultant presentation time
  932. Return:
  933. STATUS_SUCCESS else an appropriate error code
  934. --*/
  935. {
  936. PAGED_CODE();
  937. CWaveClock *pCWaveClock =
  938. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  939. *Time = pCWaveClock->GetCurrentTime(
  940. IoGetCurrentIrpStackLocation( Irp )->FileObject );
  941. Irp->IoStatus.Information = sizeof( LONGLONG );
  942. return STATUS_SUCCESS;
  943. }
  944. NTSTATUS
  945. CWaveClock::GetCorrelatedPhysicalTime(
  946. IN PIRP Irp,
  947. IN PKSPROPERTY Property,
  948. OUT PKSCORRELATED_TIME CorrelatedTime
  949. )
  950. /*++
  951. Routine Description:
  952. Retrieves the current physical time correlated with the system time.
  953. Arguments:
  954. IN PIRP Irp -
  955. pointer to the I/O request packet
  956. IN PKSPROPERTY Property -
  957. pointer to the property structure
  958. OUT PKSCORRELATED_TIME CorrelatedTime -
  959. resultant correlated physical time
  960. Return:
  961. STATUS_SUCCESS else an appropriate error code
  962. --*/
  963. {
  964. PAGED_CODE();
  965. CWaveClock *pCWaveClock =
  966. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  967. CorrelatedTime->Time =
  968. pCWaveClock->GetCurrentCorrelatedPhysicalTime(
  969. IoGetCurrentIrpStackLocation( Irp )->FileObject,
  970. &CorrelatedTime->SystemTime );
  971. Irp->IoStatus.Information = sizeof( KSCORRELATED_TIME );
  972. return STATUS_SUCCESS;
  973. }
  974. NTSTATUS
  975. CWaveClock::GetPhysicalTime(
  976. IN PIRP Irp,
  977. IN PKSPROPERTY Property,
  978. OUT PLONGLONG Time
  979. )
  980. /*++
  981. Routine Description:
  982. Returns the clock's physical time. This is the actual clock physical time
  983. which is not halted for starvation, etc.
  984. Arguments:
  985. IN PIRP Irp -
  986. pointer to the I/O request packet
  987. IN PKSPROPERTY Property -
  988. pointer to the property structure
  989. OUT PLONGLONG Time -
  990. resultant time in 100 ns units
  991. Return:
  992. STATUS_SUCCESS or an appropriate error code
  993. --*/
  994. {
  995. PAGED_CODE();
  996. CWaveClock *pCWaveClock =
  997. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  998. *Time =
  999. pCWaveClock->GetCurrentPhysicalTime(
  1000. IoGetCurrentIrpStackLocation( Irp )->FileObject );
  1001. Irp->IoStatus.Information = sizeof( LONGLONG );
  1002. return STATUS_SUCCESS;
  1003. }
  1004. NTSTATUS
  1005. CWaveClock::GetResolution(
  1006. IN PIRP Irp,
  1007. IN PKSPROPERTY Property,
  1008. OUT PKSRESOLUTION Resolution
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. Retrieves the resolution of this clock.
  1013. Arguments:
  1014. IN PIRP Irp -
  1015. pointer to the I/O request packet
  1016. IN PKSPROPERTY Property -
  1017. pointer to the property structure
  1018. OUT PKSRESOLUTIONM Resolution -
  1019. pointer to the resultant resolution structure which stores the
  1020. granularity and error in 100ns units.
  1021. Return Value:
  1022. STATUS_SUCCESS
  1023. --*/
  1024. {
  1025. PAGED_CODE();
  1026. CWaveClock *pCWaveClock =
  1027. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  1028. //
  1029. // This clock has a resolution dependant on the data format. Assume
  1030. // that for cyclic devices, a byte position is computed for the DMA
  1031. // controller and convert this to 100ns units. The error (event
  1032. // notification error) is +/- NotificationFrequency/2
  1033. Resolution->Granularity =
  1034. pCWaveClock->m_pIrpStreamControl->NormalizePosition(1);
  1035. Resolution->Error =
  1036. (_100NS_UNITS_PER_SECOND / 1000 * WAVECYC_NOTIFICATION_FREQUENCY) / 2;
  1037. Irp->IoStatus.Information = sizeof(*Resolution);
  1038. return STATUS_SUCCESS;
  1039. }
  1040. NTSTATUS
  1041. CWaveClock::GetState(
  1042. IN PIRP Irp,
  1043. IN PKSPROPERTY Property,
  1044. OUT PKSSTATE State
  1045. )
  1046. /*++
  1047. Routine Description:
  1048. Returns the underlying pin's state.
  1049. Arguments:
  1050. IN PIRP Irp -
  1051. pointer to the I/O request packet
  1052. IN PKSPROPERTY Property -
  1053. pointer to the property structure
  1054. OUT PKSSTATE State -
  1055. pointer to resultant KSSTATE
  1056. Return:
  1057. STATUS_SUCCESS
  1058. --*/
  1059. {
  1060. PAGED_CODE();
  1061. CWaveClock *pCWaveClock =
  1062. (CWaveClock *) KsoGetIrpTargetFromIrp(Irp);
  1063. //
  1064. // Synchronize with SetState,
  1065. //
  1066. KeWaitForMutexObject(
  1067. &pCWaveClock->m_StateMutex,
  1068. Executive,
  1069. KernelMode,
  1070. FALSE,
  1071. NULL );
  1072. //
  1073. // retrieve the state
  1074. //
  1075. *State = pCWaveClock->m_DeviceState;
  1076. //
  1077. // and then release the mutex
  1078. //
  1079. KeReleaseMutex( &pCWaveClock->m_StateMutex, FALSE );
  1080. Irp->IoStatus.Information = sizeof(*State);
  1081. return STATUS_SUCCESS;
  1082. }