ReactOS 0.4.16-dev-329-g9223134
wavecyclicstream.cpp
Go to the documentation of this file.
1/********************************************************************************
2** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
3**
4** Portions Copyright (c) 1998-1999 Intel Corporation
5**
6********************************************************************************/
7
8// Every debug output has "Modulname text"
9#define STR_MODULENAME "AC97 Cyclic Stream: "
10
11#include "wavecyclicminiport.h"
12#include "wavecyclicstream.h"
13#define BUFFERTIME 10
14#define NBUFFERS 4
15
16#ifdef _MSC_VER
17#pragma code_seg("PAGE")
18#endif
19
22
23/*****************************************************************************
24 * General Info
25 *****************************************************************************
26 * To protect the stBDList structure that is used to store mappings, we use a
27 * spin lock called MapLock. This spin lock is also acquired when we change
28 * the DMA registers. Normally, changes in stBDList and the DMA registers go
29 * hand in hand. In case we only want to change the DMA registers, we need
30 * to acquire the spin lock!
31 */
32
33/*****************************************************************************
34 * CreateMiniportWaveCyclicStream
35 *****************************************************************************
36 * Creates a wave miniport stream object for the AC97 audio adapter. This is
37 * (nearly) like the macro STD_CREATE_BODY_ from STDUNK.H.
38 */
40(
41 OUT CMiniportWaveCyclicStream **MiniportCyclicStream,
42 IN PUNKNOWN pUnknownOuter,
44 __drv_reportError("Must succeed pool allocations are forbidden. "
45 "Allocation failures cause a system crash"))
47)
48{
49 PAGED_CODE ();
50
51 DOUT (DBG_PRINT, ("[CreateMiniportWaveCyclicStream]"));
52
53 //
54 // This is basically like the macro at stdunk with the change that we
55 // don't cast to interface unknown but to interface MiniportIchStream.
56 //
57 *MiniportCyclicStream = new (PoolType, PoolTag)
58 CMiniportWaveCyclicStream (pUnknownOuter);
59 if (*MiniportCyclicStream)
60 {
61 (*MiniportCyclicStream)->AddRef ();
62 return STATUS_SUCCESS;
63 }
64
66}
67
68
69/*****************************************************************************
70 * CMiniportWaveCyclicStream::~CMiniportWaveCyclicStream
71 *****************************************************************************
72 * Destructor
73 */
75{
76 PAGED_CODE ();
77
78
79 DOUT (DBG_PRINT, ("[CMiniportWaveCyclicStream::~CMiniportWaveCyclicStream]"));
80
81 // Release the scatter/gather table.
83}
84
85/*****************************************************************************
86 * CMiniportWaveCyclicStream::Init
87 *****************************************************************************
88 * This routine initializes the stream object, sets up the BDL, and programs
89 * the buffer descriptor list base address register for the pin being
90 * initialized.
91 */
93{
94 PAGED_CODE ();
95
96 DOUT (DBG_PRINT, ("[CMiniportWaveCyclicStream::Init]"));
97
98 //
99 // Setup the Buffer Descriptor List (BDL)
100 // Allocate 32 entries of 8 bytes (one BDL entry).
101 // The pointer is aligned on a 8 byte boundary (that's what we need).
102 //
103
104 if (!BDList_Alloc())
105 {
106 DOUT (DBG_ERROR, ("Failed AllocateCommonBuffer!"));
108 }
109
110 return ResizeBuffer();
111}
112
113STDMETHODIMP_(NTSTATUS) CMiniportWaveCyclicStream::SetFormat
114(
116)
117{
118 NTSTATUS ntStatus = CMiniportStream::SetFormat(Format);
119 if (!NT_SUCCESS (ntStatus))
120 return ntStatus;
121 return ResizeBuffer();
122}
123
125{
126 // calculate buffer size
127 DWORD nSamples = DataFormat->WaveFormatEx.nSamplesPerSec * BUFFERTIME / 1000;
128 DWORD bufferSize = DataFormat->WaveFormatEx.nBlockAlign * nSamples;
129 DWORD totalSize = bufferSize * NBUFFERS;
130
131 // allocate buffer
132 PDMACHANNEL DmaChannel = Miniport->DmaChannel;
133 DWORD allocSize = DmaChannel->AllocatedBufferSize();
134 if(totalSize > allocSize)
135 {
136 DmaChannel->FreeBuffer();
137 NTSTATUS ntStatus = DmaChannel->AllocateBuffer(totalSize, 0);
138 if (!NT_SUCCESS (ntStatus)) {
139 m_bufferSize = 0;
140 return ntStatus;
141 }
142 }
143
144 DmaChannel->SetBufferSize(totalSize);
145
146 // initialize bdList
147 DWORD addr = DmaChannel->PhysicalAddress().LowPart;
148 for (UINT loop = 0; loop < MAX_BDL_ENTRIES; loop++)
149 {
150 BDList[loop].dwPtrToPhyAddress = addr + bufferSize * (loop % NBUFFERS);
151 BDList[loop].wLength = (WORD)bufferSize/2;
153 }
154
155 // update buffer size
157 return STATUS_SUCCESS;
158}
159
160
161STDMETHODIMP_(ULONG) CMiniportWaveCyclicStream::SetNotificationFreq
162(
164 _Out_ PULONG FrameSize
165)
166{
167 *FrameSize = m_bufferSize;
168 return BUFFERTIME;
169}
170
171/*****************************************************************************
172 * Non paged code begins here
173 *****************************************************************************
174 */
175
176#ifdef _MSC_VER
177#pragma code_seg()
178#endif
179
181
182STDMETHODIMP_(void) CMiniportWaveCyclicStream::Silence
183(
186)
187{
189}
190
191/*****************************************************************************
192 * CMiniportWaveCyclicStream::GetPosition
193 *****************************************************************************
194 * Gets the stream position. This is a byte count of the current position of
195 * a stream running on a particular DMA engine. We must return a sample
196 * accurate count or the MiniportDrv32 wave drift tests (35.2 & 36.2) will fail.
197 *
198 * The position is the sum of three parts:
199 * 1) The total number of bytes in released buffers
200 * 2) The position in the current buffer.
201 * 3) The total number of bytes in played but not yet released buffers
202 */
203STDMETHODIMP_(NTSTATUS) CMiniportWaveCyclicStream::GetPosition
204(
206)
207{
208 UCHAR nCurrentIndex ;
209
211
212 nCurrentIndex = GetBuffPos((DWORD*)Position);
213 nCurrentIndex %= NBUFFERS;
214 *Position += nCurrentIndex * m_bufferSize;
215
216 return STATUS_SUCCESS;
217}
218
220{
221 //
222 // Update the LVI so that we cycle around in the scatter gather list.
223 //
225
226 //
227 // Request DPC service for PCM out.
228 //
229 Miniport->Port->Notify (ServiceGroup);
230}
#define PAGED_CODE()
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
tBDEntry * BDList
Definition: stream.h:61
PVOID BDList_Alloc()
Definition: stream2.cpp:11
void BDList_Free()
Definition: stream2.cpp:25
CMiniport * Miniport
Definition: stream.h:42
void UpdateLviCyclic()
Definition: stream.h:172
int GetBuffPos(DWORD *buffPos)
Definition: stream.cpp:509
PSERVICEGROUP ServiceGroup
Definition: stream.h:55
PDMACHANNEL DmaChannel
Definition: miniport.h:33
PPORT_ Port
Definition: miniport.h:30
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define DOUT(lvl, strings)
Definition: debug.h:82
#define IMP_CMiniportStream_QueryInterface(cType, sType)
Definition: stream.h:185
#define IMP_CMiniport_SetState(cType)
Definition: stream.h:192
#define IMP_CMiniport_NormalizePhysicalPosition(cType)
Definition: stream.h:196
#define __drv_reportError(why)
Definition: driverspecs.h:320
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
size_t bufferSize
GLenum const GLvoid * addr
Definition: glext.h:9621
const USHORT IOC_ENABLE
Definition: ichreg.h:103
const USHORT BUP_SET
Definition: ichreg.h:104
#define ASSERT(a)
Definition: mode.c:44
unsigned int UINT
Definition: ndis.h:50
DWORD Interval
Definition: netstat.c:30
#define DBG_ERROR
Definition: nfs41_debug.h:78
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _When_(c, a)
Definition: no_sal2.h:38
IDmaChannel * PDMACHANNEL
Definition: portcls.h:784
const int MAX_BDL_ENTRIES
Definition: rtstream.h:24
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
WORD wPolicyBits
Definition: stream.h:33
WORD wLength
Definition: stream.h:32
DWORD dwPtrToPhyAddress
Definition: stream.h:31
static COORD Position
Definition: mouse.c:34
uint32_t * PULONG
Definition: typedefs.h:59
INT POOL_TYPE
Definition: typedefs.h:78
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define BUFFERTIME
STDMETHODIMP_(void) CMiniportWaveCyclicStream
#define NBUFFERS
NTSTATUS CreateMiniportWaveCyclicStream(OUT CMiniportWaveCyclicStream **MiniportCyclicStream, IN PUNKNOWN pUnknownOuter, _When_((PoolType &NonPagedPoolMustSucceed) !=0, __drv_reportError("Must succeed pool allocations are forbidden. " "Allocation failures cause a system crash")) IN POOL_TYPE PoolType)
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG PoolTag
Definition: wdfmemory.h:164
#define DBG_PRINT(ppi, ch, level)
Definition: win32kdebug.h:169
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
@ NonPagedPoolMustSucceed
Definition: ketypes.h:880
unsigned char UCHAR
Definition: xmlstorage.h:181