1626bc4beSJérôme Duval// ****************************************************************************
2626bc4beSJérôme Duval//
3626bc4beSJérôme Duval//		CEchoGals.cpp
4626bc4beSJérôme Duval//
5626bc4beSJérôme Duval//		Implementation file for the CEchoGals driver class.
6626bc4beSJérôme Duval//		Set editor tabs to 3 for your viewing pleasure.
7626bc4beSJérôme Duval//
8626bc4beSJérôme Duval// ----------------------------------------------------------------------------
9626bc4beSJérôme Duval//
10626bc4beSJérôme Duval// This file is part of Echo Digital Audio's generic driver library.
11626bc4beSJérôme Duval// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
12626bc4beSJérôme Duval// All rights reserved
13626bc4beSJérôme Duval// www.echoaudio.com
14626bc4beSJérôme Duval//
15626bc4beSJérôme Duval// This library is free software; you can redistribute it and/or
16626bc4beSJérôme Duval// modify it under the terms of the GNU Lesser General Public
17626bc4beSJérôme Duval// License as published by the Free Software Foundation; either
18626bc4beSJérôme Duval// version 2.1 of the License, or (at your option) any later version.
19626bc4beSJérôme Duval//
20626bc4beSJérôme Duval// This library is distributed in the hope that it will be useful,
21626bc4beSJérôme Duval// but WITHOUT ANY WARRANTY; without even the implied warranty of
22626bc4beSJérôme Duval// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23626bc4beSJérôme Duval// Lesser General Public License for more details.
24626bc4beSJérôme Duval//
25626bc4beSJérôme Duval// You should have received a copy of the GNU Lesser General Public
26626bc4beSJérôme Duval// License along with this library; if not, write to the Free Software
27626bc4beSJérôme Duval// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28626bc4beSJérôme Duval//
29626bc4beSJérôme Duval// ****************************************************************************
30626bc4beSJérôme Duval
31626bc4beSJérôme Duval#include "CEchoGals.h"
32626bc4beSJérôme Duval
33626bc4beSJérôme Duval
34626bc4beSJérôme Duval/****************************************************************************
35626bc4beSJérôme Duval
36626bc4beSJérôme Duval	CEchoGals construction and destruction
37626bc4beSJérôme Duval
38626bc4beSJérôme Duval ****************************************************************************/
39626bc4beSJérôme Duval
40626bc4beSJérôme Duval//===========================================================================
41626bc4beSJérôme Duval//
42626bc4beSJérôme Duval// Overload new & delete so memory for this object is allocated
43626bc4beSJérôme Duval//	from non-paged memory.
44626bc4beSJérôme Duval//
45626bc4beSJérôme Duval//===========================================================================
46626bc4beSJérôme Duval
47626bc4beSJérôme DuvalPVOID CEchoGals::operator new( size_t Size )
48626bc4beSJérôme Duval{
49626bc4beSJérôme Duval	PVOID 		pMemory;
50626bc4beSJérôme Duval	ECHOSTATUS 	Status;
51626bc4beSJérôme Duval
52626bc4beSJérôme Duval	Status = OsAllocateNonPaged(Size,&pMemory);
53626bc4beSJérôme Duval
54626bc4beSJérôme Duval	if ( (ECHOSTATUS_OK != Status) || (NULL == pMemory ))
55626bc4beSJérôme Duval	{
56626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CEchoGals::operator new - memory allocation failed\n"));
57626bc4beSJérôme Duval
58626bc4beSJérôme Duval		pMemory = NULL;
59626bc4beSJérôme Duval	}
60626bc4beSJérôme Duval	else
61626bc4beSJérôme Duval	{
62626bc4beSJérôme Duval		memset( pMemory, 0, Size );
63626bc4beSJérôme Duval	}
64626bc4beSJérôme Duval
65626bc4beSJérôme Duval	return pMemory;
66626bc4beSJérôme Duval
67626bc4beSJérôme Duval}	// PVOID CEchoGals::operator new( size_t Size )
68626bc4beSJérôme Duval
69626bc4beSJérôme Duval
70626bc4beSJérôme DuvalVOID  CEchoGals::operator delete( PVOID pVoid )
71626bc4beSJérôme Duval{
72626bc4beSJérôme Duval	if ( ECHOSTATUS_OK != OsFreeNonPaged( pVoid ) )
73626bc4beSJérôme Duval	{
74626bc4beSJérôme Duval		ECHO_DEBUGPRINTF(("CEchoGals::operator delete memory free failed\n"));
75626bc4beSJérôme Duval	}
76626bc4beSJérôme Duval}	// VOID  CEchoGals::operator delete( PVOID pVoid )
77626bc4beSJérôme Duval
78626bc4beSJérôme Duval
79626bc4beSJérôme Duval//===========================================================================
80626bc4beSJérôme Duval//
81626bc4beSJérôme Duval// Constructor
82626bc4beSJérôme Duval//
83626bc4beSJérôme Duval//===========================================================================
84626bc4beSJérôme Duval
85626bc4beSJérôme DuvalCEchoGals::CEchoGals
86626bc4beSJérôme Duval(
87626bc4beSJérôme Duval	PCOsSupport pOsSupport
88626bc4beSJérôme Duval)
89626bc4beSJérôme Duval{
904dd9e436SJérôme Duval	ECHO_ASSERT(pOsSupport );
91626bc4beSJérôme Duval
92626bc4beSJérôme Duval	m_pOsSupport = pOsSupport;		// Ptr to OS Support methods & data
93626bc4beSJérôme Duval
94626bc4beSJérôme Duval	m_wFlags = ECHOGALS_FLAG_BADBOARD;
95626bc4beSJérôme Duval
96626bc4beSJérôme Duval	m_dwLockedSampleRate	= 44100;
97626bc4beSJérôme Duval
98626bc4beSJérôme Duval}	// CEchoGals::CEchoGals()
99626bc4beSJérôme Duval
100626bc4beSJérôme Duval
101626bc4beSJérôme Duval//===========================================================================
102626bc4beSJérôme Duval//
103626bc4beSJérôme Duval// Destructor
104626bc4beSJérôme Duval//
105626bc4beSJérôme Duval//===========================================================================
106626bc4beSJérôme Duval
107626bc4beSJérôme DuvalCEchoGals::~CEchoGals()
108626bc4beSJérôme Duval{
109626bc4beSJérôme Duval	//
110626bc4beSJérôme Duval	// Free stuff
111626bc4beSJérôme Duval	//
112626bc4beSJérôme Duval	delete m_pDspCommObject;	// This powers down the DSP
113626bc4beSJérôme Duval
114626bc4beSJérôme Duval	//
115626bc4beSJérôme Duval	// Clean up the ducks
116626bc4beSJérôme Duval	//
117626bc4beSJérôme Duval	WORD i;
118626bc4beSJérôme Duval
119626bc4beSJérôme Duval	for (i = 0; i < ECHO_MAXAUDIOPIPES; i++)
120626bc4beSJérôme Duval	{
121626bc4beSJérôme Duval		if (NULL != m_DaffyDucks[i])
122626bc4beSJérôme Duval			delete m_DaffyDucks[i];
123626bc4beSJérôme Duval	}
124626bc4beSJérôme Duval
125626bc4beSJérôme Duval	//
126626bc4beSJérôme Duval	//	Clean up the mixer client list
127626bc4beSJérôme Duval	//
128626bc4beSJérôme Duval	while (NULL != m_pMixerClients)
129626bc4beSJérôme Duval	{
130626bc4beSJérôme Duval		ECHO_MIXER_CLIENT *pDeadClient;
131626bc4beSJérôme Duval
132626bc4beSJérôme Duval		pDeadClient = m_pMixerClients;
133626bc4beSJérôme Duval		m_pMixerClients = pDeadClient->pNext;
134626bc4beSJérôme Duval		OsFreeNonPaged(pDeadClient);
135626bc4beSJérôme Duval	}
136626bc4beSJérôme Duval
137626bc4beSJérôme Duval	ECHO_DEBUGPRINTF( ( "CEchoGals::~CEchoGals() is toast!\n" ) );
138626bc4beSJérôme Duval
139626bc4beSJérôme Duval}	// CEchoGals::~CEchoGals()
140626bc4beSJérôme Duval
141626bc4beSJérôme Duval
142626bc4beSJérôme Duval
143626bc4beSJérôme Duval
144626bc4beSJérôme Duval/****************************************************************************
145626bc4beSJérôme Duval
146626bc4beSJérôme Duval	CEchoGals setup and hardware initialization
147626bc4beSJérôme Duval
148626bc4beSJérôme Duval ****************************************************************************/
149626bc4beSJérôme Duval
150626bc4beSJérôme Duval//===========================================================================
151626bc4beSJérôme Duval//
152626bc4beSJérôme Duval// AssignResources does just what you'd expect.
153626bc4beSJérôme Duval//
154626bc4beSJérôme Duval// Note that pvSharedMemory is a logical pointer - that is, the driver
155626bc4beSJérôme Duval// will dereference this pointer to access the memory-mapped regisers on
156626bc4beSJérôme Duval// the DSP.  The caller needs to take the physical address from the PCI
157626bc4beSJérôme Duval// config space and map it.
158626bc4beSJérôme Duval//
159626bc4beSJérôme Duval//===========================================================================
160626bc4beSJérôme Duval
161626bc4beSJérôme DuvalECHOSTATUS CEchoGals::AssignResources
162626bc4beSJérôme Duval(
163626bc4beSJérôme Duval	PVOID		pvSharedMemory,		// Ptr to DSP registers
164626bc4beSJérôme Duval	PCHAR		pszCardName				// Caller gets from registry
165626bc4beSJérôme Duval)
166626bc4beSJérôme Duval{
167626bc4beSJérôme Duval	//
1684dd9e436SJérôme Duval	//	Use ECHO_ASSERT(to be sure this isn't called twice!
169626bc4beSJérôme Duval	//
1704dd9e436SJérôme Duval	ECHO_ASSERT(NULL == m_pvSharedMemory );
171626bc4beSJérôme Duval
172626bc4beSJérôme Duval	//
173626bc4beSJérôme Duval	//	Check and store the parameters
174626bc4beSJérôme Duval	//
1754dd9e436SJérôme Duval	ECHO_ASSERT(pvSharedMemory );
176626bc4beSJérôme Duval	if ( NULL == pszCardName )
177626bc4beSJérôme Duval	{
178626bc4beSJérôme Duval		return( ECHOSTATUS_BAD_CARD_NAME );
179626bc4beSJérôme Duval	}
180626bc4beSJérôme Duval	m_pvSharedMemory = pvSharedMemory;	// Shared memory addr assigned by PNP
181626bc4beSJérôme Duval
182626bc4beSJérôme Duval	//
183626bc4beSJérôme Duval	//	Copy card name & make sure we don't overflow our buffer
184626bc4beSJérôme Duval	//
185626bc4beSJérôme Duval	strncpy( m_szCardInstallName, pszCardName, ECHO_MAXNAMELEN-1 );
186626bc4beSJérôme Duval	m_szCardInstallName[ ECHO_MAXNAMELEN-1 ] = 0;
187626bc4beSJérôme Duval
188626bc4beSJérôme Duval	return ECHOSTATUS_OK;
189626bc4beSJérôme Duval
190626bc4beSJérôme Duval}	// ECHOSTATUS CEchoGals::AssignResources
191626bc4beSJérôme Duval
192626bc4beSJérôme Duval
193626bc4beSJérôme Duval//===========================================================================
194626bc4beSJérôme Duval//
195626bc4beSJérôme Duval// InitHw is device-specific and so does nothing here; it is overridden
196626bc4beSJérôme Duval// in the derived classes.
197626bc4beSJérôme Duval//
198626bc4beSJérôme Duval//	The correct sequence is:
199626bc4beSJérôme Duval//
200626bc4beSJérôme Duval//	Construct the appropriate CEchoGals-derived object for the card
201626bc4beSJérôme Duval// Call AssignResources
202626bc4beSJérôme Duval// Call InitHw
203626bc4beSJérôme Duval//
204626bc4beSJérôme Duval//===========================================================================
205626bc4beSJérôme Duval
206626bc4beSJérôme DuvalECHOSTATUS CEchoGals::InitHw()
207626bc4beSJérôme Duval{
208626bc4beSJérôme Duval	//
2094dd9e436SJérôme Duval	//	Use ECHO_ASSERT to be sure AssignResources was called!
210626bc4beSJérôme Duval	//
2114dd9e436SJérôme Duval	ECHO_ASSERT(m_pvSharedMemory );
212626bc4beSJérôme Duval
213626bc4beSJérôme Duval	return ECHOSTATUS_OK;
214626bc4beSJérôme Duval
215626bc4beSJérôme Duval} // ECHOSTATUS CEchoGals::InitHw()
216626bc4beSJérôme Duval
217626bc4beSJérôme Duval
218626bc4beSJérôme Duval//===========================================================================
219626bc4beSJérôme Duval//
220626bc4beSJérôme Duval// This method initializes classes to control the mixer controls for
221626bc4beSJérôme Duval// the busses and pipes.  This is a protected method; it is called
222626bc4beSJérôme Duval// from each of the CEchoGals derived classes once the DSP is up
223626bc4beSJérôme Duval// and running.
224626bc4beSJérôme Duval//
225626bc4beSJérôme Duval//===========================================================================
226626bc4beSJérôme Duval
227626bc4beSJérôme DuvalECHOSTATUS CEchoGals::InitLineLevels()
228626bc4beSJérôme Duval{
229626bc4beSJérôme Duval	ECHOSTATUS	Status = ECHOSTATUS_OK;
230626bc4beSJérôme Duval	WORD			i;
231626bc4beSJérôme Duval
232626bc4beSJérôme Duval	m_fMixerDisabled = TRUE;
233626bc4beSJérôme Duval
234626bc4beSJérôme Duval	if ( 	(NULL == GetDspCommObject()) ||
235626bc4beSJérôme Duval			(GetDspCommObject()->IsBoardBad() ) )
236626bc4beSJérôme Duval	{
237626bc4beSJérôme Duval		return ECHOSTATUS_DSP_DEAD;
238626bc4beSJérôme Duval	}
239626bc4beSJérôme Duval
240626bc4beSJérôme Duval	//
241626bc4beSJérôme Duval	// Do output busses first since output pipes & monitors
242626bc4beSJérôme Duval	// depend on output bus values
243626bc4beSJérôme Duval	//
244626bc4beSJérôme Duval	for ( i = 0; i < GetNumBussesOut(); i++ )
245626bc4beSJérôme Duval	{
246626bc4beSJérôme Duval		m_BusOutLineLevels[ i ].Init( i, this );
247626bc4beSJérôme Duval	}
248626bc4beSJérôme Duval
249626bc4beSJérôme Duval	Status = m_PipeOutCtrl.Init(this);
250626bc4beSJérôme Duval	if (ECHOSTATUS_OK != Status)
251626bc4beSJérôme Duval		return Status;
252626bc4beSJérôme Duval
253626bc4beSJérôme Duval	Status = m_MonitorCtrl.Init(this);
254626bc4beSJérôme Duval	if (ECHOSTATUS_OK != Status)
255626bc4beSJérôme Duval		return Status;
256626bc4beSJérôme Duval
257626bc4beSJérôme Duval	for ( i = 0; i < GetNumBussesIn(); i++ )
258626bc4beSJérôme Duval	{
259626bc4beSJérôme Duval		m_BusInLineLevels[ i ].Init(	i,	this );
260626bc4beSJérôme Duval	}
261626bc4beSJérôme Duval
262626bc4beSJérôme Duval	m_fMixerDisabled = FALSE;
263626bc4beSJérôme Duval
264626bc4beSJérôme Duval	return Status;
265626bc4beSJérôme Duval
266626bc4beSJérôme Duval}	// ECHOSTATUS CEchoGals::InitLineLevels()
267626bc4beSJérôme Duval
268626bc4beSJérôme Duval
269626bc4beSJérôme Duval
270626bc4beSJérôme Duval
271626bc4beSJérôme Duval/******************************************************************************
272626bc4beSJérôme Duval
273626bc4beSJérôme Duval CEchoGals interrupt handler functions
274626bc4beSJérôme Duval
275626bc4beSJérôme Duval ******************************************************************************/
276626bc4beSJérôme Duval
277626bc4beSJérôme Duval//===========================================================================
278626bc4beSJérôme Duval//
279626bc4beSJérôme Duval// This isn't the interrupt handler itself; rather, the OS-specific layer
280626bc4beSJérôme Duval// of the driver has an interrupt handler that calls this function.
281626bc4beSJérôme Duval//
282626bc4beSJérôme Duval//===========================================================================
283626bc4beSJérôme Duval
284626bc4beSJérôme DuvalECHOSTATUS CEchoGals::ServiceIrq(BOOL &fMidiReceived)
285626bc4beSJérôme Duval{
286626bc4beSJérôme Duval	CDspCommObject *pDCO;
287626bc4beSJérôme Duval
288626bc4beSJérôme Duval	//
289626bc4beSJérôme Duval	// Read the DSP status register and see if this DSP
290626bc4beSJérôme Duval	// generated this interrupt
291626bc4beSJérôme Duval	//
292626bc4beSJérôme Duval	fMidiReceived = FALSE;
293626bc4beSJérôme Duval
294626bc4beSJérôme Duval	pDCO = GetDspCommObject();
295626bc4beSJérôme Duval	if ( pDCO->GetStatusReg() & CHI32_STATUS_IRQ )
296626bc4beSJérôme Duval	{
297626bc4beSJérôme Duval
298626bc4beSJérôme Duval#ifdef MIDI_SUPPORT
299626bc4beSJérôme Duval
300626bc4beSJérôme Duval		//
301626bc4beSJérôme Duval		// If this was a MIDI input interrupt, get the MIDI input data
302626bc4beSJérôme Duval		//
303626bc4beSJérôme Duval		DWORD dwMidiInCount;
304626bc4beSJérôme Duval
305626bc4beSJérôme Duval		pDCO->ReadMidi( 0, dwMidiInCount );	  // The count is at index 0
306626bc4beSJérôme Duval		if ( 0 != dwMidiInCount )
307626bc4beSJérôme Duval		{
308626bc4beSJérôme Duval			m_MidiIn.ServiceIrq();
309626bc4beSJérôme Duval			fMidiReceived = TRUE;
310626bc4beSJérôme Duval		}
311626bc4beSJérôme Duval
312626bc4beSJérôme Duval#endif // MIDI_SUPPORT
313626bc4beSJérôme Duval
314626bc4beSJérôme Duval		//
315626bc4beSJérôme Duval		//	Clear the hardware interrupt
316626bc4beSJérôme Duval		//
317626bc4beSJérôme Duval		pDCO->AckInt();
318626bc4beSJérôme Duval
319626bc4beSJérôme Duval		return ECHOSTATUS_OK;
320626bc4beSJérôme Duval	}
321626bc4beSJérôme Duval
322626bc4beSJérôme Duval	//
323626bc4beSJérôme Duval	// This interrupt line must be shared
324626bc4beSJérôme Duval	//
325626bc4beSJérôme Duval	/*
326626bc4beSJérôme Duval	ECHO_DEBUGPRINTF( ("CEchoGals::ServiceIrq() %s\tInterrupt not ours!\n",
327626bc4beSJérôme Duval							 GetDeviceName()) );
328626bc4beSJérôme Duval	*/
329626bc4beSJérôme Duval
330626bc4beSJérôme Duval	return ECHOSTATUS_IRQ_NOT_OURS;
331626bc4beSJérôme Duval
332626bc4beSJérôme Duval}	// ECHOSTATUS CEchoGals::ServiceIrq()
333626bc4beSJérôme Duval
334626bc4beSJérôme Duval
335626bc4beSJérôme Duval
336626bc4beSJérôme Duval
337626bc4beSJérôme Duval/****************************************************************************
338626bc4beSJérôme Duval
339626bc4beSJérôme Duval	Character strings for the ECHOSTATUS return values -
340626bc4beSJérôme Duval	useful for debugging.
341626bc4beSJérôme Duval
342626bc4beSJérôme Duval ****************************************************************************/
343626bc4beSJérôme Duval
344626bc4beSJérôme Duval//
345626bc4beSJérôme Duval// pStatusStrs is used if you want to print out a friendlier version of
346626bc4beSJérôme Duval// the various ECHOSTATUS codes.
347626bc4beSJérôme Duval//
348626bc4beSJérôme Duvalchar *	pStatusStrs[ECHOSTATUS_LAST] =
349626bc4beSJérôme Duval{
350626bc4beSJérôme Duval	"ECHOSTATUS_OK",
351626bc4beSJérôme Duval	"ECHOSTATUS_BAD_FORMAT",
352626bc4beSJérôme Duval	"ECHOSTATUS_BAD_BUFFER_SIZE",
353626bc4beSJérôme Duval	"ECHOSTATUS_CANT_OPEN",
354626bc4beSJérôme Duval	"ECHOSTATUS_CANT_CLOSE",
355626bc4beSJérôme Duval	"ECHOSTATUS_CHANNEL_NOT_OPEN",
356626bc4beSJérôme Duval	"ECHOSTATUS_BUSY",
357626bc4beSJérôme Duval	"ECHOSTATUS_BAD_LEVEL",
358626bc4beSJérôme Duval	"ECHOSTATUS_NO_MIDI",
359626bc4beSJérôme Duval	"ECHOSTATUS_CLOCK_NOT_SUPPORTED",
360626bc4beSJérôme Duval	"ECHOSTATUS_CLOCK_NOT_AVAILABLE",
361626bc4beSJérôme Duval	"ECHOSTATUS_BAD_CARDID",
362626bc4beSJérôme Duval	"ECHOSTATUS_NOT_SUPPORTED",
363626bc4beSJérôme Duval	"ECHOSTATUS_BAD_NOTIFY_SIZE",
364626bc4beSJérôme Duval	"ECHOSTATUS_INVALID_PARAM",
365626bc4beSJérôme Duval	"ECHOSTATUS_NO_MEM",
366626bc4beSJérôme Duval	"ECHOSTATUS_NOT_SHAREABLE",
367626bc4beSJérôme Duval	"ECHOSTATUS_FIRMWARE_LOADED",
368626bc4beSJérôme Duval	"ECHOSTATUS_DSP_DEAD",
369626bc4beSJérôme Duval	"ECHOSTATUS_DSP_TIMEOUT",
370626bc4beSJérôme Duval	"ECHOSTATUS_INVALID_CHANNEL",
371626bc4beSJérôme Duval	"ECHOSTATUS_CHANNEL_ALREADY_OPEN",
372626bc4beSJérôme Duval	"ECHOSTATUS_DUCK_FULL",
373626bc4beSJérôme Duval	"ECHOSTATUS_INVALID_INDEX",
374626bc4beSJérôme Duval	"ECHOSTATUS_BAD_CARD_NAME",
375626bc4beSJérôme Duval	"ECHOSTATUS_IRQ_NOT_OURS",
376626bc4beSJérôme Duval	"",
377626bc4beSJérôme Duval	"",
378626bc4beSJérôme Duval	"",
379626bc4beSJérôme Duval	"",
380626bc4beSJérôme Duval	"",
381626bc4beSJérôme Duval	"ECHOSTATUS_BUFFER_OVERFLOW",
382626bc4beSJérôme Duval	"ECHOSTATUS_OPERATION_CANCELED",
383626bc4beSJérôme Duval	"ECHOSTATUS_EVENT_NOT_OPEN",
384626bc4beSJérôme Duval	"ECHOSTATUS_ASIC_NOT_LOADED"
385626bc4beSJérôme Duval	"ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED",
386626bc4beSJérôme Duval	"ECHOSTATUS_RESERVED",
387626bc4beSJérôme Duval	"ECHOSTATUS_BAD_COOKIE",
388626bc4beSJérôme Duval	"ECHOSTATUS_MIXER_DISABLED",
389626bc4beSJérôme Duval	"ECHOSTATUS_NO_SUPER_INTERLEAVE",
390626bc4beSJérôme Duval	"ECHOSTATUS_DUCK_NOT_WRAPPED"
391626bc4beSJérôme Duval};
392626bc4beSJérôme Duval
393626bc4beSJérôme Duval
394626bc4beSJérôme Duval
395626bc4beSJérôme Duval// *** CEchoGals.cpp ***
396626bc4beSJérôme Duval
397626bc4beSJérôme Duval
398626bc4beSJérôme Duval
399626bc4beSJérôme Duval
400626bc4beSJérôme Duval
401c2ddc71cSJérôme Duval