Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / AHI / Toccata / libinit.c
blob44c4f1438ff5fd2a6fe65f10d1ebaefa747523dd
1 /*
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,
18 MA 02139, USA.
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>
32 #include <string.h>
34 long _WBenchMsg;
36 /* Prototypes */
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);
56 struct MyLibrary {
57 struct Library ml_Lib;
58 APTR ml_BoardAddress; /* Toccata */
59 APTR ml_HardInfo; /* Toccata */
60 ULONG ml_SegList;
61 ULONG ml_Flags;
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 */
66 long ml_numjmps;
67 #endif
70 typedef LONG (*myPFL)(); /* pointer to function returning 32-bit int */
72 /* library initialization table, used for AUTOINIT libraries */
73 struct InitTable {
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
81 long _WBenchMsg;
82 long _OSERR;
83 long __base;
84 #endif
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),
110 _LibFuncTab,
111 NULL, /* will initialize my own data */
112 _LibInit,
115 __asm ULONG _LibInit( register __a0 APTR seglist,
116 register __d0 struct MyLibrary *libbase )
118 #ifdef ONE_GLOBAL_SECTION
119 long *reloc;
120 #endif
121 long *sdata;
122 char *ddata;
123 long nrelocs;
126 libbase->ml_SegList = (ULONG) seglist;
128 /* init. library structure (since I don't do automatic data init.) */
129 #ifdef DEVICE
130 libbase->ml_Lib.lib_Node.ln_Type = NT_DEVICE;
131 #else
132 libbase->ml_Lib.lib_Node.ln_Type = NT_LIBRARY;
133 #endif
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;
144 #endif
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;
155 nrelocs = *sdata;
156 #ifdef ONE_GLOBAL_SECTION
157 sdata++;
158 while (nrelocs > 0)
160 reloc = (long *)((long)ddata + *sdata++);
161 *reloc += (long)ddata;
162 nrelocs--;
165 #ifndef DEVICE
166 if (__UserLibInit(libbase) != 0)
167 return NULL; /* abort if user init failed */
168 #endif
170 #else
171 if (nrelocs)
173 if ((libbase->ml_relocs = AllocMem((nrelocs * 4) + 4, MEMF_PUBLIC)) == NULL)
174 return 0;
175 memcpy((void *)libbase->ml_relocs, (void *)sdata, (nrelocs * 4) + 4);
177 #endif
179 return ( (ULONG) libbase );
182 LONG __asm _LibOpen(
183 #ifdef DEVICE
184 register __d0 long unit,
185 register __a1 struct IORequest *ior,
186 #endif
187 register __a6 struct MyLibrary *libbase )
189 #ifndef ONE_GLOBAL_SECTION
190 struct MyLibrary *origbase = libbase;
191 struct ExecBase *SysBase = *(struct ExecBase **)4;
192 char *newlib;
193 long *sdata, *ddata, *reloc;
194 long nrelocs;
195 #endif
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;
211 /* copy over data */
212 memcpy(newlib, (char *)libbase - SIZEJMPTAB,
213 (long)(MYLIBRARYSIZE + DATAWORDS*4 + SIZEJMPTAB));
215 libbase = (struct MyLibrary *)(newlib+SIZEJMPTAB);
216 libbase->ml_relocs = NULL;
218 /* perform relocs */
219 ddata = (long *)((char *)libbase + MYLIBRARYSIZE);
220 sdata = libbase->ml_origbase->ml_relocs;
221 if (sdata)
223 nrelocs = *sdata++;
224 while (nrelocs > 0)
226 reloc = (long *)((long)ddata + *sdata++);
227 *reloc += (long)ddata;
228 nrelocs--;
232 /* now we need to flush the cache because we copied the jmp table */
233 if (SysBase->LibNode.lib_Version >= 36)
234 CacheClearU();
236 #ifdef DEVICE
237 ior->io_Device = (struct Device *)libbase; /* local copy of libary base */
238 #endif
240 if (__libfpinit(libbase) ||
241 #ifdef DEVICE
242 __UserDevInit(unit, ior, libbase) != 0
243 #else
244 (__UserLibInit(libbase) != 0) ||
245 __UserLibOpen(libbase) != 0)
246 #endif
249 __libfpterm(libbase);
250 FreeMem(newlib, (long)(MYLIBRARYSIZE +
251 ((long)&RESLEN) + SIZEJMPTAB));
252 error:
253 origbase->ml_origbase->ml_Lib.lib_OpenCnt--;
254 return NULL; /* abort if user init failed */
257 #else
258 #ifdef DEVICE
259 if (__UserDevInit(unit, ior, libbase) != 0)
261 libbase->ml_Lib.lib_OpenCnt--;
262 return NULL;
264 #endif
265 if (__UserLibOpen(libbase) != 0)
267 libbase->ml_Lib.lib_OpenCnt--;
268 return NULL;
270 #endif
272 return ( (LONG) libbase );
275 ULONG __asm _LibClose(
276 #ifdef DEVICE
277 register __a1 struct IORequest *ior,
278 #endif
279 register __a6 struct MyLibrary *libbase )
281 ULONG retval = 0;
283 #ifndef ONE_GLOBAL_SECTION
284 struct MyLibrary *origbase;
286 if (libbase != libbase->ml_origbase)
288 #ifdef DEVICE
289 __UserDevCleanup(ior, libbase);
290 #else
291 __UserLibClose(libbase);
292 __UserLibCleanup(libbase);
293 #endif
294 __libfpterm(libbase);
295 origbase = libbase->ml_origbase;
296 FreeMem((char *)libbase-SIZEJMPTAB,
297 (long)(MYLIBRARYSIZE + ((long)&RESLEN)+SIZEJMPTAB));
298 libbase = origbase;
300 #else
301 __UserLibClose(libbase);
302 #ifdef DEVICE
303 __UserDevCleanup(ior, libbase);
304 #endif
305 #endif
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 */
316 return (retval);
319 ULONG __asm _LibExpunge( register __a6 struct MyLibrary *libbase )
321 ULONG seglist = 0;
322 LONG libsize;
324 #ifndef ONE_GLOBAL_SECTION
325 libbase = libbase->ml_origbase;
326 #endif
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);
335 #else
336 __UserLibCleanup(libbase);
337 #endif
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 );