tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / devs / AHI / Drivers / EMU10kx / CAMD / emu10kx.c
blob989b93c6ca480461baf0345f620271b4799b0373
1 /*
2 emu10kx - CAMD driver for SoundBlaster Live! series
3 Copyright (C) 2003-2005 Martin Blom <martin@blom.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <config.h>
22 #include <exec/memory.h>
23 #include <midi/camddevices.h>
24 #include <clib/alib_protos.h>
25 #include <proto/exec.h>
27 #include "emu10kx-camd.h"
28 #include "camdstubs.h"
29 #include "version.h"
31 struct PortInfo
33 struct Hook TransmitHook;
34 struct Hook ReceiveHook;
35 APTR TransmitFunc;
36 APTR ReceiveFunc;
37 APTR UserData;
41 /*** Module entry (exactly 4 bytes!!) *****************************************/
43 __asm(
44 " moveq #-1,%d0\n"
45 " rts\n"
48 /*** Identification data must follow directly *********************************/
50 static struct MidiDeviceData MidiDeviceData =
52 MDD_Magic,
53 "emu10kx",
54 "emu10kx CAMD MIDI driver " VERS,
55 VERSION, REVISION,
56 gwInit,
57 gwExpunge,
58 gwOpenPort,
59 gwClosePort,
60 4, // For some braindamaged reason, camd.library V40 reads
61 // this value BEFORE calling Init(). :-(
62 1 // Use new-style if using camd.library V40
66 /*** Global data **************************************************************/
68 #ifndef __AROS__
69 static struct ExecBase* SysBase = NULL;
70 #endif
71 static struct Library* EMU10kxBase = NULL;
72 static struct EMU10kxCamd* EMU10kxCamd = NULL;
73 static struct PortInfo* PortInfos = NULL;
74 static ULONG CAMDv40 = FALSE;
75 static const char VersionString[] = "$VER: emu10kx " VERS "\r\n";
78 /*** Debug code ***************************************************************/
80 static UWORD rawputchar_m68k[] =
82 0x2C4B, // MOVEA.L A3,A6
83 0x4EAE, 0xFDFC, // JSR -$0204(A6)
84 0x4E75 // RTS
88 static void
89 KPrintFArgs( UBYTE* fmt,
90 ULONG* args )
92 RawDoFmt( fmt, args, (void(*)(void)) rawputchar_m68k, SysBase );
95 #define KPrintF( fmt, ... ) \
96 ({ \
97 ULONG _args[] = { __VA_ARGS__ }; \
98 KPrintFArgs( (fmt), _args ); \
102 /*** CAMD callbacks ***********************************************************/
104 #ifdef __AROS__
105 static AROS_UFH3(ULONG, TransmitFunc,
106 AROS_UFHA(struct Hook *, hook, A0),
107 AROS_UFHA(struct Library *, emu10kxbase, A2),
108 AROS_UFHA(APTR, null, A1))
110 AROS_USERFUNC_INIT
111 #else
112 static ULONG
113 TransmitFunc( struct Hook* hook __asm( "a0" ),
114 struct Library* emu10kxbase __asm( "a2" ),
115 APTR null __asm( "a1" ) )
117 #endif
118 struct PortInfo* pi = (struct PortInfo*) hook->h_Data;
119 ULONG res;
121 __asm volatile (
122 "movel %1,%%a2\n"
123 "movel %2,%%a0\n"
124 "jsr (%%a0)\n"
125 "swapw %%d0\n"
126 "movew %%d1,%%d0\n"
127 "swapw %%d0\n"
128 : "=r"(res)
129 : "m" (pi->UserData), "m" (pi->TransmitFunc)
130 : "a0", "a2" );
132 return res;
133 #ifdef __AROS__
134 AROS_USERFUNC_EXIT
135 #endif
139 #ifdef __AROS__
140 static AROS_UFH3(VOID, ReceiveFunc,
141 AROS_UFHA(struct Hook *, hook, A0),
142 AROS_UFHA(struct Library *, emu10kxbase, A2),
143 AROS_UFHA(struct ReceiveMessage*, msg, A1))
145 AROS_USERFUNC_INIT
146 #else
147 static VOID
148 ReceiveFunc( struct Hook* hook __asm( "a0" ),
149 struct Library* emu10kxbase __asm( "a2" ),
150 struct ReceiveMessage* msg __asm( "a1" ) )
152 #endif
153 struct PortInfo* pi = (struct PortInfo*) hook->h_Data;
155 __asm volatile (
156 "movel %0,%%d0\n"
157 "movel %1,%%a2\n"
158 "movel %2,%%a0\n"
159 "jsr (%%a0)\n"
161 : "m" (msg->InputByte), "m" (pi->UserData), "m" (pi->ReceiveFunc)
162 : "d0", "a0", "a2" );
163 #ifdef __AROS__
164 AROS_USERFUNC_EXIT
165 #endif
169 /*** ActivateXmit *************************************************************/
171 VOID
172 _ActivateXmit( APTR userdata,
173 ULONG portnum )
175 // In the original CAMD, there is no port number :-(
177 // KPrintF( "ActiavteXmit( %08lx, %ld )\n", userdata, portnum & 255 );
179 if( !CAMDv40 )
181 for( portnum = 0; portnum < MidiDeviceData.NPorts; ++portnum )
183 if( userdata == PortInfos[ portnum ].UserData )
185 break;
189 if( portnum == MidiDeviceData.NPorts )
191 return;
195 CallHook( &EMU10kxCamd->ActivateXmitFunc, (Object*) EMU10kxBase,
196 portnum & 255 );
199 struct MidiPortData MidiPortData =
201 gwActivateXmit
205 /*** Init *********************************************************************/
207 #ifdef __AROS__
208 #include <aros/symbolsets.h>
210 THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)
211 THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)
212 DEFINESET(INIT)
213 DEFINESET(EXIT)
214 #endif
216 VOID
217 _Expunge( ULONG dummy );
219 BOOL
220 _Init( struct ExecBase* sysbase )
222 struct Library* camdlib;
224 #ifdef __AROS__
225 SysBase = sysbase;
226 #else
227 // sysbase is not valid in the original CAMD anyway
228 SysBase = *(struct ExecBase**) 4;
229 #endif
231 #ifdef __AROS__
232 if (!set_call_funcs(SETNAME(INIT), 1, 1))
233 return NULL;
234 #endif
236 EMU10kxBase = OpenLibrary( "DEVS:AHI/emu10kx.audio", VERSION );
238 if( EMU10kxBase == NULL )
240 return FALSE;
243 Forbid();
244 EMU10kxCamd = (struct EMU10kxCamd*) FindSemaphore( EMU10KX_CAMD_SEMAPHORE );
245 if( EMU10kxCamd != NULL )
247 ObtainSemaphore( &EMU10kxCamd->Semaphore );
249 Permit();
251 if( EMU10kxCamd == NULL )
253 _Expunge( 0 );
254 return FALSE;
257 MidiDeviceData.NPorts = EMU10kxCamd->Cards;
259 PortInfos = AllocVec( sizeof( struct PortInfo ) * EMU10kxCamd->Cards,
260 MEMF_PUBLIC );
262 if( PortInfos == NULL )
264 _Expunge( 0 );
265 return FALSE;
268 return TRUE;
272 /*** Expunge ******************************************************************/
274 VOID
275 _Expunge( ULONG dummy )
277 FreeVec( PortInfos );
279 if( EMU10kxCamd != NULL )
281 ReleaseSemaphore( &EMU10kxCamd->Semaphore );
284 #ifdef __AROS__
285 set_call_funcs(SETNAME(EXIT), -1, 0);
286 #endif
288 CloseLibrary( EMU10kxBase );
292 /*** OpenPort *****************************************************************/
294 struct MidiPortData*
295 _OpenPort( struct MidiDeviceData* data,
296 LONG portnum,
297 APTR transmitfunc,
298 APTR receivefunc,
299 APTR userdata )
301 static struct Library* camdbase = NULL;
303 struct PortInfo* pi = &PortInfos[ portnum & 255 ];
305 pi->TransmitHook.h_Entry = (HOOKFUNC) TransmitFunc;
306 pi->TransmitHook.h_Data = pi;
307 pi->ReceiveHook.h_Entry = (HOOKFUNC) ReceiveFunc;
308 pi->ReceiveHook.h_Data = pi;
309 pi->TransmitFunc = transmitfunc;
310 pi->ReceiveFunc = receivefunc;
311 pi->UserData = userdata;
313 if( camdbase == NULL )
315 camdbase = OpenLibrary( "camd.library", 0 );
317 if( camdbase != NULL )
319 CAMDv40 = ( camdbase->lib_Version >= 40 );
322 // Close library but leave pointer set, so we never execute this
323 // code again.
324 CloseLibrary( camdbase );
327 if( !CallHook( &EMU10kxCamd->OpenPortFunc, (Object*) EMU10kxBase,
328 portnum & 255, CAMDv40, &pi->TransmitHook, &pi->ReceiveHook ) )
330 return NULL;
333 return &MidiPortData;
337 /*** ClosePort ****************************************************************/
339 VOID
340 _ClosePort( struct MidiDeviceData *data, LONG portnum )
342 CallHook( &EMU10kxCamd->ClosePortFunc, (Object*) EMU10kxBase,
343 portnum & 255 );