xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/OsSupportBeOS.cpp (revision e79e4e7c9e432c90415f79809b7160e864f79001)
1 // ****************************************************************************
2 //
3 //		OsSupportWDM.cpp
4 //
5 //		Implementation file for WDM support services to the CEchoGals
6 //		generic driver class.
7 //
8 //		This will need to be rewritten for each new target OS.
9 //
10 //		Set editor tabs to 3 for your viewing pleasure.
11 //
12 //		Copyright Echo Digital Audio Corporation (c) 1998 - 2002
13 //		All rights reserved
14 //		www.echoaudio.com
15 //
16 //		Modifications for OpenBeOS Copyright Andrew Bachmann (c) 2002
17 //		All rights reserved
18 //		www.openbeos.org
19 //
20 //		Permission is hereby granted, free of charge, to any person obtaining a
21 //		copy of this software and associated documentation files (the
22 //		"Software"), to deal with the Software without restriction, including
23 //		without limitation the rights to use, copy, modify, merge, publish,
24 //		distribute, sublicense, and/or sell copies of the Software, and to
25 //		permit persons to whom the Software is furnished to do so, subject to
26 //		the following conditions:
27 //
28 //		- Redistributions of source code must retain the above copyright
29 //		notice, this list of conditions and the following disclaimers.
30 //
31 //		- Redistributions in binary form must reproduce the above copyright
32 //		notice, this list of conditions and the following disclaimers in the
33 //		documentation and/or other materials provided with the distribution.
34 //
35 //		- Neither the name of Echo Digital Audio, nor the names of its
36 //		contributors may be used to endorse or promote products derived from
37 //		this Software without specific prior written permission.
38 //
39 //		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
40 //		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41 //		MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
42 //		IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
43 //		ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
44 //		TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
45 //		SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
46 //
47 // ****************************************************************************
48 
49 #include "CEchoGals.h"
50 #include <stdarg.h>
51 #include <RealtimeAlloc.h>
52 #include <OS.h>
53 #include <Alert.h>
54 
55 /****************************************************************************
56 
57 	Memory management - not part of COsSupport
58 
59  ****************************************************************************/
60 
61 //===========================================================================
62 //
63 // Init the memory tracking counter; right now, this just uses a simple
64 // scheme that tracks the number of allocations
65 //
66 //===========================================================================
67 
68 DWORD gdwAllocNonPagedCount = 0;
69 rtm_pool * echo_pool = 0;
70 
71 void OsAllocateInit()
72 {
73 	gdwAllocNonPagedCount = 0;
74 	rtm_create_pool(&echo_pool,0xFFFF, ECHO_POOL_TAG);
75 	if ( NULL == echo_pool )
76 	{
77 		ECHO_DEBUGPRINTF( ("OsAllocateInit : Failed to create the pool\n") );
78 		ECHO_DEBUGBREAK();
79 		return;
80 	}
81 
82 }	// OsAllocateInit
83 
84 
85 //===========================================================================
86 //
87 // OsAllocateNonPaged is used to allocate a block of memory that will always
88 // be resident; that is, this particular block of memory won't be swapped
89 // out as virtual memory and can always be accessed at interrupt time.
90 //
91 // gdwAllocNonPagedCount tracks the number of times this has been
92 // successfully called.
93 //
94 // This is primarily used for overloading the new operator for the various
95 // generic classes.
96 //
97 //===========================================================================
98 
99 // OsAllocateNonPaged is used to (surprise!) allocate non-paged memory.  Non-paged
100 // memory is defined as memory that is always physically resident - that is, the virtual
101 // memory manager won't swap this memory to disk.  Nonpaged memory can be accessed
102 // from the interrupt handler.
103 // Nonpaged memory has no particular requirements on address alignment.
104 
105 ECHOSTATUS OsAllocateNonPaged
106 (
107     DWORD	dwByteCt,				// Block size in bytes
108     PPVOID	ppMemAddr				// Where to return memory ptr
109 )
110 {
111 	*ppMemAddr = rtm_alloc( echo_pool, dwByteCt );
112 
113 	if ( NULL == *ppMemAddr )
114 	{
115 		ECHO_DEBUGPRINTF( ("OsAllocateNonPaged : Failed on %d bytes\n",
116 								 dwByteCt) );
117 		ECHO_DEBUGBREAK();
118 		return ECHOSTATUS_NO_MEM;
119 	}
120 
121 	OsZeroMemory( *ppMemAddr, dwByteCt );
122 
123 	gdwAllocNonPagedCount++;
124 	ECHO_DEBUGPRINTF(("gdwAllocNonPagedCount %d\n",gdwAllocNonPagedCount));
125 
126 	return ECHOSTATUS_OK;
127 
128 }	// ECHOSTATUS OsAllocateNonPaged
129 
130 
131 //===========================================================================
132 //
133 // OsFreeNonPaged is used to free memory allocated by OsAllocateNonPaged.
134 //
135 // gdwAllocNonPagedCount tracks the number of times this has been
136 // successfully called.
137 //
138 //===========================================================================
139 
140 ECHOSTATUS OsFreeNonPaged
141 (
142     PVOID	pMemAddr
143 )
144 {
145 	rtm_free( pMemAddr );
146 
147 	gdwAllocNonPagedCount--;
148 	ECHO_DEBUGPRINTF(("gdwAllocNonPagedCount %d\n",gdwAllocNonPagedCount));
149 
150 	return ECHOSTATUS_OK;
151 
152 }	// ECHOSTATUS OsFreeNonPaged
153 
154 
155 //***********************************************************************
156 
157 //
158 // This class is uniquely defined for each OS.  It provides
159 //	information that other components may require.
160 //
161 // For example, in Windows NT it contains a device object used by various
162 //	memory management methods.
163 //
164 // An instance of this class must be constructed and initialized prior to
165 //	constructing the CEchoGals derived object.  The CEchoGals and
166 //	CDspCommObject classes must have access to it during their respective
167 // construction times.
168 //
169 //***********************************************************************
170 
171 //===========================================================================
172 //
173 //	Construction/destruction
174 //
175 //===========================================================================
176 
177 COsSupport::COsSupport
178 (
179 	DWORD				dwDeviceId		// PCI bus subsystem ID
180 )
181 {
182 	m_ullStartTime = system_time(); // All system time calls relative to this
183 
184 	m_dwDeviceId = dwDeviceId;
185 
186 }	// COsSupport::COsSupport()
187 
188 
189 COsSupport::~COsSupport()
190 {
191 }	// COsSupport::~COsSupport()
192 
193 
194 //===========================================================================
195 //
196 //	Timer methods
197 //
198 //===========================================================================
199 
200 //---------------------------------------------------------------------------
201 //
202 // Return the system time in microseconds.
203 // Return error status if the OS doesn't support this function.
204 //
205 //---------------------------------------------------------------------------
206 
207 ECHOSTATUS COsSupport::OsGetSystemTime
208 (
209 	PULONGLONG	pullTime					// Where to return system time
210 )
211 {
212 	*pullTime = ULONGLONG(system_time());
213 
214 	return ECHOSTATUS_OK;
215 
216 }	// ECHOSTATUS COsSupport::OsGetSystemTime
217 
218 
219 //---------------------------------------------------------------------------
220 //
221 // Stall execution for dwTime microseconds.
222 // Return error status if the OS doesn't support this
223 // function.
224 //
225 //---------------------------------------------------------------------------
226 
227 ECHOSTATUS COsSupport::OsSnooze
228 (
229 	DWORD	dwTime						// Duration in micro seconds
230 )
231 {
232 	status_t status;
233 	status = snooze(bigtime_t(dwTime));
234 	switch (status) {
235 		case B_OK:
236 			return ECHOSTATUS_OK;
237 			break;
238 		case B_INTERRUPTED:
239 			return ECHOSTATUS_OPERATION_CANCELED; // maybe not appropriate, but anyway
240 			break;
241 		default:
242 			return ECHOSTATUS_NOT_SUPPORTED; // no generic error?
243 			break;
244 	}
245 }
246 
247 
248 //===========================================================================
249 //
250 //	More memory management
251 //
252 //===========================================================================
253 
254 //---------------------------------------------------------------------------
255 //
256 // Allocate locked, non-pageable, physically contiguous memory pages
257 //	in the drivers address space.  Used to allocate memory for the DSP
258 //	communications area.
259 //
260 // Currently, none of the generic code ever sets dwPageCt to higher than
261 // one.  On the platforms we've developed for so far, a page is 4096
262 // bytes and is aligned on a 4096 byte boundary.  None of the structures
263 // allocated by OsPageAllocate are more than 4096 bytes; memory
264 // allocated by this routine should be at least aligned on a 32 byte
265 // boundary and be physically contiguous.
266 //
267 // Note that this code is not 64 bit ready, since it's only using
268 // the low 32 bits of the physical address.
269 //
270 //---------------------------------------------------------------------------
271 
272 // COsSupport::OsPageAllocate is used for allocating memory that is read and written by
273 // the DSP.  This means that any memory allocated by OsPageAllocate must be nonpaged
274 // and should be aligned on at least a 32 byte address boundary.  It must be aligned on at
275 // least a 4 byte boundary.
276 
277 ECHOSTATUS COsSupport::OsPageAllocate
278 (
279 	DWORD			dwPageCt,				// How many pages to allocate
280 	PPVOID		ppPageAddr,				// Where to return the memory ptr
281 	PPHYS_ADDR	pPhysicalPageAddr		// Where to return the physical PCI address
282 )
283 {
284 	PHYSICAL_ADDRESS		LogicalAddress;
285 
286 	*ppPageAddr = rtm_alloc ( echo_pool, dwPageCt );
287 
288 	if (NULL != *ppPageAddr)
289 	{
290 		physical_entry PhysTemp;
291 
292 		get_memory_map(ppPageAddr, dwPageCt, &PhysTemp, 1);
293 
294 		PhysTemp = MmGetPhysicalAddress(*ppPageAddr); // XXX: ?
295 		*pPhysicalPageAddr = PhysTemp.address;
296 	}
297 
298 	OsZeroMemory( *ppPageAddr, dwPageCt * PAGE_SIZE );
299 
300 	return ECHOSTATUS_OK;
301 
302 }	// ECHOSTATUS COsSupport::OsPageAllocate
303 
304 
305 //---------------------------------------------------------------------------
306 //
307 // Unlock and free non-pageable, physically contiguous memory pages in
308 //	the drivers address space; the inverse of OsPageAllocate
309 //
310 //---------------------------------------------------------------------------
311 
312 ECHOSTATUS COsSupport::OsPageFree
313 (
314 		DWORD			dwPageCt,				// How many pages to free
315 		PVOID			pPageAddr,				// Virtual memory ptr
316 		PHYS_ADDR	PhysicalPageAddr		// Physical PCI addr
317 )
318 {
319 	PHYSICAL_ADDRESS		LogicalAddress;
320 
321 	if (NULL == pPageAddr)
322 		return ECHOSTATUS_OK;
323 
324 	rtm_free(pPageAddr);
325 
326 	return ECHOSTATUS_OK;
327 
328 }	// ECHOSTATUS COsSupport::OsPageFree
329 
330 
331 //---------------------------------------------------------------------------
332 //
333 //	Display an error message w/title; currently not supported under WDM.
334 //
335 //---------------------------------------------------------------------------
336 
337 void COsSupport::EchoErrorMsg
338 (
339 	PCHAR pszMsg,
340 	PCHAR pszTitle
341 )
342 {
343 	BAlert alert(pszTitle,pszMsg,"Ok",NULL,NULL,B_WIDTH_AS_USUAL,B_STOP_ALERT);
344 	alert.Go();
345 }	// void COsSupport::EchoErrorMsg( PCHAR )
346 
347 
348 //---------------------------------------------------------------------------
349 //
350 // Overload new & delete so memory for this object is allocated from
351 //	non-paged memory.
352 //
353 //---------------------------------------------------------------------------
354 
355 PVOID COsSupport::operator new( size_t Size )
356 {
357 	PVOID 		pMemory;
358 
359 	// it's probably better to not rtm alloc this
360 	// but it does need to be resident
361 	pMemory = rtm_alloc(NULL,Size);
362 
363 	if ( NULL == pMemory )
364 	{
365 		ECHO_DEBUGPRINTF(("COsSupport::operator new - memory allocation failed\n"));
366 
367 		pMemory = NULL;
368 	}
369 	else
370 	{
371 		memset( pMemory, 0, Size );
372 	}
373 
374 	return pMemory;
375 
376 }	// PVOID COsSupport::operator new( size_t Size )
377 
378 
379 VOID COsSupport::operator delete( PVOID pVoid )
380 {
381 	status_t status;
382 	status = rtm_free(pVoid);
383 
384 	if (status != B_OK) {
385 		ECHO_DEBUGPRINTF(("COsSupport::operator delete "
386 								"memory free failed\n"));
387 	}
388 
389 }	// VOID COsSupport::operator delete( PVOID pVoid )
390 
391