ReactOS  0.4.15-dev-4872-g8a3db97
CMiniportWaveICHStream Class Reference

#include <wavepcistream.h>

Inheritance diagram for CMiniportWaveICHStream:
Collaboration diagram for CMiniportWaveICHStream:

Public Member Functions

 DECLARE_STD_UNKNOWN ()
 
 DEFINE_STD_CONSTRUCTOR (CMiniportWaveICHStream)
 
 ~CMiniportWaveICHStream ()
 
NTSTATUS Init_ ()
 
void PowerChangeNotify_ (IN POWER_STATE NewState)
 
void InterruptServiceRoutine ()
 
- Public Member Functions inherited from CMiniportStream
 ~CMiniportStream ()
 
void ResetDMA (void)
 
void PauseDMA (void)
 
void ResumeDMA (ULONG state=DMA_ENGINE_ON)
 
int GetBuffPos (DWORD *buffPos)
 
void WriteReg8 (ULONG addr, UCHAR data)
 
void WriteReg16 (ULONG addr, USHORT data)
 
void WriteReg32 (ULONG addr, ULONG data)
 
UCHAR ReadReg8 (ULONG addr)
 
USHORT ReadReg16 (ULONG addr)
 
ULONG ReadReg32 (ULONG addr)
 
 STDMETHODIMP_ (NTSTATUS) SetFormat(_In_ PKSDATAFORMAT Format)
 
void PowerChangeNotify (IN POWER_STATE NewState)
 
ULONG GetCurrentSampleRate (void)
 
NTSTATUS Init (IN CMiniport *Miniport_, IN PUNKNOWN PortStream, IN WavePins Pin_, IN BOOLEAN Capture_, IN PKSDATAFORMAT DataFormat_, OUT PSERVICEGROUP *ServiceGroup_)
 
NTSTATUS NonDelegatingQueryInterface (_In_ REFIID Interface, _COM_Outptr_ PVOID *Object, _In_ REFIID iStream, _In_ PUNKNOWN stream)
 
NTSTATUS SetState (_In_ KSSTATE State)
 
NTSTATUS NormalizePhysicalPosition (_Inout_ PLONGLONG PhysicalPosition)
 
PVOID BDList_Alloc ()
 
void BDList_Free ()
 
void UpdateLviCyclic ()
 

Public Attributes

 IMP_IMiniportWavePciStream
 
- Public Attributes inherited from CUnknown
union {
   IUnknown   IUnknown
 
   INonDelegatingUnknown   INonDelegatingUnknown
 
}; 
 
LONG m_ref_count
 
PUNKNOWN m_outer_unknown
 
- Public Attributes inherited from CMiniportStream
CMiniportMiniport
 
WavePins Pin
 
BOOL Capture
 
WORD NumberOfChannels
 
DEVICE_POWER_STATE m_PowerState
 
PPORTSTREAM_ PortStream
 
PKSDATAFORMAT_WAVEFORMATEX DataFormat
 
PSERVICEGROUP ServiceGroup
 
ULONG CurrentRate
 
ULONG DMAEngineState
 
ULONG m_ulBDAddr
 
PHYSICAL_ADDRESS BDList_PhysAddr
 
tBDEntryBDList
 
 IMP_IDrmAudioStream
 

Private Member Functions

NTSTATUS GetNewMappings (void)
 
NTSTATUS ReleaseUsedMappings (void)
 
CMiniportWaveICHWave ()
 

Private Attributes

KSPIN_LOCK MapLock
 
ULONGLONG TotalBytesMapped
 
ULONGLONG TotalBytesReleased
 
BOOL m_inGetMapping
 
tBDList stBDList
 

Detailed Description

Definition at line 57 of file wavepcistream.h.

Constructor & Destructor Documentation

◆ ~CMiniportWaveICHStream()

CMiniportWaveICHStream::~CMiniportWaveICHStream ( )

Definition at line 73 of file wavepcistream.cpp.

74 {
75  PAGED_CODE ();
76 
77 
78  DOUT (DBG_PRINT, ("[CMiniportWaveICHStream::~CMiniportWaveICHStream]"));
79 
80  //
81  // Print information about the scatter gather list.
82  //
83  DOUT (DBG_DMA, ("Head %d, Tail %d, Entries %d.",
86 
87  // Release the scatter/gather table.
88  BDList_Free();
89 }
#define DOUT(lvl, strings)
Definition: debug.h:82
const int DBG_DMA
Definition: debug.h:24
void BDList_Free()
Definition: stream2.cpp:25
const int DBG_PRINT
Definition: debug.h:17
#define PAGED_CODE()

Member Function Documentation

◆ DECLARE_STD_UNKNOWN()

CMiniportWaveICHStream::DECLARE_STD_UNKNOWN ( )

◆ DEFINE_STD_CONSTRUCTOR()

CMiniportWaveICHStream::DEFINE_STD_CONSTRUCTOR ( CMiniportWaveICHStream  )

◆ GetNewMappings()

NTSTATUS CMiniportWaveICHStream::GetNewMappings ( void  )
private

Definition at line 553 of file wavepcistream.cpp.

554 {
555  KIRQL OldIrql;
556 
557  NTSTATUS ntStatus = STATUS_SUCCESS;
558  ULONG ulBytesMapped = 0;
559  int nInsertMappings = 0;
560  int nTail; // aut. variable
561 
562  DOUT (DBG_PRINT, ("[CMiniportWaveICHStream::GetNewMappings]"));
563 
564  // acquire the mapping spin lock
566 
567  // detect reentrance
568  if(m_inGetMapping) {
569  m_inGetMapping = 2;
571  return STATUS_SUCCESS;
572  }
573 
574 #if (DBG)
575  if (ReadReg16 (X_SR) & SR_CELV)
576  {
577  //
578  // We starve. :-(
579  //
580  DOUT (DBG_DMA, ("[GetNewMappings] We starved ... Head %d, Tail %d, Entries %d.",
582  }
583 #endif
584 
585  //
586  // Get available mappings up to the max of 31 that we can hold in the BDL.
587  //
588  while (stBDList.nBDEntries < (MAX_BDL_ENTRIES - 1))
589  {
590  //
591  // Get the information from the list.
592  //
593  ULONG Flags;
595  ULONG ulBufferLength;
596  PHYSICAL_ADDRESS PhysAddr;
597  PVOID VirtAddr;
598 
599 
600  // Release the mapping spin lock
601 NEW_MAPPINGS_AVAILBLE_MAYBE:
604 
605  //
606  // Try to get the mapping from the port.
607  // Here comes the problem: When calling GetMapping or ReleaseMapping we
608  // cannot hold our spin lock. So we need to buffer the return values and
609  // stick the information into the structure later when we have the spin
610  // lock acquired.
611  //
612  ntStatus = PortStream->GetMapping ((PVOID)ULongToPtr(ulTag),
613  (PPHYSICAL_ADDRESS)&PhysAddr,
614  &VirtAddr,
615  &ulBufferLength,
616  &Flags);
617 
618  // Acquire the mapping spin lock
620 
621  //
622  // Quit this loop when we run out of mappings.
623  //
624  if (!NT_SUCCESS (ntStatus))
625  {
626  if(m_inGetMapping == 2)
627  goto NEW_MAPPINGS_AVAILBLE_MAYBE;
628  break;
629  }
630 
631  // Sanity check: The audio stack will not give you data
632  // that you cannot handle, but an application could use
633  // DirectKS and send bad buffer down.
634 
635  // One mapping needs to be <0x1FFFF bytes for mono
636  // streams on the AC97.
637  if (ulBufferLength > 0x1FFFE)
638  {
639  // That is a little too long. That should never happen.
640  DOUT (DBG_ERROR, ("[GetNewMappings] Buffer length too long!"));
641  ulBufferLength = 0x1FFFE;
642  }
643 
644  // The AC97 can only handle WORD aligned buffers.
645  if (PhysAddr.LowPart & 0x01)
646  {
647  // we cannot play that! Set the buffer length to 0 so
648  // that the HW will skip the buffer.
649  DOUT (DBG_WARNING, ("[GetNewMappings] Buffer address unaligned!"));
650  ulBufferLength = 0;
651  }
652 
653  // The AC97 cannot handle unaligned mappings with respect
654  // to the frame size (eg. 42 bytes on 4ch playback).
655  if (ulBufferLength % NumberOfChannels)
656  {
657  // modify the length (don't play the rest of the bytes)
658  DOUT (DBG_WARNING, ("[GetNewMappings] Buffer length unaligned!"));
659  ulBufferLength -= ulBufferLength % NumberOfChannels;
660  }
661 
662  //
663  // Save the mapping.
664  //
665  nTail = stBDList.nTail;
666  stBDList.pMapData[nTail].ulBufferLength = ulBufferLength;
667  stBDList.pMapData[nTail].ulState = 1;
668  ulBytesMapped += ulBufferLength;
669 
670  //
671  // Fill in the BDL entry with pointer to physical address and length.
672  //
673  BDList[nTail].dwPtrToPhyAddress = PhysAddr.LowPart;
674  BDList[nTail].wLength = (WORD)(ulBufferLength >> 1);
675  BDList[nTail].wPolicyBits = BUP_SET;
676 
677  //
678  // Generate an interrupt when portcls tells us to or roughly every 10ms.
679  //
680  if (Flags || (ulBytesMapped > (CurrentRate * NumberOfChannels * 2) / 100))
681  {
682  BDList[nTail].wPolicyBits |= IOC_ENABLE;
683  ulBytesMapped = 0;
684  }
685 
686  //
687  // Take the new mapping into account.
688  //
691  TotalBytesMapped += (ULONGLONG)ulBufferLength;
692  nInsertMappings++;
693 
694  //
695  // Set last valid index (LVI) register! We need to do this here to avoid inconsistency
696  // of the BDList with the HW. Note that we need to release spin locks every time
697  // we call into portcls, that means we can be interrupted by ReleaseUsedMappings.
698  //
699  WriteReg8 (X_LVI, (UCHAR)nTail);
700  }
701 
702  //
703  // If there were processed mappings, print out some debug messages and eventually try to
704  // restart DMA engine.
705  //
706  if (nInsertMappings)
707  {
708  //
709  // Print debug information ...
710  //
711  DOUT (DBG_DMA, ("[GetNewMappings] Got %d mappings.", nInsertMappings));
712  DOUT (DBG_DMA, ("[GetNewMappings] Head %d, Tail %d, Entries %d.",
714 
715  if(stBDList.nBDEntries >= 2)
717  }
718 
719  // Release the mapping spin lock
722 
723  return ntStatus;
724 }
const USHORT SR_CELV
Definition: ichreg.h:62
ULONG ulBufferLength
const int DBG_WARNING
Definition: debug.h:18
#define ULongToPtr(ul)
Definition: basetsd.h:92
WORD wLength
Definition: stream.h:32
#define TRUE
Definition: types.h:120
tMapData * pMapData
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
const USHORT BUP_SET
Definition: ichreg.h:104
#define DOUT(lvl, strings)
Definition: debug.h:82
UCHAR KIRQL
Definition: env_spec_w32.h:591
void WriteReg8(ULONG addr, UCHAR data)
Definition: stream.cpp:623
#define FALSE
Definition: types.h:117
USHORT ReadReg16(ULONG addr)
Definition: stream.cpp:631
WORD NumberOfChannels
Definition: stream.h:45
const int DBG_DMA
Definition: debug.h:24
ULONG ulState
Definition: wavepcistream.h:30
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
uint64_t ULONGLONG
Definition: typedefs.h:67
unsigned short WORD
Definition: ntddk_ex.h:93
const ULONG X_SR
Definition: ichreg.h:53
const int DBG_ERROR
Definition: debug.h:19
unsigned char UCHAR
Definition: xmlstorage.h:181
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
const USHORT IOC_ENABLE
Definition: ichreg.h:103
const int MAX_BDL_ENTRIES
Definition: rtstream.h:24
ULONG LowPart
Definition: typedefs.h:106
WORD wPolicyBits
Definition: stream.h:33
_In_ ULONG _In_ ULONG ulTag
Definition: winddi.h:3941
const int BDL_MASK
Definition: rtstream.h:29
ULONG CurrentRate
Definition: stream.h:56
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
const ULONG X_LVI
Definition: ichreg.h:52
PPORTSTREAM_ PortStream
Definition: stream.h:48
void ResumeDMA(ULONG state=DMA_ENGINE_ON)
Definition: stream.cpp:599
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
tBDEntry * BDList
Definition: stream.h:61
const int DMA_ENGINE_PAUSE
Definition: stream.h:5
const int DBG_PRINT
Definition: debug.h:17
DWORD dwPtrToPhyAddress
Definition: stream.h:31

Referenced by STDMETHODIMP_().

◆ Init_()

NTSTATUS CMiniportWaveICHStream::Init_ ( )
virtual

Reimplemented from CMiniportStream.

Definition at line 99 of file wavepcistream.cpp.

100 {
101  PAGED_CODE ();
102 
103  DOUT (DBG_PRINT, ("[CMiniportWaveICHStream::Init]"));
104 
105  //
106  // The rule here is that we return when we fail without a cleanup.
107  // The destructor will relase the allocated memory.
108  //
109 
110  //
111  // Initialize the BDL spinlock.
112  //
114 
115  //
116  // Setup the Buffer Descriptor List (BDL)
117  // Allocate 32 entries of 8 bytes (one BDL entry).
118  // The pointer is aligned on a 8 byte boundary (that's what we need).
119  //
120 
121  if (!BDList_Alloc())
122  {
123  DOUT (DBG_ERROR, ("Failed AllocateCommonBuffer!"));
125  }
126 
127  PPREFETCHOFFSET PreFetchOffset;
128  //
129  // Query for the new interface "PreFetchOffset" and use
130  // function offered there in case the interface is offered.
131  //
132  if (NT_SUCCESS(PortStream->QueryInterface(IID_IPreFetchOffset, (PVOID *)&PreFetchOffset)))
133  {
134  // why don't we pad by 32 sample frames
135  PreFetchOffset->SetPreFetchOffset(32 * (DataFormat->WaveFormatEx.nChannels * 2));
136  PreFetchOffset->Release();
137  }
138 
139  return STATUS_SUCCESS;
140 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
IPreFetchOffset * PPREFETCHOFFSET
Definition: portcls.h:2297
#define DOUT(lvl, strings)
Definition: debug.h:82
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:240
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
nsrefcnt Release()
const int DBG_ERROR
Definition: debug.h:19
PPORTSTREAM_ PortStream
Definition: stream.h:48
PVOID BDList_Alloc()
Definition: stream2.cpp:11
#define STATUS_SUCCESS
Definition: shellext.h:65
const int DBG_PRINT
Definition: debug.h:17
#define PAGED_CODE()

◆ InterruptServiceRoutine()

void CMiniportWaveICHStream::InterruptServiceRoutine ( )
virtual

Reimplemented from CMiniportStream.

Definition at line 417 of file rtstream.cpp.

418 {
419  //
420  // Update the LVI so that we cycle around in the scatter gather list.
421  //
422  UpdateLviCyclic();
423 }
void UpdateLviCyclic()
Definition: stream.h:172

◆ PowerChangeNotify_()

void CMiniportWaveICHStream::PowerChangeNotify_ ( IN POWER_STATE  NewState)
virtual

Reimplemented from CMiniportStream.

Definition at line 203 of file wavepcistream.cpp.

206 {
207  KIRQL OldIrql;
208 
210 
211  if(NewState.DeviceState == PowerDeviceD0)
212  {
213  ResetDMA ();
214 
215  // Restore the remaining DMA registers, that is last valid index
216  // only if the index is not pointing to 0. Note that the index is
217  // equal to head + entries.
218  if (stBDList.nTail)
219  {
220  WriteReg8 (X_LVI, (UCHAR)((stBDList.nTail - 1) & BDL_MASK));
221  }
222  }
223  else
224  {
225 
226  // Disable interrupts and stop DMA just in case.
227  WriteReg8 (X_CR, (UCHAR)0);
228 
229  // Get current index
230  // int nCurrentIndex = (int)ReadReg8 (X_CIV);
231  }
232 
234 }
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
void ResetDMA(void)
Definition: stream.cpp:544
const ULONG X_CR
Definition: ichreg.h:56
UCHAR KIRQL
Definition: env_spec_w32.h:591
void WriteReg8(ULONG addr, UCHAR data)
Definition: stream.cpp:623
unsigned char UCHAR
Definition: xmlstorage.h:181
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
const int BDL_MASK
Definition: rtstream.h:29
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
const ULONG X_LVI
Definition: ichreg.h:52

◆ ReleaseUsedMappings()

NTSTATUS CMiniportWaveICHStream::ReleaseUsedMappings ( void  )
private

Definition at line 735 of file wavepcistream.cpp.

736 {
737  KIRQL OldIrql;
738  int nMappingsReleased = 0;
739 
740  DOUT (DBG_PRINT, ("[CMiniportWaveICHStream::ReleaseUsedMappings]"));
741 
742  // acquire the mapping spin lock
744 
745  //
746  // Clean up everything to that index.
747  //
748  while (stBDList.nBDEntries)
749  {
750  //
751  // Get current index
752  //
753  int nCurrentIndex = (int)ReadReg8 (X_CIV);
754 
755  //
756  // When CIV is == Head -1 we released all mappings.
757  //
758  if (nCurrentIndex == ((stBDList.nHead - 1) & BDL_MASK))
759  {
760  break;
761  }
762 
763  //
764  // Check if CIV is between head and tail.
765  //
766  if (nCurrentIndex < stBDList.nHead)
767  {
768  //
769  // Check for CIV being outside range.
770  //
771  if ((nCurrentIndex + MAX_BDL_ENTRIES) >=
773  {
774  DOUT (DBG_ERROR, ("[ReleaseUsedMappings] CIV out of range!"));
775  break;
776  }
777  }
778  else
779  {
780  //
781  // Check for CIV being outside range.
782  //
783  if (nCurrentIndex >= (stBDList.nHead + stBDList.nBDEntries))
784  {
785  DOUT (DBG_ERROR, ("[ReleaseUsedMappings] CIV out of range!"));
786  break;
787  }
788  }
789 
790  //
791  // Check to see if we've released all the buffers.
792  //
793  if (stBDList.nHead == nCurrentIndex)
794  {
795  if (nCurrentIndex == ((stBDList.nTail - 1) & BDL_MASK))
796  {
797  //
798  // A special case is starvation or stop of stream, when the
799  // DMA engine finished playing the buffers, CVI is equal LVI
800  // and SR_CELV is set.
801  //
802  if (!(ReadReg16 (X_SR) & SR_CELV))
803  {
804  // It is still playing the last buffer.
805  break;
806  }
807 
808  //
809  // In case the CVI=LVI bit is set, nBDEntries should be 1
810  //
811  if (stBDList.nBDEntries != 1)
812  {
813  DOUT (DBG_ERROR, ("[ReleaseUsedMappings] Inconsitency: Tail reached and Entries != 1."));
814  }
815  }
816  else
817  {
818  //
819  // Bail out. Current Index did not move.
820  //
821  break;
822  }
823  }
824 
825  //
826  // Save the tag and remove the entry from the list.
827  //
831  nMappingsReleased++;
832 
833  // if entry has not been revoked
834  if(stBDList.pMapData[ulTag].ulState == 1)
835  {
837 
838  // Release the mapping spin lock
840 
841  //
842  // Release this entry.
843  //
844  PortStream->ReleaseMapping ((PVOID)ULongToPtr(ulTag));
845 
846  // acquire the mapping spin lock
848  }
849 
851  }
852 
853 
854  // Print some debug information in case we released mappings.
855  if (nMappingsReleased)
856  {
857  //
858  // Print release information and return.
859  //
860  DOUT (DBG_DMA, ("[ReleaseUsedMappings] Head %d, Tail %d, Entries %d.",
862  }
863 
864  // Release the mapping spin lock
866 
867  return STATUS_SUCCESS;
868 }
const USHORT SR_CELV
Definition: ichreg.h:62
ULONG ulBufferLength
#define ULongToPtr(ul)
Definition: basetsd.h:92
tMapData * pMapData
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
const ULONG X_CIV
Definition: ichreg.h:51
#define DOUT(lvl, strings)
Definition: debug.h:82
UCHAR KIRQL
Definition: env_spec_w32.h:591
USHORT ReadReg16(ULONG addr)
Definition: stream.cpp:631
const int DBG_DMA
Definition: debug.h:24
ULONG ulState
Definition: wavepcistream.h:30
uint64_t ULONGLONG
Definition: typedefs.h:67
const ULONG X_SR
Definition: ichreg.h:53
const int DBG_ERROR
Definition: debug.h:19
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
const int MAX_BDL_ENTRIES
Definition: rtstream.h:24
_In_ ULONG _In_ ULONG ulTag
Definition: winddi.h:3941
const int BDL_MASK
Definition: rtstream.h:29
ULONGLONG TotalBytesReleased
Definition: wavepcistream.h:67
UCHAR ReadReg8(ULONG addr)
Definition: stream.cpp:629
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
PPORTSTREAM_ PortStream
Definition: stream.h:48
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65
const int DBG_PRINT
Definition: debug.h:17
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31

Referenced by STDMETHODIMP_().

◆ Wave()

CMiniportWaveICH* CMiniportWaveICHStream::Wave ( )
inlineprivate

Definition at line 91 of file wavepcistream.h.

91  {
92  return (CMiniportWaveICH*)Miniport; }
CMiniport * Miniport
Definition: stream.h:42

Member Data Documentation

◆ IMP_IMiniportWavePciStream

CMiniportWaveICHStream::IMP_IMiniportWavePciStream

Definition at line 114 of file wavepcistream.h.

◆ m_inGetMapping

BOOL CMiniportWaveICHStream::m_inGetMapping
private

Definition at line 68 of file wavepcistream.h.

Referenced by GetNewMappings().

◆ MapLock

KSPIN_LOCK CMiniportWaveICHStream::MapLock
private

Definition at line 65 of file wavepcistream.h.

Referenced by GetNewMappings(), Init_(), PowerChangeNotify_(), and ReleaseUsedMappings().

◆ stBDList

tBDList CMiniportWaveICHStream::stBDList
private

◆ TotalBytesMapped

ULONGLONG CMiniportWaveICHStream::TotalBytesMapped
private

Definition at line 66 of file wavepcistream.h.

Referenced by GetNewMappings().

◆ TotalBytesReleased

ULONGLONG CMiniportWaveICHStream::TotalBytesReleased
private

Definition at line 67 of file wavepcistream.h.

Referenced by ReleaseUsedMappings().


The documentation for this class was generated from the following files: