Initialize lib_OpenCnt of DOS.
[AROS.git] / rom / dos / dos_init.c
blob2b3153651393de52d3ef8329fd64a188abb0538a
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Header for dos.library
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/execbase.h>
11 #include <exec/libraries.h>
12 #include <exec/memory.h>
13 #include <exec/resident.h>
14 #include <proto/exec.h>
15 #include <aros/symbolsets.h>
16 #include <dos/dosextens.h>
17 #include <dos/dostags.h>
18 #include <proto/dos.h>
19 #include <proto/alib.h>
20 #include <proto/utility.h>
21 #include <proto/partition.h>
22 #include <utility/tagitem.h>
23 #include <resources/filesysres.h>
25 #include LC_LIBDEFS_FILE
27 #include "dos_intern.h"
29 static const UBYTE version[];
30 extern const char LIBEND;
32 AROS_UFP3S(struct DosLibrary *, DosInit,
33 AROS_UFPA(ULONG, dummy, D0),
34 AROS_UFPA(BPTR, segList, A0),
35 AROS_UFPA(struct ExecBase *, SysBase, A6));
37 const struct Resident Dos_resident =
39 RTC_MATCHWORD,
40 (struct Resident *)&Dos_resident,
41 (APTR)&LIBEND,
42 0, /* We don't autoinit */
43 VERSION_NUMBER,
44 NT_LIBRARY,
45 RESIDENTPRI,
46 MOD_NAME_STRING,
47 (STRPTR)&version[6],
48 DosInit
51 static const UBYTE version[] = VERSION_STRING;
53 extern const ULONG err_Numbers[];
54 extern const char err_Strings[];
56 static void DosExpunge(struct DosLibrary *DOSBase);
58 extern const APTR GM_UNIQUENAME(FuncTable)[];
60 THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)
61 THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)
62 THIS_PROGRAM_HANDLES_SYMBOLSET(INITLIB)
63 THIS_PROGRAM_HANDLES_SYMBOLSET(EXPUNGELIB)
64 DEFINESET(INIT)
65 DEFINESET(EXIT)
66 DEFINESET(INITLIB)
67 DEFINESET(EXPUNGELIB)
69 static void init_fs(struct DosLibrary *DOSBase)
71 struct FileSysResource *fsr;
72 struct Library *PartitionBase;
74 PartitionBase = OpenLibrary("partition.library", 3);
75 if (PartitionBase) {
76 LoadBootFileSystems();
77 CloseLibrary(PartitionBase);
81 * Set dl_Root->rn_FileHandlerSegment to the AFS handler,
82 * if it's been loaded. Otherwise, use the first handler
83 * on the FileSystemResource list that has fse_PatchFlags
84 * set to mark it with a valid SegList
86 if ((fsr = OpenResource("FileSystem.resource")))
88 struct FileSysEntry *fse;
89 BPTR defseg = BNULL;
90 const ULONG DosMagic = 0x444f5301; /* DOS\001 */
92 ForeachNode(&fsr->fsr_FileSysEntries, fse)
94 if ((fse->fse_PatchFlags & FSEF_SEGLIST) && fse->fse_SegList)
96 /* We prefer DOS\001 */
97 if (fse->fse_DosType == DosMagic)
99 defseg = fse->fse_SegList;
100 break;
102 /* This will remember the first defined seglist */
103 if (!defseg)
104 defseg = fse->fse_SegList;
107 DOSBase->dl_Root->rn_FileHandlerSegment = defseg;
108 /* Add all that have both Handler and SegList defined to the Resident list */
109 ForeachNode(&fsr->fsr_FileSysEntries, fse)
111 if ((fse->fse_PatchFlags & FSEF_HANDLER) &&
112 (fse->fse_PatchFlags & FSEF_SEGLIST) &&
113 (fse->fse_Handler != BNULL) &&
114 (fse->fse_SegList != BNULL))
116 D(bug("[DosInit] Adding \"%b\" (%p) at %p to the resident list\n",
117 fse->fse_Handler, BADDR(fse->fse_Handler), BADDR(fse->fse_SegList)));
118 AddSegment(AROS_BSTR_ADDR(fse->fse_Handler), fse->fse_SegList, CMD_SYSTEM);
125 * Init routine is intentionally written by hands in order to be reentrant.
126 * Reentrancy is needed when there are already some devices mounted, but
127 * all of them are not bootable. And now we insert a floppy with OS3.1
128 * bootblock. It reenters this function...
131 AROS_UFH3S(struct DosLibrary *, DosInit,
132 AROS_UFHA(ULONG, dummy, D0),
133 AROS_UFHA(BPTR, segList, A0),
134 AROS_UFHA(struct ExecBase *, sysBase, A6)
137 AROS_USERFUNC_INIT
139 struct DosLibrary *DOSBase;
141 if (!SysBase)
142 SysBase = sysBase;
144 if (!set_call_funcs(SETNAME(INIT), 1, 1))
145 return NULL;
147 DOSBase = (struct DosLibrary *)FindName(&SysBase->LibList, "dos.library");
149 D(bug("[DosInit] DOSBase 0x%p\n", DOSBase));
151 if (!DOSBase)
153 IPTR *taskarray;
154 struct DosInfo *dosinfo;
156 D(bug("[DosInit] Creating dos.library...\n"));
158 DOSBase = (struct DosLibrary *)MakeLibrary(GM_UNIQUENAME(FuncTable), NULL, NULL, sizeof(struct IntDosBase), BNULL);
159 if (!DOSBase)
160 return NULL;
162 /* Initialize our header */
163 DOSBase->dl_lib.lib_Node.ln_Name = MOD_NAME_STRING;
164 DOSBase->dl_lib.lib_Node.ln_Type = NT_LIBRARY;
165 DOSBase->dl_lib.lib_Node.ln_Pri = RESIDENTPRI;
166 DOSBase->dl_lib.lib_Version = VERSION_NUMBER;
167 DOSBase->dl_lib.lib_Revision = REVISION_NUMBER;
168 DOSBase->dl_lib.lib_IdString = (char *)&version[6];
169 DOSBase->dl_lib.lib_Flags = LIBF_SUMUSED|LIBF_CHANGED;
170 DOSBase->dl_lib.lib_OpenCnt = 0;
173 * These two are allocated together with DOSBase, for reduced fragmentation.
174 * Structure pointed to by dl_Errors is intentionally read-write - who knows...
176 DOSBase->dl_Root = &((struct IntDosBase *)DOSBase)->rootNode;
177 DOSBase->dl_Errors = &((struct IntDosBase *)DOSBase)->errors;
179 DOSBase->dl_Errors->estr_Nums = (LONG *)err_Numbers;
180 DOSBase->dl_Errors->estr_Strings = (STRPTR)err_Strings;
182 /* Init the RootNode structure */
183 dosinfo = AllocMem(sizeof(struct DosInfo), MEMF_PUBLIC|MEMF_CLEAR);
184 if (!dosinfo)
186 DosExpunge(DOSBase);
187 return NULL;
190 DOSBase->dl_Root->rn_Info = MKBADDR(dosinfo);
192 taskarray = AllocMem(sizeof(IPTR) + sizeof(APTR) * 20, MEMF_CLEAR);
193 if (!taskarray)
195 DosExpunge(DOSBase);
196 return NULL;
199 taskarray[0] = 20;
200 DOSBase->dl_Root->rn_TaskArray = MKBADDR(taskarray);
202 NEWLIST((struct List *)&DOSBase->dl_Root->rn_CliList);
203 InitSemaphore(&DOSBase->dl_Root->rn_RootLock);
205 InitSemaphore(&dosinfo->di_DevLock);
206 InitSemaphore(&dosinfo->di_EntryLock);
207 InitSemaphore(&dosinfo->di_DeleteLock);
209 /* Initialize for Stricmp */
210 DOSBase->dl_UtilityBase = TaggedOpenLibrary(TAGGEDOPEN_UTILITY);
211 if (!DOSBase->dl_UtilityBase)
213 DosExpunge(DOSBase);
214 return NULL;
217 /* Initialize for the fools that illegally used this field */
218 DOSBase->dl_IntuitionBase = TaggedOpenLibrary(TAGGEDOPEN_INTUITION);
221 * iaint:
222 * I know this is bad, but I also know that the timer.device
223 * will never go away during the life of dos.library. I also
224 * don't intend to make any I/O calls using this.
226 * I also know that timer.device does exist in the device list
227 * at this point in time.
229 * I can't allocate a timerequest/MsgPort pair here anyway,
230 * because I need a separate one for each caller to Delay().
231 * However, CreateIORequest() will fail if MsgPort == NULL, so we
232 * supply some dummy value.
234 DOSBase->dl_TimeReq = CreateIORequest((APTR)0xC0DEBAD0, sizeof(struct timerequest));
235 if (!DOSBase->dl_TimeReq)
237 DosExpunge(DOSBase);
238 return NULL;
241 if (OpenDevice("timer.device", UNIT_VBLANK, &DOSBase->dl_TimeReq->tr_node, 0))
243 DeleteIORequest(DOSBase->dl_TimeReq);
244 DOSBase->dl_TimeReq = NULL;
245 DosExpunge(DOSBase);
246 return NULL;
249 /* Call platform-specific init code (if any) */
250 if (!set_call_libfuncs(SETNAME(INITLIB), 1, 1, DOSBase))
252 DosExpunge(DOSBase);
253 return NULL;
256 /* debug.library is optional, so don't check result */
257 DebugBase = OpenLibrary("debug.library", 0);
259 /* Initialization finished */
260 AddLibrary(&DOSBase->dl_lib);
262 init_fs(DOSBase);
265 /* Try to boot */
266 if (CliInit(NULL) == RETURN_OK)
269 * We now restart the multitasking - this is done
270 * automatically by RemTask() when it switches.
272 RemTask(NULL);
274 /* We really really shouldn't ever get to this line. */
277 DosExpunge(DOSBase);
278 return NULL;
280 AROS_USERFUNC_EXIT
283 static void DosExpunge(struct DosLibrary *DOSBase)
285 struct DosInfo *dinfo = BADDR(DOSBase->dl_Root->rn_Info);
286 struct Segment *seg, *stmp;
288 D(bug("[DosInit] Expunge...\n"));
290 /* If we have anything in the Dos List,
291 * we can't die.
293 if (dinfo->di_DevInfo != BNULL)
295 #if DEBUG
296 struct DosList *dol;
298 bug("[DosInit] Entries still in the Dos List, can't expunge.\n");
299 for (dol = BADDR(dinfo->di_DevInfo); dol != NULL; dol = BADDR(dol->dol_Next))
301 bug("[DosInit] %d '%b'\n", dol->dol_Type, dol->dol_Name);
303 #endif
304 return;
307 if (DOSBase->dl_lib.lib_OpenCnt)
310 * Someone is holding us... Perhaps some handler started subprocess
311 * which didn't quit. Who knows...
313 D(bug("[DosInit] Open count is %d, can't expunge\n", DOSBase->dl_lib.lib_OpenCnt));
314 return;
317 /* Call platform-specific expunge code (if any) */
318 if (!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, DOSBase))
320 D(bug("[DosInit] Platform-dependent code failed to expunge\n"));
321 return;
324 /* Close some libraries */
325 CloseLibrary(DebugBase);
326 CloseLibrary((APTR)DOSBase->dl_IntuitionBase);
327 CloseLibrary((APTR)DOSBase->dl_UtilityBase);
329 /* Free the timer device */
330 if (DOSBase->dl_TimeReq)
332 CloseDevice(&DOSBase->dl_TimeReq->tr_node);
333 DeleteIORequest(DOSBase->dl_TimeReq);
336 if (dinfo)
338 /* Remove all segments */
339 for (seg = BADDR(dinfo->di_ResList); seg != NULL; seg = stmp)
341 stmp = BADDR(seg->seg_Next);
342 FreeVec(seg);
344 FreeMem(dinfo, sizeof(*dinfo));
347 /* Free memory */
348 FreeMem(BADDR(DOSBase->dl_Root->rn_TaskArray), sizeof(IPTR) + sizeof(APTR) * 20);
350 if (DOSBase->dl_lib.lib_Node.ln_Succ)
353 * A fresh DOSBase after creation is filled with NULLs.
354 * ln_Succ will be set to something only after AddLibrary().
356 Remove(&DOSBase->dl_lib.lib_Node);
359 FreeMem((char *)DOSBase - DOSBase->dl_lib.lib_NegSize, DOSBase->dl_lib.lib_NegSize + DOSBase->dl_lib.lib_PosSize);
361 set_call_funcs(SETNAME(EXIT), -1, 0);
363 D(bug("%s: Expunged.\n", __func__));
367 * Simple open and close routines.
368 * We never auto-expunge, because if we ever do this,
369 * we won't be able to come up again. BTW, LDDemon constantly holds us open,
370 * so we always have at least one user.
372 AROS_LH1(struct DosLibrary *, OpenLib,
373 AROS_LHA(ULONG, version, D0),
374 struct DosLibrary *, DOSBase, 1, Dos)
376 AROS_LIBFUNC_INIT
378 /* I have one more opener. */
379 DOSBase->dl_lib.lib_OpenCnt++;
380 return DOSBase;
382 AROS_LIBFUNC_EXIT
385 AROS_LH0(BPTR, CloseLib,
386 struct DosLibrary *, DOSBase, 2, Dos)
388 AROS_LIBFUNC_INIT
390 /* I have one fewer opener. */
391 DOSBase->dl_lib.lib_OpenCnt--;
392 return BNULL;
394 AROS_LIBFUNC_EXIT