2 toccata.library - AHI-based Toccata emulation library
3 Copyright (C) 1997-2005 Martin Blom <martin@blom.org> and Teemu Suikki.
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 #define _USEOLDEXEC_ 1
23 #include <exec/types.h>
24 #include <exec/nodes.h>
25 #include <exec/memory.h>
26 #include <exec/resident.h>
27 #include <exec/libraries.h>
28 #include <exec/execbase.h>
29 #include <libraries/dos.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
37 ULONG __asm
_LibExpunge( register __a6
struct MyLibrary
*libbase
);
38 ULONG __asm
_LibInit ( register __a0 APTR seglist
,
39 register __d0
struct MyLibrary
*libbase
);
41 int __saveds __asm
__UserLibInit (register __a6
struct MyLibrary
*libbase
);
42 void __saveds __asm
__UserLibCleanup(register __a6
struct MyLibrary
*libbase
);
44 int __saveds __asm
__UserLibOpen (register __a6
struct MyLibrary
*libbase
);
45 void __saveds __asm
__UserLibClose (register __a6
struct MyLibrary
*libbase
);
47 int __saveds __asm
__UserDevInit (register __d0
long unit
,
48 register __a0
struct IORequest
*ior
,
49 register __a6
struct MyLibrary
*libbase
);
50 void __saveds __asm
__UserDevCleanup(register __a0
struct IORequest
*ior
,
51 register __a6
struct MyLibrary
*libbase
);
53 int __saveds __asm
__libfpinit (register __a6
struct MyLibrary
*libbase
);
54 void __saveds __asm
__libfpterm (register __a6
struct MyLibrary
*libbase
);
57 struct Library ml_Lib
;
58 APTR ml_BoardAddress
; /* Toccata */
59 APTR ml_HardInfo
; /* Toccata */
62 APTR ml_ExecBase
; /* pointer to exec base */
63 #ifndef ONE_GLOBAL_SECTION
64 long * ml_relocs
; /* pointer to relocs. */
65 struct MyLibrary
* ml_origbase
; /* pointer to original library base */
70 typedef LONG (*myPFL
)(); /* pointer to function returning 32-bit int */
72 /* library initialization table, used for AUTOINIT libraries */
74 ULONG
*it_DataSize
; /* library data space size */
75 myPFL
*it_FuncTable
; /* table of entry points */
76 APTR it_DataInit
; /* table of data initializers */
77 myPFL it_InitFunc
; /* initialization function to run */
80 #ifndef ONE_GLOBAL_SECTION
86 /* symbols generated by blink */
87 extern char __far _LibID
[]; /* ID string */
88 extern char __far _LibName
[]; /* Name string */
89 extern char __far RESLEN
; /* size of init data */
90 extern long __far NEWDATAL
; /* size of global data */
91 extern long __far NUMJMPS
; /* number of jmp vectors to copy */
92 extern myPFL _LibFuncTab
[]; /* my function table */
93 extern long __far _LibVersion
; /* Version of library */
94 extern long __far _LibRevision
; /* Revision of library */
95 #define MYVERSION ((long)&_LibVersion)
96 #define MYREVISION ((long)&_LibRevision)
97 #define DATAWORDS ((long)&NEWDATAL) /* magic to get right tpye of reloc */
98 #define SIZEJMPTAB ((long)libbase->ml_origbase->ml_numjmps)
99 /* size in bytes of jmp table */
101 /* From libent.o, needed to determine where data is loaded by loadseg */
102 extern long far _Libmergeddata
;
104 #define MYLIBRARYSIZE ((sizeof(struct MyLibrary) +3) & ~3)
108 struct InitTable __far _LibInitTab
= {
109 (long *)(&RESLEN
+MYLIBRARYSIZE
),
111 NULL
, /* will initialize my own data */
115 __asm ULONG
_LibInit( register __a0 APTR seglist
,
116 register __d0
struct MyLibrary
*libbase
)
118 #ifdef ONE_GLOBAL_SECTION
126 libbase
->ml_SegList
= (ULONG
) seglist
;
128 /* init. library structure (since I don't do automatic data init.) */
130 libbase
->ml_Lib
.lib_Node
.ln_Type
= NT_DEVICE
;
132 libbase
->ml_Lib
.lib_Node
.ln_Type
= NT_LIBRARY
;
134 libbase
->ml_Lib
.lib_Node
.ln_Name
= _LibName
;
135 libbase
->ml_Lib
.lib_Flags
= LIBF_SUMUSED
| LIBF_CHANGED
;
136 libbase
->ml_Lib
.lib_Version
= MYVERSION
;
137 libbase
->ml_Lib
.lib_Revision
= MYREVISION
;
138 libbase
->ml_Lib
.lib_IdString
= (APTR
) _LibID
;
139 #ifndef ONE_GLOBAL_SECTION
140 libbase
->ml_relocs
= NULL
;
141 libbase
->ml_origbase
= libbase
;
142 sdata
= (long *)_LibInitTab
.it_FuncTable
;
143 libbase
->ml_numjmps
= (long)&NUMJMPS
;
145 /* Start of copy of global data after structure */
146 ddata
= (char *)libbase
+ MYLIBRARYSIZE
;
148 sdata
= (long *)&_Libmergeddata
; /* where loadseg loaded the data */
149 memcpy(ddata
, (void *)sdata
, DATAWORDS
*4);
151 /* perform relocs if we want one global section for all programs */
152 /* that have this lib open. If we want a global section for each */
153 /* open, copy the relocs, and do them on each open call. */
154 sdata
= sdata
+ DATAWORDS
;
156 #ifdef ONE_GLOBAL_SECTION
160 reloc
= (long *)((long)ddata
+ *sdata
++);
161 *reloc
+= (long)ddata
;
166 if (__UserLibInit(libbase
) != 0)
167 return NULL
; /* abort if user init failed */
173 if ((libbase
->ml_relocs
= AllocMem((nrelocs
* 4) + 4, MEMF_PUBLIC
)) == NULL
)
175 memcpy((void *)libbase
->ml_relocs
, (void *)sdata
, (nrelocs
* 4) + 4);
179 return ( (ULONG
) libbase
);
184 register __d0
long unit
,
185 register __a1
struct IORequest
*ior
,
187 register __a6
struct MyLibrary
*libbase
)
189 #ifndef ONE_GLOBAL_SECTION
190 struct MyLibrary
*origbase
= libbase
;
191 struct ExecBase
*SysBase
= *(struct ExecBase
**)4;
193 long *sdata
, *ddata
, *reloc
;
197 /* mark us as having another customer */
198 libbase
->ml_Lib
.lib_OpenCnt
++;
200 /* clear delayed expunges (standard procedure) */
201 libbase
->ml_Lib
.lib_Flags
&= ~LIBF_DELEXP
;
203 #ifndef ONE_GLOBAL_SECTION
204 /* Allocate new lib base */
205 newlib
= AllocMem((long)(MYLIBRARYSIZE
+
206 ((long)&RESLEN
) + SIZEJMPTAB
),
207 MEMF_PUBLIC
|MEMF_CLEAR
);
209 if (newlib
== NULL
) goto error
;
212 memcpy(newlib
, (char *)libbase
- SIZEJMPTAB
,
213 (long)(MYLIBRARYSIZE
+ DATAWORDS
*4 + SIZEJMPTAB
));
215 libbase
= (struct MyLibrary
*)(newlib
+SIZEJMPTAB
);
216 libbase
->ml_relocs
= NULL
;
219 ddata
= (long *)((char *)libbase
+ MYLIBRARYSIZE
);
220 sdata
= libbase
->ml_origbase
->ml_relocs
;
226 reloc
= (long *)((long)ddata
+ *sdata
++);
227 *reloc
+= (long)ddata
;
232 /* now we need to flush the cache because we copied the jmp table */
233 if (SysBase
->LibNode
.lib_Version
>= 36)
237 ior
->io_Device
= (struct Device
*)libbase
; /* local copy of libary base */
240 if (__libfpinit(libbase
) ||
242 __UserDevInit(unit
, ior
, libbase
) != 0
244 (__UserLibInit(libbase
) != 0) ||
245 __UserLibOpen(libbase
) != 0)
249 __libfpterm(libbase
);
250 FreeMem(newlib
, (long)(MYLIBRARYSIZE
+
251 ((long)&RESLEN
) + SIZEJMPTAB
));
253 origbase
->ml_origbase
->ml_Lib
.lib_OpenCnt
--;
254 return NULL
; /* abort if user init failed */
259 if (__UserDevInit(unit
, ior
, libbase
) != 0)
261 libbase
->ml_Lib
.lib_OpenCnt
--;
265 if (__UserLibOpen(libbase
) != 0)
267 libbase
->ml_Lib
.lib_OpenCnt
--;
272 return ( (LONG
) libbase
);
275 ULONG __asm
_LibClose(
277 register __a1
struct IORequest
*ior
,
279 register __a6
struct MyLibrary
*libbase
)
283 #ifndef ONE_GLOBAL_SECTION
284 struct MyLibrary
*origbase
;
286 if (libbase
!= libbase
->ml_origbase
)
289 __UserDevCleanup(ior
, libbase
);
291 __UserLibClose(libbase
);
292 __UserLibCleanup(libbase
);
294 __libfpterm(libbase
);
295 origbase
= libbase
->ml_origbase
;
296 FreeMem((char *)libbase
-SIZEJMPTAB
,
297 (long)(MYLIBRARYSIZE
+ ((long)&RESLEN
)+SIZEJMPTAB
));
301 __UserLibClose(libbase
);
303 __UserDevCleanup(ior
, libbase
);
307 if (( --libbase
->ml_Lib
.lib_OpenCnt
== 0 ) &&
308 ( libbase
->ml_Lib
.lib_Flags
& LIBF_DELEXP
))
310 /* no more people have me open,
311 * and I have a delayed expunge pending
313 retval
= _LibExpunge( libbase
); /* return segment list */
319 ULONG __asm
_LibExpunge( register __a6
struct MyLibrary
*libbase
)
324 #ifndef ONE_GLOBAL_SECTION
325 libbase
= libbase
->ml_origbase
;
328 libbase
->ml_Lib
.lib_Flags
|= LIBF_DELEXP
;
329 if ( libbase
->ml_Lib
.lib_OpenCnt
== 0 )
331 /* really expunge: remove libbase and freemem */
332 #ifndef ONE_GLOBAL_SECTION
333 if (libbase
->ml_relocs
)
334 FreeMem(libbase
->ml_relocs
, (*libbase
->ml_relocs
* 4) + 4);
336 __UserLibCleanup(libbase
);
338 seglist
= libbase
->ml_SegList
;
340 Remove( (struct Node
*) libbase
);
342 libsize
= libbase
->ml_Lib
.lib_NegSize
+ libbase
->ml_Lib
.lib_PosSize
;
343 FreeMem( (char *) libbase
- libbase
->ml_Lib
.lib_NegSize
,(LONG
) libsize
);
346 /* return NULL or real seglist */
347 return ( (ULONG
) seglist
);