1// ****************************************************************************
2//
3//		OsSupportBeOS.cpp
4//
5//		Implementation file for BeOS support services to the CEchoGals
6//		generic driver class
7//		Set editor tabs to 3 for your viewing pleasure.
8//
9// ----------------------------------------------------------------------------
10//
11// This file is part of Echo Digital Audio's generic driver library.
12// Copyright Echo Digital Audio Corporation (c) 1998 - 2005
13// All rights reserved
14// www.echoaudio.com
15//
16// This library is free software; you can redistribute it and/or
17// modify it under the terms of the GNU Lesser General Public
18// License as published by the Free Software Foundation; either
19// version 2.1 of the License, or (at your option) any later version.
20//
21// This library is distributed in the hope that it will be useful,
22// but WITHOUT ANY WARRANTY; without even the implied warranty of
23// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24// Lesser General Public License for more details.
25//
26// You should have received a copy of the GNU Lesser General Public
27// License along with this library; if not, write to the Free Software
28// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29//
30// ****************************************************************************
31
32#include "OsSupportBeOS.h"
33
34#include "EchoGalsXface.h"
35
36#include <KernelExport.h>
37#include "util.h"
38
39//
40//	Version information.
41//	In NT, we want to get this from a resource
42//
43BYTE OsGetVersion()
44{
45	// Use EngFindResource, for now hard code
46	return( 1 );
47}	// BYTE OsGetVersion()
48
49BYTE OsGetRevision()
50{
51	// Use EngFindResource, for now hard code
52	return( 0 );
53}	// BYTE OsGetRevision()
54
55BYTE OsGetRelease()
56{
57	// Use EngFindResource, for now hard code
58	return( 0 );
59}	// BYTE OsGetRelease()
60
61//
62//	Global Memory Management Functions
63//
64DWORD gAllocNonPagedCount = 0;
65
66LIST_HEAD(mems, _echo_mem) mems;
67
68
69static echo_mem *
70echo_mem_new(size_t size)
71{
72	echo_mem *mem = NULL;
73
74	if ((mem = (echo_mem*)malloc(sizeof(*mem))) == NULL)
75		return (NULL);
76
77	mem->area = alloc_mem(&mem->phy_base, &mem->log_base, size, "echo buffer", true);
78	mem->size = size;
79	if (mem->area < B_OK) {
80		free(mem);
81		return NULL;
82	}
83	return mem;
84}
85
86static void
87echo_mem_delete(echo_mem *mem)
88{
89	if(mem->area > B_OK)
90		delete_area(mem->area);
91	free(mem);
92}
93
94echo_mem *
95echo_mem_alloc(size_t size)
96{
97	echo_mem *mem = NULL;
98
99	mem = echo_mem_new(size);
100	if (mem == NULL)
101		return (NULL);
102
103	LIST_INSERT_HEAD(&mems, mem, next);
104
105	return mem;
106}
107
108void
109echo_mem_free(void *ptr)
110{
111	echo_mem *mem = NULL;
112
113	LIST_FOREACH(mem, &mems, next) {
114		if (mem->log_base != ptr)
115			continue;
116		LIST_REMOVE(mem, next);
117
118		echo_mem_delete(mem);
119		break;
120	}
121}
122
123void OsAllocateInit()
124{
125	gAllocNonPagedCount = 0;
126
127	/* Init mems list */
128	LIST_INIT(&mems);
129}
130
131// ***********************************************************************
132//
133//  Allocate locked, non-pageable block of memory.  Does not have to be
134//	physically contiguous.  Primarily used to implement the overloaded
135//	new operator.
136//
137// ***********************************************************************
138
139ECHOSTATUS OsAllocateNonPaged
140(
141    DWORD	dwByteCt,				// Block size in bytes
142    PPVOID	ppMemAddr				// Where to return memory ptr
143)
144{
145
146
147	echo_mem * mem = echo_mem_alloc( dwByteCt );
148	if(mem)
149		*ppMemAddr = mem->log_base;
150
151	if ( NULL == *ppMemAddr )
152	{
153		ECHO_DEBUGPRINTF( ("OsAllocateNonPaged : Failed on %ld bytes\n",
154								 dwByteCt) );
155		ECHO_DEBUGBREAK();
156		return ECHOSTATUS_NO_MEM;
157	}
158
159	OsZeroMemory( *ppMemAddr, dwByteCt );
160
161	gAllocNonPagedCount++;
162	ECHO_DEBUGPRINTF(("gAllocNonPagedCount %ld\n",gAllocNonPagedCount));
163
164	return ECHOSTATUS_OK;
165
166}	// ECHOSTATUS OsAllocateNonPaged
167
168
169// ***********************************************************************
170//
171// Unlock and free, non-pageable block of memory.
172//
173// ***********************************************************************
174ECHOSTATUS OsFreeNonPaged
175(
176    PVOID	pMemAddr
177)
178{
179	echo_mem_free( pMemAddr );
180
181	gAllocNonPagedCount--;
182	ECHO_DEBUGPRINTF(("gAllocNonPagedCount %ld\n",gAllocNonPagedCount));
183
184	return ECHOSTATUS_OK;
185
186}	// ECHOSTATUS OsFreeNonPaged
187
188
189
190// ***********************************************************************
191//
192// This class is optional and uniquely defined for each OS.  It provides
193//	information that other components may require.
194// For example, in Windows NT it contains a device object used by various
195//	memory management methods.
196// Since static variables are used in place of globals, an instance must
197//	be constructed and initialized by the OS Interface object prior to
198//	constructing the CEchoGals derived object.  The CEchoGals and
199//	CDspCommObject classes must have access to it during their respective
200// construction times.
201//
202// ***********************************************************************
203
204COsSupport::COsSupport
205(
206	WORD				wDeviceId,		// PCI bus device ID
207	WORD				wCardRev			// Card revision number
208)
209{
210   ECHO_DEBUGPRINTF(("COsSupport::COsSupport born, device id = 0x%x.\n", wDeviceId));
211
212	m_wDeviceId = wDeviceId;
213	m_wCardRev = wCardRev;
214}
215
216COsSupport::~COsSupport()
217{
218	ECHO_DEBUGPRINTF(("COsSupport is all gone - m_dwPageBlockCount %ld\n",m_dwPageBlockCount));
219}
220
221//
222//	Timer Methods
223//
224
225ECHOSTATUS COsSupport::OsGetSystemTime
226(
227	PULONGLONG	pullTime					// Where to return system time
228)
229{
230	*pullTime = ULONGLONG(system_time());
231
232	return ECHOSTATUS_OK;
233
234}	// ECHOSTATUS COsSupport::OsGetSystemTime
235
236
237ECHOSTATUS COsSupport::OsSnooze
238(
239	DWORD	dwTime						// Duration in micro seconds
240)
241{
242	status_t status;
243	status = snooze(bigtime_t(dwTime));
244	switch (status) {
245		case B_OK:
246			return ECHOSTATUS_OK;
247			break;
248		case B_INTERRUPTED:
249			return ECHOSTATUS_OPERATION_CANCELED; // maybe not appropriate, but anyway
250			break;
251		default:
252			return ECHOSTATUS_NOT_SUPPORTED; // no generic error?
253			break;
254	}
255}
256
257
258//
259//	Memory Management Methods
260//
261
262//---------------------------------------------------------------------------
263//
264//	Allocate a physical page block that can be used for DSP bus mastering.
265//
266//---------------------------------------------------------------------------
267
268ECHOSTATUS COsSupport::AllocPhysPageBlock
269(
270	DWORD			dwBytes,
271	PPAGE_BLOCK	&pPageBlock
272)
273{
274	DWORD	dwRoundedBytes;
275
276	//
277	// Allocate
278	//
279	dwRoundedBytes = (dwBytes + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
280	ECHO_DEBUGPRINTF(("COsSupport::AllocPhysPageBlock - dwBytes %ld  dwRoundedBytes %ld\n",
281							dwBytes,dwRoundedBytes));
282
283	pPageBlock = echo_mem_alloc ( dwRoundedBytes );
284
285	if (NULL == pPageBlock)
286	{
287		ECHO_DEBUGPRINTF(("AllocPhysPageBlock failed for %ld bytes\n",dwBytes));
288
289		pPageBlock = NULL;
290		return ECHOSTATUS_NO_MEM;
291	}
292
293	ECHO_DEBUGPRINTF(("\tIOBufferMemoryDescriptor is OK\n"));
294
295	OsZeroMemory( pPageBlock->log_base, dwRoundedBytes );
296
297#ifdef _DEBUG
298	m_dwPageBlockCount++;
299	ECHO_DEBUGPRINTF(("\tm_dwPageBlockCount %ld\n",m_dwPageBlockCount));
300#endif
301
302	return ECHOSTATUS_OK;
303
304}	// AllocPageBlock
305
306
307//---------------------------------------------------------------------------
308//
309//	Free a physical page block
310//
311//---------------------------------------------------------------------------
312
313ECHOSTATUS COsSupport::FreePhysPageBlock
314(
315	DWORD			dwBytes,
316	PPAGE_BLOCK	pPageBlock
317)
318{
319	echo_mem_free(pPageBlock->log_base);
320
321#ifdef _DEBUG
322	m_dwPageBlockCount--;
323	ECHO_DEBUGPRINTF(("\tm_dwPageBlockCount %ld\n",m_dwPageBlockCount));
324#endif
325
326	return ECHOSTATUS_OK;
327
328}	// FreePageBlock
329
330
331//---------------------------------------------------------------------------
332//
333//	Get the virtual address for the buffer corresponding to the MDL
334//
335//---------------------------------------------------------------------------
336
337PVOID COsSupport::GetPageBlockVirtAddress
338(
339	PPAGE_BLOCK	pPageBlock
340)
341{
342
343	return pPageBlock->log_base;
344
345}	// GetPageBlockVirtAddress
346
347
348//---------------------------------------------------------------------------
349//
350//	Get the physical address for part of the buffer corresponding to the MDL
351//
352//---------------------------------------------------------------------------
353
354ECHOSTATUS COsSupport::GetPageBlockPhysSegment
355(
356	PPAGE_BLOCK	pPageBlock,			// pass in a previously allocated block
357	DWORD			dwOffset,			// pass in the offset into the block
358	PHYS_ADDR	&PhysAddr,			// returns the physical address
359	DWORD			&dwSegmentSize		// and the length of the segment
360)
361{
362
363	PhysAddr = ((PHYS_ADDR)pPageBlock->phy_base + dwOffset);
364
365	return ECHOSTATUS_OK;
366
367} // GetPageBlockPhysSegment
368
369
370//
371// Add additional methods here
372//
373
374//
375//	Display an error message w/title
376//
377void COsSupport::EchoErrorMsg(const char* pszMsg, const char* pszTitle)
378{
379}
380
381PVOID COsSupport::operator new(size_t size)
382{
383	PVOID 		pMemory;
384
385	pMemory = malloc(size);
386
387	if ( NULL == pMemory )
388	{
389		ECHO_DEBUGPRINTF(("COsSupport::operator new - memory allocation failed\n"));
390
391		pMemory = NULL;
392	}
393	else
394	{
395		memset( pMemory, 0, size );
396	}
397
398	return pMemory;
399}
400
401VOID COsSupport::operator delete(PVOID memory)
402{
403	free(memory);
404}
405
406