1626bc4beSJérôme Duval// ****************************************************************************
2626bc4beSJérôme Duval//
3626bc4beSJérôme Duval//		CDaffyDuck.CPP
4626bc4beSJérôme Duval//
5626bc4beSJérôme Duval//		Implementation file for the CDaffyDuck class.
6626bc4beSJérôme Duval//		Set editor tabs to 3 for your viewing pleasure.
7626bc4beSJérôme Duval//
8626bc4beSJérôme Duval// This file is part of Echo Digital Audio's generic driver library.
9626bc4beSJérôme Duval// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
10626bc4beSJérôme Duval// All rights reserved
11626bc4beSJérôme Duval// www.echoaudio.com
12626bc4beSJérôme Duval//
13626bc4beSJérôme Duval// This library is free software; you can redistribute it and/or
14626bc4beSJérôme Duval// modify it under the terms of the GNU Lesser General Public
15626bc4beSJérôme Duval// License as published by the Free Software Foundation; either
16626bc4beSJérôme Duval// version 2.1 of the License, or (at your option) any later version.
17626bc4beSJérôme Duval//
18626bc4beSJérôme Duval// This library is distributed in the hope that it will be useful,
19626bc4beSJérôme Duval// but WITHOUT ANY WARRANTY; without even the implied warranty of
21626bc4beSJérôme Duval// Lesser General Public License for more details.
22626bc4beSJérôme Duval//
23626bc4beSJérôme Duval// You should have received a copy of the GNU Lesser General Public
24626bc4beSJérôme Duval// License along with this library; if not, write to the Free Software
25626bc4beSJérôme Duval// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26626bc4beSJérôme Duval//
27626bc4beSJérôme Duval//---------------------------------------------------------------------------
28626bc4beSJérôme Duval//
29626bc4beSJérôme Duval// The head pointer tracks the next free slot in the circular buffers
30626bc4beSJérôme Duval// The tail pointer tracks the oldest mapping.
31626bc4beSJérôme Duval//
32626bc4beSJérôme Duval// Fixme add integrity checks for all functions
33626bc4beSJérôme Duval//
34626bc4beSJérôme Duval//****************************************************************************
35626bc4beSJérôme Duval
36626bc4beSJérôme Duval#include "CEchoGals.h"
37626bc4beSJérôme Duval
38626bc4beSJérôme Duval/****************************************************************************
39626bc4beSJérôme Duval
40626bc4beSJérôme Duval	Construction/destruction
41626bc4beSJérôme Duval
42626bc4beSJérôme Duval ****************************************************************************/
43626bc4beSJérôme Duval
44626bc4beSJérôme Duval//===========================================================================
45626bc4beSJérôme Duval//
46626bc4beSJérôme Duval// Overload new & delete so memory for this object is allocated
47626bc4beSJérôme Duval//	from non-paged memory.
48626bc4beSJérôme Duval//
49626bc4beSJérôme Duval//===========================================================================
50626bc4beSJérôme Duval
51626bc4beSJérôme DuvalPVOID CDaffyDuck::operator new( size_t Size )
52626bc4beSJérôme Duval{
53626bc4beSJérôme Duval	PVOID 		pMemory;
54626bc4beSJérôme Duval	ECHOSTATUS 	Status;
55626bc4beSJérôme Duval
56626bc4beSJérôme Duval	Status = OsAllocateNonPaged(Size,&pMemory);
57626bc4beSJérôme Duval
58626bc4beSJérôme Duval	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
59626bc4beSJérôme Duval	{
60626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CDaffyDuck::operator new - memory allocation failed\n"));
61626bc4beSJérôme Duval
62626bc4beSJérôme Duval		pMemory = NULL;
63626bc4beSJérôme Duval	}
64626bc4beSJérôme Duval	else
65626bc4beSJérôme Duval	{
66626bc4beSJérôme Duval		memset( pMemory, 0, Size );
67626bc4beSJérôme Duval	}
68626bc4beSJérôme Duval
69626bc4beSJérôme Duval	return pMemory;
70626bc4beSJérôme Duval
71626bc4beSJérôme Duval}	// PVOID CDaffyDuck::operator new( size_t Size )
72626bc4beSJérôme Duval
73626bc4beSJérôme Duval
74626bc4beSJérôme DuvalVOID  CDaffyDuck::operator delete( PVOID pVoid )
75626bc4beSJérôme Duval{
76626bc4beSJérôme Duval
77626bc4beSJérôme Duval	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
78626bc4beSJérôme Duval	{
79626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CDaffyDuck::operator delete memory free failed\n"));
80626bc4beSJérôme Duval	}
81626bc4beSJérôme Duval
82626bc4beSJérôme Duval}	// VOID  CDaffyDuck::operator delete( PVOID pVoid )
83626bc4beSJérôme Duval
84626bc4beSJérôme Duval
85626bc4beSJérôme Duval//===========================================================================
86626bc4beSJérôme Duval//
87626bc4beSJérôme Duval// Constructor
88626bc4beSJérôme Duval//
89626bc4beSJérôme Duval//===========================================================================
90626bc4beSJérôme Duval
91626bc4beSJérôme DuvalCDaffyDuck::CDaffyDuck
92626bc4beSJérôme Duval(
93626bc4beSJérôme Duval	PCOsSupport 	pOsSupport
94626bc4beSJérôme Duval)
95626bc4beSJérôme Duval{
96626bc4beSJérôme Duval	//
97626bc4beSJérôme Duval	//	Stash stuff
98626bc4beSJérôme Duval	//
99626bc4beSJérôme Duval	m_pOsSupport = pOsSupport;
100626bc4beSJérôme Duval
101626bc4beSJérôme Duval}	// CDaffyDuck::CDaffyDuck()
102626bc4beSJérôme Duval
103626bc4beSJérôme Duval
104626bc4beSJérôme Duval//===========================================================================
105626bc4beSJérôme Duval//
106626bc4beSJérôme Duval// Destructor
107626bc4beSJérôme Duval//
108626bc4beSJérôme Duval//===========================================================================
109626bc4beSJérôme Duval
110626bc4beSJérôme DuvalCDaffyDuck::~CDaffyDuck()
111626bc4beSJérôme Duval{
112626bc4beSJérôme Duval
113be188ae1SJérôme Duval	if (NULL != m_pDuckPage)
114c2d81050SJérôme Duval		m_pOsSupport->FreePhysPageBlock( PAGE_SIZE, m_pDuckPage);
115626bc4beSJérôme Duval
116626bc4beSJérôme Duval}	// CDaffyDuck::~CDaffyDuck()
117626bc4beSJérôme Duval
118626bc4beSJérôme Duval
119626bc4beSJérôme Duval
120626bc4beSJérôme Duval
121626bc4beSJérôme Duval/****************************************************************************
122626bc4beSJérôme Duval
123626bc4beSJérôme Duval	Setup and initialization
124626bc4beSJérôme Duval
125626bc4beSJérôme Duval ****************************************************************************/
126626bc4beSJérôme Duval
127626bc4beSJérôme Duval//===========================================================================
128626bc4beSJérôme Duval//
129626bc4beSJérôme Duval// Reset - resets the mapping and duck entry circular buffers
130626bc4beSJérôme Duval//
131626bc4beSJérôme Duval//===========================================================================
132626bc4beSJérôme Duval
133626bc4beSJérôme Duvalvoid CDaffyDuck::Reset()
134626bc4beSJérôme Duval{
135626bc4beSJérôme Duval	//
136626bc4beSJérôme Duval	//	Zero stuff
137626bc4beSJérôme Duval	//
138626bc4beSJérôme Duval	OsZeroMemory(m_Mappings,sizeof(m_Mappings));
139626bc4beSJérôme Duval
140626bc4beSJérôme Duval	m_dwHead = 0;
141626bc4beSJérôme Duval	m_dwTail = 0;
142626bc4beSJérôme Duval	m_dwCount = 0;
143626bc4beSJérôme Duval	m_ullLastEndPos = 0;
144626bc4beSJérôme Duval
145626bc4beSJérôme Duval	//
146626bc4beSJérôme Duval	// Set all duck entries to "end of list" except for the last one
147626bc4beSJérôme Duval	//
148626bc4beSJérôme Duval	DWORD i;
149626bc4beSJérôme Duval
150626bc4beSJérôme Duval	for (i = 0; i < MAX_ENTRIES; i++)
151626bc4beSJérôme Duval	{
152626bc4beSJérôme Duval		m_DuckEntries[i].PhysAddr = 0;
153626bc4beSJérôme Duval		m_DuckEntries[i].dwSize = 0xffffffff;
154626bc4beSJérôme Duval	}
155626bc4beSJérôme Duval
156626bc4beSJérôme Duval	//
157626bc4beSJérôme Duval	// Put the physical address of the duck at the end of
158626bc4beSJérôme Duval	// the m_DuckEntries array so the DSP will wrap around
159626bc4beSJérôme Duval	// to the start of the duck.
160626bc4beSJérôme Duval	//
161626bc4beSJérôme Duval
162626bc4beSJérôme Duval	m_DuckEntries[MAX_ENTRIES].PhysAddr = SWAP( m_dwDuckEntriesPhys );
163626bc4beSJérôme Duval	m_DuckEntries[MAX_ENTRIES].dwSize = 0;
164626bc4beSJérôme Duval
165626bc4beSJérôme Duval}	// Reset
166626bc4beSJérôme Duval
167626bc4beSJérôme Duval
168626bc4beSJérôme Duval//===========================================================================
169626bc4beSJérôme Duval//
170626bc4beSJérôme Duval// ResetStartPos - Takes the current list and re-calculates the
171626bc4beSJérôme Duval// DMA end position for each mapping, starting at DMA position zero.
172626bc4beSJérôme Duval//
173626bc4beSJérôme Duval//===========================================================================
174626bc4beSJérôme Duval
175626bc4beSJérôme Duvalvoid CDaffyDuck::ResetStartPos()
176626bc4beSJérôme Duval{
177626bc4beSJérôme Duval	DWORD dwRemaining,dwIndex;
178626bc4beSJérôme Duval
179626bc4beSJérôme Duval	m_ullLastEndPos = 0L;
180626bc4beSJérôme Duval
181626bc4beSJérôme Duval	//
182626bc4beSJérôme Duval	// Re-calculate the end positions
183626bc4beSJérôme Duval	//
184626bc4beSJérôme Duval	dwRemaining = m_dwCount;
185626bc4beSJérôme Duval	dwIndex = m_dwTail;
186626bc4beSJérôme Duval	while (0 != dwRemaining)
187626bc4beSJérôme Duval	{
188626bc4beSJérôme Duval		if (	( 0 != m_DuckEntries[ dwIndex ].dwSize) &&
189626bc4beSJérôme Duval				( 0 != m_DuckEntries[ dwIndex ].PhysAddr ) )
190626bc4beSJérôme Duval		{
191626bc4beSJérôme Duval			m_Mappings[dwIndex].ullEndPos =
192626bc4beSJérôme Duval				m_ullLastEndPos + SWAP( m_DuckEntries[ dwIndex ].dwSize );
193626bc4beSJérôme Duval
194626bc4beSJérôme Duval			m_ullLastEndPos = m_Mappings[ dwIndex ].ullEndPos;
195626bc4beSJérôme Duval		}
196626bc4beSJérôme Duval		else
197626bc4beSJérôme Duval		{
198626bc4beSJérôme Duval			m_Mappings[dwIndex].ullEndPos = m_ullLastEndPos;
199626bc4beSJérôme Duval		}
200626bc4beSJérôme Duval
201626bc4beSJérôme Duval		dwIndex++;
202626bc4beSJérôme Duval		dwIndex &= ENTRY_INDEX_MASK;
203626bc4beSJérôme Duval
204626bc4beSJérôme Duval		dwRemaining--;
205626bc4beSJérôme Duval	}
206626bc4beSJérôme Duval
207626bc4beSJérôme Duval}	// ResetStartPos
208626bc4beSJérôme Duval
209626bc4beSJérôme Duval
210626bc4beSJérôme Duval
211626bc4beSJérôme Duval/****************************************************************************
212626bc4beSJérôme Duval
213626bc4beSJérôme Duval	Mapping management
214626bc4beSJérôme Duval
215626bc4beSJérôme Duval ****************************************************************************/
216626bc4beSJérôme Duval
217626bc4beSJérôme Duval//===========================================================================
218626bc4beSJérôme Duval//
219626bc4beSJérôme Duval// AddMapping
220626bc4beSJérôme Duval//
221626bc4beSJérôme Duval// Take a mapping and add it to the circular buffer.
222626bc4beSJérôme Duval//
223626bc4beSJérôme Duval// Note that the m_DuckEntries array is read by the DSP; entries must
224626bc4beSJérôme Duval// therefore be stored in little-endian format.
225626bc4beSJérôme Duval//
226626bc4beSJérôme Duval// The buffer pointed to by dwPhysAddr and dwBytes must be
227626bc4beSJérôme Duval// physically contiguous.
228626bc4beSJérôme Duval//
229626bc4beSJérôme Duval//===========================================================================
230626bc4beSJérôme Duval
231626bc4beSJérôme DuvalECHOSTATUS CDaffyDuck::AddMapping
232626bc4beSJérôme Duval(
233626bc4beSJérôme Duval	DWORD			dwPhysAddr,
234626bc4beSJérôme Duval	DWORD			dwBytes,
235626bc4beSJérôme Duval	NUINT 		Tag,
236626bc4beSJérôme Duval	DWORD			dwInterrupt,
237626bc4beSJérôme Duval	DWORD			&dwNumFreeEntries
238626bc4beSJérôme Duval)
239626bc4beSJérôme Duval{
240626bc4beSJérôme Duval#ifdef INTEGRITY_CHECK
241626bc4beSJérôme Duval	CheckIntegrity();
242626bc4beSJérôme Duval#endif
243626bc4beSJérôme Duval
244626bc4beSJérôme Duval	//
245626bc4beSJérôme Duval	// There must always be at least one free entry for the "end of list"
246626bc4beSJérôme Duval	// entry.  dwInterrupt may be non-zero, so make sure that there's enough
247626bc4beSJérôme Duval	// room for two more entries
248626bc4beSJérôme Duval	//
249626bc4beSJérôme Duval	if ((MAX_ENTRIES - m_dwCount) < 3)
250626bc4beSJérôme Duval	{
251626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("AddMapping - duck is full\n"));
252626bc4beSJérôme Duval		return ECHOSTATUS_DUCK_FULL;
253626bc4beSJérôme Duval	}
254626bc4beSJérôme Duval
255626bc4beSJérôme Duval	//
256626bc4beSJérôme Duval	//	At least two slots are available in the circular
257626bc4beSJérôme Duval	// buffer, so it's OK to add either a regular mapping or
258626bc4beSJérôme Duval	// a mapping with a double zero
259626bc4beSJérôme Duval	//
260626bc4beSJérôme Duval	m_DuckEntries[m_dwHead].PhysAddr = SWAP( dwPhysAddr );
261626bc4beSJérôme Duval	m_DuckEntries[m_dwHead].dwSize 	= SWAP( dwBytes );
262626bc4beSJérôme Duval
263626bc4beSJérôme Duval	m_Mappings[m_dwHead].Tag			= Tag;
264626bc4beSJérôme Duval	m_Mappings[m_dwHead].ullEndPos	= m_ullLastEndPos + dwBytes;
265626bc4beSJérôme Duval
266626bc4beSJérôme Duval	m_ullLastEndPos = m_Mappings[m_dwHead].ullEndPos;
267626bc4beSJérôme Duval
268626bc4beSJérôme Duval	//
269626bc4beSJérôme Duval	// If the caller wants an interrupt after this mapping, then
270626bc4beSJérôme Duval	// dwInterrupt will be non-zero
271626bc4beSJérôme Duval	//
272626bc4beSJérôme Duval	if (dwInterrupt)
273626bc4beSJérôme Duval	{
274626bc4beSJérôme Duval		DWORD dwNext;
275626bc4beSJérôme Duval
276626bc4beSJérôme Duval		//
277626bc4beSJérôme Duval		// Put in the double zero so the DSP will
278626bc4beSJérôme Duval		// generate an interrupt
279626bc4beSJérôme Duval		//
280626bc4beSJérôme Duval		dwNext = m_dwHead + 1;
281626bc4beSJérôme Duval		dwNext &= ENTRY_INDEX_MASK;
282626bc4beSJérôme Duval
283626bc4beSJérôme Duval		m_DuckEntries[dwNext].PhysAddr 	= 0;	// no need to swap zero!
284626bc4beSJérôme Duval		m_DuckEntries[dwNext].dwSize 		= 0;
285626bc4beSJérôme Duval
286626bc4beSJérôme Duval		m_Mappings[dwNext].ullEndPos = m_ullLastEndPos;
287626bc4beSJérôme Duval
288626bc4beSJérôme Duval		m_dwHead += 2;
289626bc4beSJérôme Duval		m_dwCount += 2;
290626bc4beSJérôme Duval	}
291626bc4beSJérôme Duval	else
292626bc4beSJérôme Duval	{
293626bc4beSJérôme Duval		m_dwHead++;
294626bc4beSJérôme Duval		m_dwCount++;
295626bc4beSJérôme Duval	}
296626bc4beSJérôme Duval
297626bc4beSJérôme Duval	//
298626bc4beSJérôme Duval	// Wrap the head index
299626bc4beSJérôme Duval	//
300626bc4beSJérôme Duval	m_dwHead &=	ENTRY_INDEX_MASK;
301626bc4beSJérôme Duval
302626bc4beSJérôme Duval	//
303626bc4beSJérôme Duval	// Return value to the caller
304626bc4beSJérôme Duval	//
305626bc4beSJérôme Duval	dwNumFreeEntries = MAX_ENTRIES - m_dwCount;
306626bc4beSJérôme Duval
307626bc4beSJérôme Duval//#ifdef _DEBUG
308626bc4beSJérôme Duval#if 0
309626bc4beSJérôme Duval	DWORD hi,lo;
310626bc4beSJérôme Duval
311626bc4beSJérôme Duval	hi = (DWORD) (m_ullLastEndPos >> 32);
312626bc4beSJérôme Duval	lo = (DWORD) (m_ullLastEndPos & 0xffffffffL);
313626bc4beSJérôme Duval
314626bc4beSJérôme Duval	ECHO_DEBUGPRINTF(("Added tag %ld, end pos 0x%08lx%08lx (int %ld)\n",Tag,hi,lo,dwInterrupt));
315626bc4beSJérôme Duval
316626bc4beSJérôme Duval#ifdef INTEGRITY_CHECK
317626bc4beSJérôme Duval	CheckIntegrity();
318626bc4beSJérôme Duval#endif
319626bc4beSJérôme Duval
320626bc4beSJérôme Duval	ECHO_DEBUGPRINTF(("Daffy duck count is %ld\n",m_dwCount));
321626bc4beSJérôme Duval
322626bc4beSJérôme Duval#endif
323626bc4beSJérôme Duval
324626bc4beSJérôme Duval	return ECHOSTATUS_OK;
325626bc4beSJérôme Duval
326626bc4beSJérôme Duval}	// AddMapping
327626bc4beSJérôme Duval
328626bc4beSJérôme Duval
329626bc4beSJérôme Duval//===========================================================================
330626bc4beSJérôme Duval//
331626bc4beSJérôme Duval// AddDoubleZero
332626bc4beSJérôme Duval//
333626bc4beSJérôme Duval// Adds a double zero to the circular buffer to cause the DSP to generate an
334626bc4beSJérôme Duval// IRQ.
335626bc4beSJérôme Duval//
336626bc4beSJérôme Duval//===========================================================================
337626bc4beSJérôme Duval
338626bc4beSJérôme DuvalECHOSTATUS CDaffyDuck::AddDoubleZero()
339626bc4beSJérôme Duval{
340626bc4beSJérôme Duval	//
341626bc4beSJérôme Duval	// There must always be at least one free entry for the "end of list"
342626bc4beSJérôme Duval	// entry.
343626bc4beSJérôme Duval	//
344626bc4beSJérôme Duval	if ((MAX_ENTRIES - m_dwCount) < 2)
345626bc4beSJérôme Duval	{
346626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("AddDoubleZero - duck is full\n"));
347626bc4beSJérôme Duval		return ECHOSTATUS_DUCK_FULL;
348626bc4beSJérôme Duval	}
349626bc4beSJérôme Duval
350626bc4beSJérôme Duval	//ECHO_DEBUGPRINTF(("CDaffyDuck::AddDoubleZero  m_dwCount %ld\n",m_dwCount));
351626bc4beSJérôme Duval
352626bc4beSJérôme Duval	//
353626bc4beSJérôme Duval	// Add the double zero
354626bc4beSJérôme Duval	//
355626bc4beSJérôme Duval	m_DuckEntries[m_dwHead].PhysAddr 	= 0;
356626bc4beSJérôme Duval	m_DuckEntries[m_dwHead].dwSize 		= 0;
357626bc4beSJérôme Duval	m_Mappings[m_dwHead].ullEndPos		= m_ullLastEndPos;
358626bc4beSJérôme Duval
359626bc4beSJérôme Duval	//
360626bc4beSJérôme Duval	// Housekeeping
361626bc4beSJérôme Duval	//
362626bc4beSJérôme Duval	m_dwHead++;
363626bc4beSJérôme Duval	m_dwHead &=	ENTRY_INDEX_MASK;
364626bc4beSJérôme Duval
365626bc4beSJérôme Duval	m_dwCount++;
366626bc4beSJérôme Duval
367626bc4beSJérôme Duval	return ECHOSTATUS_OK;
368626bc4beSJérôme Duval
369626bc4beSJérôme Duval}	// AddDoubleZero
370626bc4beSJérôme Duval
371626bc4beSJérôme Duval
372626bc4beSJérôme Duval//===========================================================================
373626bc4beSJérôme Duval//
374626bc4beSJérôme Duval//	Wrap
375626bc4beSJérôme Duval//
376626bc4beSJérôme Duval// Put a "next PLE" pointer at the end of the duck to make the DSP
377626bc4beSJérôme Duval// wrap around to the start; this creates a circular buffer.
378626bc4beSJérôme Duval//
379626bc4beSJérôme Duval//===========================================================================
380626bc4beSJérôme Duval
381626bc4beSJérôme Duvalvoid CDaffyDuck::Wrap()
382626bc4beSJérôme Duval{
3834dd9e436SJérôme Duval	ECHO_ASSERT(m_dwCount != MAX_ENTRIES);
384626bc4beSJérôme Duval
385626bc4beSJérôme Duval	//
386626bc4beSJérôme Duval	// Put in the address of the start of the duck entries
387626bc4beSJérôme Duval	// and a count of zero; a count of zero tells the DSP
388626bc4beSJérôme Duval	// "Go look again for a duck entry at this address"
389626bc4beSJérôme Duval	//
390626bc4beSJérôme Duval	m_DuckEntries[m_dwHead].PhysAddr		= SWAP( m_dwDuckEntriesPhys );
391626bc4beSJérôme Duval	m_DuckEntries[m_dwHead].dwSize		= 0;
392626bc4beSJérôme Duval
393626bc4beSJérôme Duval	m_dwHead++;
394626bc4beSJérôme Duval	m_dwHead &= ENTRY_INDEX_MASK;
395626bc4beSJérôme Duval
396626bc4beSJérôme Duval	m_dwCount++;
397626bc4beSJérôme Duval
398626bc4beSJérôme Duval	m_fWrapped = TRUE;
399626bc4beSJérôme Duval
400626bc4beSJérôme Duval}	// Wrap
401626bc4beSJérôme Duval
402626bc4beSJérôme Duval
403626bc4beSJérôme Duval
404626bc4beSJérôme Duval//===========================================================================
405626bc4beSJérôme Duval//
406626bc4beSJérôme Duval// ReleaseUsedMappings
407626bc4beSJérôme Duval//
408626bc4beSJérôme Duval// Find all the mapping that've been consumed and return a list of tags
409626bc4beSJérôme Duval//
410626bc4beSJérôme Duval// Return value is the number of tags written to the array
411626bc4beSJérôme Duval//
412626bc4beSJérôme Duval//===========================================================================
413626bc4beSJérôme Duval
414626bc4beSJérôme DuvalDWORD CDaffyDuck::ReleaseUsedMappings
415626bc4beSJérôme Duval(
416626bc4beSJérôme Duval	ULONGLONG 	ullDmaPos,
417626bc4beSJérôme Duval	NUINT 		*Tags,		// an array of tags
418626bc4beSJérôme Duval	DWORD			dwMaxTags	// the max number of tags in the array
419626bc4beSJérôme Duval)
420626bc4beSJérôme Duval{
421626bc4beSJérôme Duval	DWORD dwTempAddr,dwTempSize;
422626bc4beSJérôme Duval	NUINT Tag;
423626bc4beSJérôme Duval	DWORD dwTagsFree;
424626bc4beSJérôme Duval
425626bc4beSJérôme Duval	dwTagsFree = dwMaxTags;
426626bc4beSJérôme Duval	while ( (0 != m_dwCount) && (0 != dwTagsFree) )
427626bc4beSJérôme Duval	{
428626bc4beSJérôme Duval		//
429626bc4beSJérôme Duval		// Get the data from the tail
430626bc4beSJérôme Duval		//
431626bc4beSJérôme Duval		Tag = m_Mappings[m_dwTail].Tag;
432626bc4beSJérôme Duval		dwTempAddr = SWAP( m_DuckEntries[m_dwTail].PhysAddr );
433626bc4beSJérôme Duval		dwTempSize = SWAP( m_DuckEntries[m_dwTail].dwSize );
434626bc4beSJérôme Duval
435626bc4beSJérôme Duval		//
436626bc4beSJérôme Duval		// Is this an audio data mapping?
437626bc4beSJérôme Duval		//
438626bc4beSJérôme Duval		if ( (0 != dwTempAddr) && (0 != dwTempSize) )
439626bc4beSJérôme Duval		{
440626bc4beSJérôme Duval			//
441626bc4beSJérôme Duval			// Is this audio data mapping done?
442626bc4beSJérôme Duval			//
443626bc4beSJérôme Duval			if ( ullDmaPos < m_Mappings[m_dwTail].ullEndPos )
444626bc4beSJérôme Duval				break;
445626bc4beSJérôme Duval
446626bc4beSJérôme Duval			//
447626bc4beSJérôme Duval			// This one's done
448626bc4beSJérôme Duval			//
449626bc4beSJérôme Duval			*Tags = Tag;
450626bc4beSJérôme Duval			Tags++;
451626bc4beSJérôme Duval			dwTagsFree--;
452626bc4beSJérôme Duval
453626bc4beSJérôme Duval			EjectTail();
454626bc4beSJérôme Duval		}
455626bc4beSJérôme Duval		else
456626bc4beSJérôme Duval		{
457626bc4beSJérôme Duval			//
458626bc4beSJérôme Duval			// Is this non-audio data mapping done?
459626bc4beSJérôme Duval			//
460626bc4beSJérôme Duval			if ( ullDmaPos <= m_Mappings[m_dwTail].ullEndPos )
461626bc4beSJérôme Duval				break;
462626bc4beSJérôme Duval
463626bc4beSJérôme Duval			//
464626bc4beSJérôme Duval			// Pop it
465626bc4beSJérôme Duval			//
466626bc4beSJérôme Duval			EjectTail();
467626bc4beSJérôme Duval		}
468626bc4beSJérôme Duval	}
469626bc4beSJérôme Duval
470626bc4beSJérôme Duval	//
471626bc4beSJérôme Duval	// Return the number written
472626bc4beSJérôme Duval	//
473626bc4beSJérôme Duval	return dwMaxTags - dwTagsFree;
474626bc4beSJérôme Duval
475626bc4beSJérôme Duval}	// ReleaseUsedMappings
476626bc4beSJérôme Duval
477626bc4beSJérôme Duval
478626bc4beSJérôme Duval//===========================================================================
479626bc4beSJérôme Duval//
480626bc4beSJérôme Duval// RevokeMappings
481626bc4beSJérôme Duval//
482626bc4beSJérôme Duval// Returns the number actually revoked
483626bc4beSJérôme Duval//
484626bc4beSJérôme Duval//===========================================================================
485626bc4beSJérôme Duval
486626bc4beSJérôme DuvalDWORD CDaffyDuck::RevokeMappings(NUINT FirstTag,NUINT LastTag)
487626bc4beSJérôme Duval{
488626bc4beSJérôme Duval	NUINT	Offset;
489626bc4beSJérôme Duval	DWORD	dwNumRevoked;
490626bc4beSJérôme Duval
491626bc4beSJérôme Duval	dwNumRevoked = 0;
492626bc4beSJérôme Duval
493626bc4beSJérôme Duval
494626bc4beSJérôme Duval	//----------------------------------------------------------------------
495626bc4beSJérôme Duval	//
496626bc4beSJérôme Duval	// The tags may be 32 bit counters, so it is possible that they will
497626bc4beSJérôme Duval	// wrap around (that is, dwLastTag may be less than dwFirstTag).  If the
498626bc4beSJérôme Duval	// tags have wrapped, use an offset so the compares work correctly.
499626bc4beSJérôme Duval	//
500626bc4beSJérôme Duval	//----------------------------------------------------------------------
501626bc4beSJérôme Duval
502626bc4beSJérôme Duval	Offset = 0;
503626bc4beSJérôme Duval	if (LastTag < FirstTag)
504626bc4beSJérôme Duval	{
505626bc4beSJérôme Duval		Offset = LastTag;
506626bc4beSJérôme Duval
507626bc4beSJérôme Duval		LastTag -= Offset;
508626bc4beSJérôme Duval		FirstTag -= Offset;
509626bc4beSJérôme Duval	}
510626bc4beSJérôme Duval
511626bc4beSJérôme Duval
512626bc4beSJérôme Duval	//----------------------------------------------------------------------
513626bc4beSJérôme Duval	//
514626bc4beSJérôme Duval	// Go through the list and revoke stuff
515626bc4beSJérôme Duval	//
516626bc4beSJérôme Duval	//----------------------------------------------------------------------
517626bc4beSJérôme Duval
518626bc4beSJérôme Duval	DWORD dwCount;
519626bc4beSJérôme Duval	DWORD dwCurrentIndex;
520626bc4beSJérôme Duval	DWORD dwNextIndex;
521626bc4beSJérôme Duval	NUINT AdjustedTag;
522626bc4beSJérôme Duval
523626bc4beSJérôme Duval	dwCurrentIndex = m_dwTail;
524626bc4beSJérôme Duval	dwCount = m_dwCount;
525626bc4beSJérôme Duval	while (dwCount != 0)
526626bc4beSJérôme Duval	{
527626bc4beSJérôme Duval		//
528626bc4beSJérôme Duval		// Get info for this mapping
529626bc4beSJérôme Duval		//
530626bc4beSJérôme Duval		AdjustedTag = m_Mappings[dwCurrentIndex].Tag - Offset;
531626bc4beSJérôme Duval
532626bc4beSJérôme Duval		//
533626bc4beSJérôme Duval		// Only check this mapping if it contains audio data
534626bc4beSJérôme Duval		//
535626bc4beSJérôme Duval		if (	(0 != m_DuckEntries[dwCurrentIndex].PhysAddr) &&
536626bc4beSJérôme Duval				(0 != m_DuckEntries[dwCurrentIndex].dwSize) )
537626bc4beSJérôme Duval		{
538626bc4beSJérôme Duval			//
539626bc4beSJérôme Duval			// See if the current mapping needs to be revoked
540626bc4beSJérôme Duval			//
541626bc4beSJérôme Duval			if ((FirstTag <= AdjustedTag) &&
542626bc4beSJérôme Duval				 (AdjustedTag <= LastTag))
543626bc4beSJérôme Duval			{
544626bc4beSJérôme Duval				//
545626bc4beSJérôme Duval				// Revoke this tag
546626bc4beSJérôme Duval				//
547626bc4beSJérôme Duval				dwNumRevoked++;
548626bc4beSJérôme Duval
549626bc4beSJérôme Duval				//
550626bc4beSJérôme Duval				// Change this duck into a duck entry pointer; the DSP
551626bc4beSJérôme Duval				// will see that the size is zero and re-fetch the duck entry
552626bc4beSJérôme Duval				// from the address specified in PhysAddr.
553626bc4beSJérôme Duval				//
554626bc4beSJérôme Duval				dwNextIndex = dwCurrentIndex + 1;