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,
22 ** ---------- ------------- -------------------------------------------------
23 ** 2009-07-21 T. Wiszkowski Corrected SprintfA to prevent bad crashes on aros
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"
51 /******************************************************************************
52 ** Findnode *******************************************************************
53 ******************************************************************************/
55 // Find a node in a list
58 FindNode ( struct List
*list
,
61 struct Node
*currentnode
;
63 for(currentnode
= list
->lh_Head
;
65 currentnode
= currentnode
->ln_Succ
)
67 if(currentnode
== node
)
76 /******************************************************************************
77 ** Fixed2Shift ****************************************************************
78 ******************************************************************************/
80 // Returns host many steps to right-shift a value to approximate
81 // scaling with the Fixed argument.
84 Fixed2Shift( Fixed f
)
98 /******************************************************************************
99 ** ReqA ***********************************************************************
100 ******************************************************************************/
103 ReqA( const char* text
, APTR args
)
105 struct EasyStruct es
=
107 sizeof (struct EasyStruct
),
117 EasyRequestArgs( NULL
, &es
, NULL
, args
);
120 /******************************************************************************
121 ** SprintfA *******************************************************************
122 ******************************************************************************/
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@+
133 return RawDoFmt( (UBYTE
*) fmt
,
135 (void(*)(void)) &struffChar
,
138 return RawDoFmt( (UBYTE
*) fmt
,
145 /******************************************************************************
146 ** AHIInitSemaphore ***********************************************************
147 ******************************************************************************/
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 ******************************************************************************/
169 AHIObtainSemaphore( struct SignalSemaphore
* sigSem
)
171 // TODO: Verify license compatibility (Code mostly stolen from AROS).
175 Disable(); // Not Forbid()!
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
++;
189 struct SemaphoreRequest sr
;
191 me
->tc_SigRecvd
&= ~SIGF_SINGLE
;
192 AddTail((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
199 /******************************************************************************
200 ** AHIReleaseSemaphore ********************************************************
201 ******************************************************************************/
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
);
234 sigSem
->ss_Owner
= (struct Task
*)sm
->ssm_Semaphore
;
235 sm
->ssm_Semaphore
= sigSem
;
236 ReplyMsg((struct Message
*)sr
);
241 sigSem
->ss_Owner
= NULL
;
242 sigSem
->ss_QueueCount
= -1;
245 else if(sigSem
->ss_NestCount
< 0)
247 Alert( AN_SemCorrupt
);
254 /******************************************************************************
255 ** AHIAttemptSemaphore ********************************************************
256 ******************************************************************************/
259 AHIAttemptSemaphore( struct SignalSemaphore
* sigSem
)
261 // TODO: Verify license compatibility (Code mostly stolen from AROS).
265 Disable(); // Not Forbid()!
267 sigSem
->ss_QueueCount
++;
268 if( sigSem
->ss_QueueCount
== 0 )
270 sigSem
->ss_Owner
= (APTR
) ~0;
271 sigSem
->ss_NestCount
++;
276 sigSem
->ss_QueueCount
--;
285 /******************************************************************************
286 ** AHIAllocVec ****************************************************************
287 ******************************************************************************/
290 AHIAllocVec( ULONG byteSize
, ULONG requirements
)
295 return AllocVec( byteSize
, requirements
);
297 #if defined( ENABLE_WARPUP )
302 v
= AllocVec32( byteSize
, requirements
);
309 Req( "Internal error: Unknown MixBackend in AHIAllocVec()." );
313 /******************************************************************************
314 ** AHIFreeVec *****************************************************************
315 ******************************************************************************/
318 AHIFreeVec( APTR memoryBlock
)
323 FreeVec( memoryBlock
);
326 #if defined( ENABLE_WARPUP )
328 FreeVec32( memoryBlock
);
333 Req( "Internal error: Unknown MixBackend in AHIFreeVec()." );
337 /******************************************************************************
338 ** AHILoadObject **************************************************************
339 ******************************************************************************/
342 AHILoadObject( const char* objname
)
347 Req( "Internal error: Illegal MixBackend in AHILoadObject()" );
350 #if defined( ENABLE_WARPUP )
355 o
= ELFLoadObject( objname
);
363 Req( "Internal error: Unknown MixBackend in AHILoadObject()." );
367 /******************************************************************************
368 ** AHIUnLoadObject ************************************************************
369 ******************************************************************************/
372 AHIUnloadObject( void* obj
)
377 Req( "Internal error: Illegal MixBackend in AHIUnloadObject()" );
380 #if defined( ENABLE_WARPUP )
382 ELFUnLoadObject( obj
);
387 Req( "Internal error: Unknown MixBackend in AHIUnloadObject()" );
390 /******************************************************************************
391 ** AHIGetELFSymbol ************************************************************
392 ******************************************************************************/
395 AHIGetELFSymbol( const char* name
,
401 Req( "Internal error: Illegal MixBackend in AHIUnloadObject()" );
404 #if defined( ENABLE_WARPUP )
406 return ELFGetSymbol( PPCObject
, name
, ptr
);
410 Req( "Internal error: Unknown MixBackend in AHIUnloadObject()" );
414 /******************************************************************************
415 **** Endian support code. *****************************************************
416 ******************************************************************************/
418 /* See the header file for macros */
420 #if !defined( WORDS_BIGENDIAN )
423 EndianSwapUWORD( UWORD x
) {
424 return ((((x
) >> 8) & 0x00ffU
) |
425 (((x
) << 8) & 0xff00U
) );
429 EndianSwapULONG( ULONG x
) {
430 return ((((x
) >> 24) & 0x000000ffUL
) |
431 (((x
) >> 8) & 0x0000ff00UL
) |
432 (((x
) << 8) & 0x00ff0000UL
) |
433 (((x
) << 24) & 0xff000000UL
) );
437 EndianSwap( size_t size
, void* data
) {
443 *((UWORD
*) data
) = EndianSwapUWORD( *((UWORD
*) data
) );
447 *((ULONG
*) data
) = EndianSwapULONG( *((ULONG
*) data
) );
453 tmp
= EndianSwapULONG( *((ULONG
*) data
) );
454 *((ULONG
*) data
) = EndianSwapULONG( *((ULONG
*) (data
+ 4)) );
455 *((ULONG
*) (data
+ 4)) = tmp
;
466 /******************************************************************************
467 ** PreTimer ******************************************************************
468 ******************************************************************************/
471 PreTimerFunc( struct Hook
* hook
,
472 struct AHIPrivAudioCtrl
* audioctrl
,
475 return PreTimer( audioctrl
);
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
)
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
);
510 /******************************************************************************
511 ** PostTimer *****************************************************************
512 ******************************************************************************/
515 PostTimerFunc( struct Hook
* hook
,
516 struct AHIPrivAudioCtrl
* audioctrl
,
519 PostTimer( audioctrl
);
523 PostTimer( struct AHIPrivAudioCtrl
* audioctrl
)
525 if( TimerBase
== NULL
)
530 ReadEClock( &audioctrl
->ahiac_Timer
.ExitTime
);