xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CDaffyDuck.h (revision be188ae133da3258026dc1f9c1330f0d27e53494)
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 // ----------------------------------------------------------------------------
31 //
32 // This file is part of Echo Digital Audio's generic driver library.
33 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
34 // All rights reserved
35 // www.echoaudio.com
36 //
37 // This library is free software; you can redistribute it and/or
38 // modify it under the terms of the GNU Lesser General Public
39 // License as published by the Free Software Foundation; either
40 // version 2.1 of the License, or (at your option) any later version.
41 //
42 // This library is distributed in the hope that it will be useful,
43 // but WITHOUT ANY WARRANTY; without even the implied warranty of
44 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
45 // Lesser General Public License for more details.
46 //
47 // You should have received a copy of the GNU Lesser General Public
48 // License along with this library; if not, write to the Free Software
49 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
50 //
51 // ****************************************************************************
52 
53 //	Prevent problems with multiple includes
54 
55 #ifndef _DAFFYDUCKOBJECT_
56 #define _DAFFYDUCKOBJECT_
57 
58 #ifdef _DEBUG
59 //#define INTEGRITY_CHECK
60 #endif
61 
62 //
63 // DUCKENTRY is a single entry for the scatter-gather list.  A DUCKENTRY
64 // struct is read by the DSP.
65 //
66 typedef struct
67 {
68 	DWORD		PhysAddr;
69 	DWORD		dwSize;
70 }	DUCKENTRY, * PDUCKENTRY;
71 
72 
73 //
74 // The CDaffyDuck class keeps a parallel array of MAPPING structures
75 // that corresponds to the DUCKENTRY array.  You can't just pack everything
76 // into one struct since the DSP reads the DUCKENTRY structs and wouldn't
77 // know what to do with the other fields.
78 //
79 typedef struct
80 {
81 	NUINT			Tag;				// Unique ID for this mapping
82 	ULONGLONG	ullEndPos;		// The cumulative 64-bit end position for this mapping
83 										// = (previous ullEndPos) + (# of bytes mapped)
84 }	MAPPING;
85 
86 
87 class CDspCommObject;
88 
89 class CDaffyDuck
90 {
91 public:
92 
93 	//
94 	// Number of entries in the circular buffer.
95 	//
96 	// If MAX_ENTRIES is set too high, SONAR crashes in Windows XP if you are
97 	// using super-interleave mode.  64 seems to work.
98 	//
99 	enum
100 	{
101 		MAX_ENTRIES 		= 64,					// Note this must be a power of 2
102 		ENTRY_INDEX_MASK 	= MAX_ENTRIES-1
103 	};
104 
105 	//
106 	//	Destructor
107 	//
108 	~CDaffyDuck();
109 
110 	static CDaffyDuck * MakeDaffyDuck(COsSupport *pOsSupport);
111 
112 protected:
113 
114 	//
115 	// Protected constructor
116 	//
117 	CDaffyDuck(PCOsSupport 	pOsSupport);
118 
119 	DWORD			m_dwPipeIndex;
120 
121 	PPAGE_BLOCK	m_pDuckPage;
122 
123 	DUCKENTRY	*m_DuckEntries;			// Points to a locked physical page (4096 bytes)
124 													// These are for the benefit of the DSP
125 	MAPPING		m_Mappings[MAX_ENTRIES];// Parallel circular buffer to m_DuckEntries;
126 													// these are for the benefit of port class
127 
128 	DWORD			m_dwHead;					// Index where next mapping will be added;
129 													// points to an empty slot
130 	DWORD			m_dwTail;					// Next mapping to discard (read index)
131 	DWORD			m_dwCount;					// Number of entries in the circular buffer
132 
133 	DWORD			m_dwDuckEntriesPhys;		// The DSP needs this - physical address
134 													// of page pointed to by m_DuckEntries
135 
136 	ULONGLONG	m_ullLastEndPos;			// Used to calculate ullEndPos for new entries
137 
138 	PCOsSupport	m_pOsSupport;
139 
140 	BOOL			m_fWrapped;
141 
142 #ifdef INTEGRITY_CHECK
143 	void CheckIntegrity();
144 #endif
145 
146 	void EjectTail();
147 
148 public:
149 
150 	void Reset();
151 
152 	void ResetStartPos();
153 
154 	//
155 	// Call AddMapping to add a buffer of audio data to the scatter-gather list.
156 	// Note that dwPhysAddr will be asserted on the PCI bus; you will need
157 	// to make the appropriate translation between the virtual address of
158 	// the page and the bus address *before* calling this function.
159 	//
160 	// The buffer must be physically contiguous.
161 	//
162 	// The Tag parameter is a unique ID for this mapping that is used by
163 	// ReleaseUsedMapping and RevokeMappings; if you are building a circular
164 	// buffer, the tag isn't important.
165 	//
166 	// dwInterrupt is true if you want the DSP to generate an IRQ after it
167 	// consumes this audio buffer.
168 	//
169 	// dwNumFreeEntries is useful if you are calling this in a loop and
170 	// want to know when to stop;
171 	//
172 	ECHOSTATUS AddMapping
173 	(
174 		DWORD			dwPhysAddr,
175 		DWORD			dwBytes,
176 		NUINT			Tag,						// Unique ID for this mapping
177 		DWORD			dwInterrupt,			// Set TRUE if you want an IRQ after this mapping
178 		DWORD			&dwNumFreeEntries		// Return value - number of slots left in the list
179 	);
180 
181 	//
182 	// AddDoubleZero is used to have the DSP generate an interrupt;
183 	// calling AddDoubleZero will cause the DSP to interrupt after it finishes the
184 	// previous duck entry.
185 	//
186 	ECHOSTATUS AddDoubleZero();
187 
188 	//
189 	// Call Wrap if you are creating a circular DMA buffer; to make a circular
190 	// double buffer, do this:
191 	//
192 	//	AddMapping() 		Several times
193 	// AddDoubleZero()	First half-buffer interrupt
194 	// AddMapping()		Several more times
195 	// AddDoubleZero()	Second half-buffer interrupt
196 	// Wrap()				Wraps the scatter list around to make a circular buffer
197 	//
198 	// Once you call Wrap, you shouldn't add any more mappings.
199 	//
200 	void Wrap();
201 
202 	//
203 	// Call ReleaseUsedMapping to conditionally remove the oldest duck entries.
204 	//
205 	// The return value is the number of tags written to the Tags array.
206 	//
207 	DWORD ReleaseUsedMappings
208 	(
209 		ULONGLONG	ullDmaPos,
210 		NUINT		 	*Tags,
211 		DWORD			dwMaxTags
212 	);
213 
214 	//
215 	// Adjusts the duck so that DMA will start from a given position; useful
216 	// when resuming from pause
217 	//
218 	void AdjustStartPos(ULONGLONG ullPos);
219 
220 	//
221 	// This returns the physical address of the start of the scatter-gather
222 	// list; used to tell the DSP where to start looking for duck entries.
223 	//
224 	DWORD GetPhysStartAddr();
225 
226 	//
227 	// Any more room in the s.g. list?
228 	//
GetNumFreeEntries()229 	DWORD	GetNumFreeEntries()
230 	{
231 		return MAX_ENTRIES - m_dwCount;
232 	}
233 
234 	//
235 	// RevokeMappings is here specifically to support WDM; it removes
236 	// any entries from the list if their tag is >= dwFirstTag and <= dwLastTag.
237 	//
238 	DWORD RevokeMappings
239 	(
240 		NUINT		 FirstTag,
241 		NUINT		 LastTag
242 	);
243 
244 	//
245 	// Returns TRUE if Wrap has been called for this duck
246 	//
Wrapped()247 	BOOL Wrapped()
248 	{
249 		return m_fWrapped;
250 	}
251 
252 	//
253 	// CleanUpTail is used to clean out any non-audio entries from the tail
254 	// of the list that might be left over from earlier
255 	//
256 	void CleanUpTail();
257 
258 	//
259 	// Spew out some info
260 	//
261 	VOID DbgDump();
262 
263 	//
264 	//	Overload new & delete to make sure these objects are allocated from
265 	// non-paged memory.
266 	//
267 	PVOID operator new( size_t Size );
268 	VOID  operator delete( PVOID pVoid );
269 
270 };		// class CDaffyDuck
271 
272 typedef CDaffyDuck * PCDaffyDuck;
273 
274 #endif // _DAFFYDUCKOBJECT_
275 
276 // *** CDaffyDuck.H ***
277