revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Device / misc.c
blobe783e62d3bfa09432b2d03c110e54c81b7cea5b3
1 /*
2 AHI - Hardware independent audio subsystem
3 Copyright (C) 1996-2005 Martin Blom <martin@blom.org>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
18 MA 02139, USA.
21 ** WHEN WHO WHAT
22 ** ---------- ------------- -------------------------------------------------
23 ** 2009-07-21 T. Wiszkowski Corrected SprintfA to prevent bad crashes on aros
25 #include <config.h>
27 #include <stdarg.h>
29 #include <exec/alerts.h>
30 #include <exec/execbase.h>
31 #include <exec/lists.h>
32 #include <exec/nodes.h>
33 #include <exec/semaphores.h>
34 #include <intuition/intuition.h>
36 #include <proto/exec.h>
37 #include <proto/intuition.h>
38 #include <proto/timer.h>
40 #if defined( ENABLE_WARPUP )
41 # include <powerpc/powerpc.h>
42 # include <powerpc/memoryPPC.h>
43 # include <proto/powerpc.h>
44 #include "elfloader.h"
45 #endif
47 #include "ahi_def.h"
48 #include "header.h"
49 #include "misc.h"
51 /******************************************************************************
52 ** Findnode *******************************************************************
53 ******************************************************************************/
55 // Find a node in a list
57 struct Node *
58 FindNode ( struct List *list,
59 struct Node *node )
61 struct Node *currentnode;
63 for(currentnode = list->lh_Head;
64 currentnode->ln_Succ;
65 currentnode = currentnode->ln_Succ)
67 if(currentnode == node)
69 return currentnode;
72 return NULL;
76 /******************************************************************************
77 ** Fixed2Shift ****************************************************************
78 ******************************************************************************/
80 // Returns host many steps to right-shift a value to approximate
81 // scaling with the Fixed argument.
83 int
84 Fixed2Shift( Fixed f )
86 int i = 0;
87 Fixed ref = 0x10000;
89 while( f < ref )
91 i++;
92 ref >>= 1;
95 return i;
98 /******************************************************************************
99 ** ReqA ***********************************************************************
100 ******************************************************************************/
102 void
103 ReqA( const char* text, APTR args )
105 struct EasyStruct es =
107 sizeof (struct EasyStruct),
109 (STRPTR) DevName,
110 (STRPTR) text,
111 "OK"
112 #ifdef __AMIGAOS4__
113 ,0,0
114 #endif
117 EasyRequestArgs( NULL, &es, NULL, args );
120 /******************************************************************************
121 ** SprintfA *******************************************************************
122 ******************************************************************************/
124 char*
125 SprintfA( char *dst, const char *fmt, IPTR* args )
127 #if !defined(__AMIGAOS4__) && !defined(__AROS__)
128 static const UWORD struffChar[] =
130 0x16c0, // moveb %d0,%a3@+
131 0x4e75 // rts
133 return RawDoFmt( (UBYTE*) fmt,
134 args,
135 (void(*)(void)) &struffChar,
136 dst );
137 #else
138 return (char *)RawDoFmt( (UBYTE*) fmt,
139 (RAWARG)args,
141 dst );
142 #endif
145 /******************************************************************************
146 ** AHIInitSemaphore ***********************************************************
147 ******************************************************************************/
149 void
150 AHIInitSemaphore( struct SignalSemaphore* sigSem )
152 // TODO: Verify license compatibility (Code mostly stolen from AROS).
154 sigSem->ss_WaitQueue.mlh_Head = (struct MinNode *)&sigSem->ss_WaitQueue.mlh_Tail;
155 sigSem->ss_WaitQueue.mlh_Tail = NULL;
156 sigSem->ss_WaitQueue.mlh_TailPred = (struct MinNode *)&sigSem->ss_WaitQueue.mlh_Head;
157 sigSem->ss_Link.ln_Type = NT_SIGNALSEM;
158 sigSem->ss_NestCount = 0;
159 sigSem->ss_Owner = 0;
160 sigSem->ss_QueueCount = -1;
164 /******************************************************************************
165 ** AHIObtainSemaphore *********************************************************
166 ******************************************************************************/
168 void
169 AHIObtainSemaphore( struct SignalSemaphore* sigSem )
171 // TODO: Verify license compatibility (Code mostly stolen from AROS).
173 struct Task *me;
175 Disable(); // Not Forbid()!
176 me = FindTask(NULL);
177 sigSem->ss_QueueCount++;
178 if( sigSem->ss_QueueCount == 0 )
180 sigSem->ss_Owner = me;
181 sigSem->ss_NestCount++;
183 else if( sigSem->ss_Owner == me )
185 sigSem->ss_NestCount++;
187 else
189 struct SemaphoreRequest sr;
190 sr.sr_Waiter = me;
191 me->tc_SigRecvd &= ~SIGF_SINGLE;
192 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
193 Wait(SIGF_SINGLE);
195 Enable();
199 /******************************************************************************
200 ** AHIReleaseSemaphore ********************************************************
201 ******************************************************************************/
202 #include "debug.h"
203 void
204 AHIReleaseSemaphore( struct SignalSemaphore* sigSem )
206 // TODO: Verify license compatibility (Code mostly stolen from AROS).
208 Disable(); // Not Forbid()!
210 sigSem->ss_NestCount--;
211 sigSem->ss_QueueCount--;
212 if(sigSem->ss_NestCount == 0)
214 if( sigSem->ss_QueueCount >= 0
215 && sigSem->ss_WaitQueue.mlh_Head->mln_Succ != NULL )
217 struct SemaphoreRequest *sr;
218 struct SemaphoreMessage *sm;
219 sr = (struct SemaphoreRequest *)sigSem->ss_WaitQueue.mlh_Head;
221 // Note that shared semaphores are not supported!
223 sm = (struct SemaphoreMessage *)sr;
225 Remove((struct Node *)sr);
226 sigSem->ss_NestCount++;
227 if(sr->sr_Waiter != NULL)
229 sigSem->ss_Owner = sr->sr_Waiter;
230 Signal(sr->sr_Waiter, SIGF_SINGLE);
232 else
234 sigSem->ss_Owner = (struct Task *)sm->ssm_Semaphore;
235 sm->ssm_Semaphore = sigSem;
236 ReplyMsg((struct Message *)sr);
239 else
241 sigSem->ss_Owner = NULL;
242 sigSem->ss_QueueCount = -1;
245 else if(sigSem->ss_NestCount < 0)
247 Alert( AN_SemCorrupt );
250 Enable();
254 /******************************************************************************
255 ** AHIAttemptSemaphore ********************************************************
256 ******************************************************************************/
258 LONG
259 AHIAttemptSemaphore( struct SignalSemaphore* sigSem )
261 // TODO: Verify license compatibility (Code mostly stolen from AROS).
263 LONG rc = FALSE;
265 Disable(); // Not Forbid()!
267 sigSem->ss_QueueCount++;
268 if( sigSem->ss_QueueCount == 0 )
270 sigSem->ss_Owner = (APTR) ~0;
271 sigSem->ss_NestCount++;
272 rc = TRUE;
274 else
276 sigSem->ss_QueueCount--;
279 Enable();
281 return rc;
285 /******************************************************************************
286 ** AHIAllocVec ****************************************************************
287 ******************************************************************************/
289 APTR
290 AHIAllocVec( ULONG byteSize, ULONG requirements )
292 switch( MixBackend )
294 case MB_NATIVE:
295 return AllocVec( byteSize, requirements );
297 #if defined( ENABLE_WARPUP )
298 case MB_WARPUP:
300 APTR v;
302 v = AllocVec32( byteSize, requirements );
303 CacheClearU();
304 return v;
306 #endif
309 Req( "Internal error: Unknown MixBackend in AHIAllocVec()." );
310 return NULL;
313 /******************************************************************************
314 ** AHIFreeVec *****************************************************************
315 ******************************************************************************/
317 void
318 AHIFreeVec( APTR memoryBlock )
320 switch( MixBackend )
322 case MB_NATIVE:
323 FreeVec( memoryBlock );
324 return;
326 #if defined( ENABLE_WARPUP )
327 case MB_WARPUP:
328 FreeVec32( memoryBlock );
329 return;
330 #endif
333 Req( "Internal error: Unknown MixBackend in AHIFreeVec()." );
337 /******************************************************************************
338 ** AHILoadObject **************************************************************
339 ******************************************************************************/
341 void*
342 AHILoadObject( const char* objname )
344 switch( MixBackend )
346 case MB_NATIVE:
347 Req( "Internal error: Illegal MixBackend in AHILoadObject()" );
348 return NULL;
350 #if defined( ENABLE_WARPUP )
351 case MB_WARPUP:
353 void* o;
355 o = ELFLoadObject( objname );
356 CacheClearU();
358 return o;
360 #endif
363 Req( "Internal error: Unknown MixBackend in AHILoadObject()." );
364 return NULL;
367 /******************************************************************************
368 ** AHIUnLoadObject ************************************************************
369 ******************************************************************************/
371 void
372 AHIUnloadObject( void* obj )
374 switch( MixBackend )
376 case MB_NATIVE:
377 Req( "Internal error: Illegal MixBackend in AHIUnloadObject()" );
378 return;
380 #if defined( ENABLE_WARPUP )
381 case MB_WARPUP:
382 ELFUnLoadObject( obj );
383 return;
384 #endif
387 Req( "Internal error: Unknown MixBackend in AHIUnloadObject()" );
390 /******************************************************************************
391 ** AHIGetELFSymbol ************************************************************
392 ******************************************************************************/
394 BOOL
395 AHIGetELFSymbol( const char* name,
396 void** ptr )
398 switch( MixBackend )
400 case MB_NATIVE:
401 Req( "Internal error: Illegal MixBackend in AHIUnloadObject()" );
402 return FALSE;
404 #if defined( ENABLE_WARPUP )
405 case MB_WARPUP:
406 return ELFGetSymbol( PPCObject, name, ptr );
407 #endif
410 Req( "Internal error: Unknown MixBackend in AHIUnloadObject()" );
411 return FALSE;
414 /******************************************************************************
415 **** Endian support code. *****************************************************
416 ******************************************************************************/
418 /* See the header file for macros */
420 #if !defined( WORDS_BIGENDIAN )
422 static UWORD
423 EndianSwapUWORD( UWORD x ) {
424 return ((((x) >> 8) & 0x00ffU) |
425 (((x) << 8) & 0xff00U) );
428 static ULONG
429 EndianSwapULONG( ULONG x ) {
430 return ((((x) >> 24) & 0x000000ffUL) |
431 (((x) >> 8) & 0x0000ff00UL) |
432 (((x) << 8) & 0x00ff0000UL) |
433 (((x) << 24) & 0xff000000UL) );
436 void
437 EndianSwap( size_t size, void* data) {
438 switch( size ) {
439 case 1:
440 break;
442 case 2:
443 *((UWORD*) data) = EndianSwapUWORD( *((UWORD*) data) );
444 break;
446 case 4:
447 *((ULONG*) data) = EndianSwapULONG( *((ULONG*) data) );
448 break;
450 case 8: {
451 ULONG tmp;
453 tmp = EndianSwapULONG( *((ULONG*) data) );
454 *((ULONG*) data) = EndianSwapULONG( *((ULONG*) (data + 4)) );
455 *((ULONG*) (data + 4)) = tmp;
456 break;
459 default:
460 break;
464 #endif
466 /******************************************************************************
467 ** PreTimer ******************************************************************
468 ******************************************************************************/
470 BOOL
471 PreTimerFunc( struct Hook* hook,
472 struct AHIPrivAudioCtrl* audioctrl,
473 void* null )
475 return PreTimer( audioctrl );
478 BOOL
479 PreTimer( struct AHIPrivAudioCtrl* audioctrl )
481 ULONG pretimer_period; // Clocks between PreTimer calls
482 ULONG mixer_time; // Clocks spent in mixer
484 if( TimerBase == NULL )
486 return FALSE;
489 mixer_time = (audioctrl->ahiac_Timer.ExitTime.ev_lo -
490 audioctrl->ahiac_Timer.EntryTime.ev_lo);
492 pretimer_period = audioctrl->ahiac_Timer.EntryTime.ev_lo;
494 ReadEClock( &audioctrl->ahiac_Timer.EntryTime );
496 pretimer_period = audioctrl->ahiac_Timer.EntryTime.ev_lo - pretimer_period;
498 if( pretimer_period != 0 )
500 audioctrl->ahiac_UsedCPU = ( mixer_time << 8 ) / pretimer_period;
502 return ( audioctrl->ahiac_UsedCPU > audioctrl->ahiac_MaxCPU );
504 else
506 return FALSE;
510 /******************************************************************************
511 ** PostTimer *****************************************************************
512 ******************************************************************************/
514 void
515 PostTimerFunc( struct Hook* hook,
516 struct AHIPrivAudioCtrl* audioctrl,
517 void* null )
519 PostTimer( audioctrl );
522 void
523 PostTimer( struct AHIPrivAudioCtrl* audioctrl )
525 if( TimerBase == NULL )
527 return;
530 ReadEClock( &audioctrl->ahiac_Timer.ExitTime );