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.
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"
33 struct Hook TransmitHook
;
34 struct Hook ReceiveHook
;
41 /*** Module entry (exactly 4 bytes!!) *****************************************/
48 /*** Identification data must follow directly *********************************/
50 static struct MidiDeviceData MidiDeviceData
=
54 "emu10kx CAMD MIDI driver " VERS
,
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 **************************************************************/
69 static struct ExecBase
* SysBase
= NULL
;
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)
89 KPrintFArgs( UBYTE
* fmt
,
92 RawDoFmt( fmt
, args
, (void(*)(void)) rawputchar_m68k
, SysBase
);
95 #define KPrintF( fmt, ... ) \
97 ULONG _args[] = { __VA_ARGS__ }; \
98 KPrintFArgs( (fmt), _args ); \
102 /*** CAMD callbacks ***********************************************************/
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
))
113 TransmitFunc( struct Hook
* hook
__asm( "a0" ),
114 struct Library
* emu10kxbase
__asm( "a2" ),
115 APTR null
__asm( "a1" ) )
118 struct PortInfo
* pi
= (struct PortInfo
*) hook
->h_Data
;
129 : "m" (pi
->UserData
), "m" (pi
->TransmitFunc
)
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
))
148 ReceiveFunc( struct Hook
* hook
__asm( "a0" ),
149 struct Library
* emu10kxbase
__asm( "a2" ),
150 struct ReceiveMessage
* msg
__asm( "a1" ) )
153 struct PortInfo
* pi
= (struct PortInfo
*) hook
->h_Data
;
161 : "m" (msg
->InputByte
), "m" (pi
->UserData
), "m" (pi
->ReceiveFunc
)
162 : "d0", "a0", "a2" );
169 /*** ActivateXmit *************************************************************/
172 _ActivateXmit( APTR userdata
,
175 // In the original CAMD, there is no port number :-(
177 // KPrintF( "ActiavteXmit( %08lx, %ld )\n", userdata, portnum & 255 );
181 for( portnum
= 0; portnum
< MidiDeviceData
.NPorts
; ++portnum
)
183 if( userdata
== PortInfos
[ portnum
].UserData
)
189 if( portnum
== MidiDeviceData
.NPorts
)
195 CallHook( &EMU10kxCamd
->ActivateXmitFunc
, (Object
*) EMU10kxBase
,
199 struct MidiPortData MidiPortData
=
205 /*** Init *********************************************************************/
208 #include <aros/symbolsets.h>
210 THIS_PROGRAM_HANDLES_SYMBOLSET(INIT
)
211 THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT
)
217 _Expunge( ULONG dummy
);
220 _Init( struct ExecBase
* sysbase
)
222 struct Library
* camdlib
;
227 // sysbase is not valid in the original CAMD anyway
228 SysBase
= *(struct ExecBase
**) 4;
232 if (!set_call_funcs(SETNAME(INIT
), 1, 1))
236 EMU10kxBase
= OpenLibrary( "DEVS:AHI/emu10kx.audio", VERSION
);
238 if( EMU10kxBase
== NULL
)
244 EMU10kxCamd
= (struct EMU10kxCamd
*) FindSemaphore( EMU10KX_CAMD_SEMAPHORE
);
245 if( EMU10kxCamd
!= NULL
)
247 ObtainSemaphore( &EMU10kxCamd
->Semaphore
);
251 if( EMU10kxCamd
== NULL
)
257 MidiDeviceData
.NPorts
= EMU10kxCamd
->Cards
;
259 PortInfos
= AllocVec( sizeof( struct PortInfo
) * EMU10kxCamd
->Cards
,
262 if( PortInfos
== NULL
)
272 /*** Expunge ******************************************************************/
275 _Expunge( ULONG dummy
)
277 FreeVec( PortInfos
);
279 if( EMU10kxCamd
!= NULL
)
281 ReleaseSemaphore( &EMU10kxCamd
->Semaphore
);
285 set_call_funcs(SETNAME(EXIT
), -1, 0);
288 CloseLibrary( EMU10kxBase
);
292 /*** OpenPort *****************************************************************/
295 _OpenPort( struct MidiDeviceData
* data
,
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
324 CloseLibrary( camdbase
);
327 if( !CallHook( &EMU10kxCamd
->OpenPortFunc
, (Object
*) EMU10kxBase
,
328 portnum
& 255, CAMDv40
, &pi
->TransmitHook
, &pi
->ReceiveHook
) )
333 return &MidiPortData
;
337 /*** ClosePort ****************************************************************/
340 _ClosePort( struct MidiDeviceData
*data
, LONG portnum
)
342 CallHook( &EMU10kxCamd
->ClosePortFunc
, (Object
*) EMU10kxBase
,