xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CDaffyDuck.h (revision 7120e97489acbf17d86d3f33e3b2e68974fd4b23)
1 // ****************************************************************************
2 //
3 //		CDaffyDuck.H
4 //
5 //		Include file for interfacing with the CDaffyDuck class.
6 //
7 //		A daffy duck maintains a scatter-gather list used by the DSP to
8 //		transfer audio data via bus mastering.
9 //
10 //		The scatter-gather list takes the form of a circular buffer of
11 //		duck entries; each duck entry is an address/count pair that points
12 //		to an audio data buffer somewhere in memory.
13 //
14 //		Although the scatter-gather list itself is a circular buffer, that
15 // 	does not mean that the audio data pointed to by the scatter-gather
16 //		list is necessarily a circular buffer.  The audio buffers pointed to
17 // 	by the SG list may be either a non-circular linked list of buffers
18 //		or a ring buffer.
19 //
20 //		If you want a ring DMA buffer for your audio data, refer to the
21 //		Wrap() method, below.
22 //
23 //		The name "daffy duck" is an inside joke that dates back to the
24 //		original VxD for Windows 95.
25 //
26 //		Set editor tabs to 3 for your viewing pleasure.
27 //
28 //---------------------------------------------------------------------------
29 //
30 //		Copyright Echo Digital Audio Corporation (c) 1998 - 2002
31 //		All rights reserved
32 //		www.echoaudio.com
33 //
34 //		Permission is hereby granted, free of charge, to any person obtaining a
35 //		copy of this software and associated documentation files (the
36 //		"Software"), to deal with the Software without restriction, including
37 //		without limitation the rights to use, copy, modify, merge, publish,
38 //		distribute, sublicense, and/or sell copies of the Software, and to
39 //		permit persons to whom the Software is furnished to do so, subject to
40 //		the following conditions:
41 //
42 //		- Redistributions of source code must retain the above copyright
43 //		notice, this list of conditions and the following disclaimers.
44 //
45 //		- Redistributions in binary form must reproduce the above copyright
46 //		notice, this list of conditions and the following disclaimers in the
47 //		documentation and/or other materials provided with the distribution.
48 //
49 //		- Neither the name of Echo Digital Audio, nor the names of its
50 //		contributors may be used to endorse or promote products derived from
51 //		this Software without specific prior written permission.
52 //
53 //		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
54 //		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55 //		MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56 //		IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
57 //		ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58 //		TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59 //		SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
60 //
61 // ****************************************************************************
62 
63 //	Prevent problems with multiple includes
64 
65 #ifndef _DAFFYDUCKOBJECT_
66 #define _DAFFYDUCKOBJECT_
67 
68 #ifdef _DEBUG
69 #define INTEGRITY_CHECK
70 #endif
71 
72 //
73 // DUCKENTRY is a single entry for the scatter-gather list.  A DUCKENTRY
74 // struct is read by the DSP.
75 //
76 typedef struct
77 {
78 	DWORD		PhysAddr;
79 	DWORD		dwSize;
80 }	DUCKENTRY, * PDUCKENTRY;
81 
82 
83 //
84 // The CDaffyDuck class keeps a parallel array of MAPPING structures
85 // that corresponds to the DUCKENTRY array.  You can't just pack everything
86 // into one struct since the DSP reads the DUCKENTRY structs and wouldn't
87 // know what to do with the other fields.
88 //
89 typedef struct
90 {
91 	DWORD			dwNumEntries;	// How many slots in the array are used
92 										// = 1 for an audio mapping
93 										// = 2 for an audio mapping + double zero
94 	DWORD			dwTag;			// Unique ID for this mapping
95 	ULONGLONG	ullEndPos;		// The cumulative 64-bit end position for this mapping
96 										// = (previous ullEndPos) + (# of bytes mapped)
97 }	MAPPING;
98 
99 
100 class CDspCommObject;
101 
102 class CDaffyDuck
103 {
104 public:
105 
106 	//
107 	// Number of entries in the circular buffer.
108 	//
109 	// If MAX_ENTRIES is set too high, SONAR crashes in Windows XP if you are
110 	// using super-interleave mode.  64 seems to work.
111 	//
112 	enum
113 	{
114 		MAX_ENTRIES = 64
115 	};
116 
117 	//
118 	//	Construction/destruction
119 	//
120 	CDaffyDuck
121 	(
122 		PCOsSupport 	pOsSupport,
123 		CDspCommObject *pDspCommObject,
124 		WORD				wPipeIndex
125 	);
126 
127 	~CDaffyDuck();
128 
129 protected:
130 
131 	WORD			m_wPipeIndex;
132 
133 	DUCKENTRY	*m_DuckEntries;			// Points to a locked physical page (4096 bytes)
134 													// These are for the benefit of the DSP
135 	MAPPING		m_Mappings[MAX_ENTRIES];// Parallel circular buffer to m_DuckEntries;
136 													// these are for the benefit of port class
137 
138 	DWORD			m_dwHead;					// Index for most recently adding mapping
139 	DWORD			m_dwTail;					// Next mapping to discard (read index)
140 	DWORD			m_dwCount;					// Number of entries in the circular buffer
141 
142 	DWORD			m_dwDuckEntriesPhys;		// The DSP needs this - physical address
143 													// of page pointed to by m_DuckEntries
144 
145 	ULONGLONG	m_ullLastEndPos;
146 
147 	PCOsSupport	m_pOsSupport;
148 
149 	CDspCommObject *m_pDspCommObject;
150 
151 	BOOL			m_fWrapped;
152 
153 #ifdef INTEGRITY_CHECK
154 	void CheckIntegrity();
155 #endif
156 
157 	ECHOSTATUS GetTail
158 	(
159 		DUCKENTRY	*pDuckEntry,
160 		MAPPING		*pMapping
161 	);
162 
163 public:
164 
165 	//
166 	// InitCheck should be called after constructing the CDaffyDuck; this
167 	// is needed because you can't use exceptions in the Windows kernel.
168 	//
169 	ECHOSTATUS InitCheck();
170 
171 	void Reset();
172 
173 	void ResetStartPos();
174 
175 	//
176 	// Call AddMapping to add a buffer of audio data to the scatter-gather list.
177 	// Note that dwPhysAddr will be asserted on the PCI bus; you will need
178 	// to make the appropriate translation between the virtual address of
179 	// the page and the bus address *before* calling this function.
180 	//
181 	// The buffer must be physically contiguous.
182 	//
183 	// The dwTag parameter is a unique ID for this mapping that is used by
184 	// ReleaseUsedMapping and RevokeMappings; if you are building a circular
185 	// buffer, the tag isn't important.
186 	//
187 	// dwInterrupt is true if you want the DSP to generate an IRQ after it
188 	// consumes this audio buffer.
189 	//
190 	// dwNumFreeEntries is useful if you are calling this in a loop and
191 	// want to know when to stop;
192 	//
193 	ECHOSTATUS AddMapping
194 	(
195 		DWORD			dwPhysAddr,
196 		DWORD			dwBytes,
197 		DWORD			dwTag,					// Unique ID for this mapping
198 		DWORD			dwInterrupt,			// Set TRUE if you want an IRQ after this mapping
199 		DWORD			&dwNumFreeEntries		// Return value - number of slots left in the list
200 	);
201 
202 	//
203 	// AddDoubleZero is used to have the DSP generate an interrupt;
204 	// calling AddDoubleZero will cause the DSP to interrupt after it finishes the
205 	// previous duck entry.
206 	//
207 	void AddDoubleZero();
208 
209 	//
210 	// Call Wrap if you are creating a circular DMA buffer; to make a circular
211 	// double buffer, do this:
212 	//
213 	//	AddMapping() 		Several times
214 	// AddDoubleZero()	First half-buffer interrupt
215 	// AddMapping()		Several more times
216 	// AddDoubleZero()	Second half-buffer interrupt
217 	// Wrap()				Wraps the scatter list around to make a circular buffer
218 	//
219 	// Once you call Wrap, you shouldn't add any more mappings.
220 	//
221 	void Wrap();
222 
223 	//
224 	// Call ReleaseUsedMapping to conditionally remove the oldest duck entry.
225 	// ReleaseUsedMapping looks at the DMA position you pass in; if the DMA position
226 	// is past the end of the oldest mapping, the oldest mapping is removed
227 	// from the list and the tag number is returned in the dwTag parameter.
228 	//
229 	ECHOSTATUS ReleaseUsedMapping
230 	(
231 		ULONGLONG	ullDmaPos,
232 		DWORD			&dwTag
233 	);
234 
235 	//
236 	// This returns the physical address of the start of the scatter-gather
237 	// list; used to tell the DSP where to start looking for duck entries.
238 	//
239 	DWORD GetPhysStartAddr()
240 	{
241 		return m_dwDuckEntriesPhys + (m_dwTail * sizeof(DUCKENTRY));
242 	}
243 
244 	//
245 	// Any more room in the s.g. list?
246 	//
247 	DWORD	GetNumFreeEntries()
248 	{
249 		return MAX_ENTRIES - m_dwCount;
250 	}
251 
252 	//
253 	// Used to reset the end pos for rebuilding the duck; this
254 	// is used by the WDM driver to handle revoking.
255 	//
256 	void SetLastEndPos(ULONGLONG ullPos)
257 	{
258 		m_ullLastEndPos = ullPos;
259 	}
260 
261 	//
262 	// Returns the 64 bit DMA position of the start of the oldest entry
263 	//
264 	ULONGLONG GetStartPos()
265 	{
266 		return m_Mappings[ m_dwTail ].ullEndPos -
267 					(ULONGLONG) (m_DuckEntries[ m_dwTail ].dwSize);
268 	}
269 
270 	//
271 	// RevokeMappings is here specifically to support WDM; it removes
272 	// any entries from the list if their tag is >= dwFirstTag and <= dwLastTag.
273 	//
274 	DWORD RevokeMappings
275 	(
276 		DWORD dwFirstTag,
277 		DWORD dwLastTag
278 	);
279 
280 	//
281 	// Returns TRUE if Wrap has been called for this duck
282 	//
283 	BOOL Wrapped()
284 	{
285 		return m_fWrapped;
286 	}
287 
288 
289 	//
290 	//	Overload new & delete to make sure these objects are allocated from
291 	// non-paged memory.
292 	//
293 	PVOID operator new( size_t Size );
294 	VOID  operator delete( PVOID pVoid );
295 
296 };		// class CDaffyDuck
297 
298 typedef CDaffyDuck * PCDaffyDuck;
299 
300 #endif // _DAFFYDUCKOBJECT_
301 
302 // *** CDaffyDuck.H ***
303