2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Header for dos.library
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
=
40 (struct Resident
*)&Dos_resident
,
42 0, /* We don't autoinit */
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
)
69 static void init_fs(struct DosLibrary
*DOSBase
)
71 struct FileSysResource
*fsr
;
72 struct Library
*PartitionBase
;
74 PartitionBase
= OpenLibrary("partition.library", 3);
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
;
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
;
102 /* This will remember the first defined seglist */
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
)
139 struct DosLibrary
*DOSBase
;
144 if (!set_call_funcs(SETNAME(INIT
), 1, 1))
147 DOSBase
= (struct DosLibrary
*)FindName(&SysBase
->LibList
, "dos.library");
149 D(bug("[DosInit] DOSBase 0x%p\n", DOSBase
));
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
);
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
);
190 DOSBase
->dl_Root
->rn_Info
= MKBADDR(dosinfo
);
192 taskarray
= AllocMem(sizeof(IPTR
) + sizeof(APTR
) * 20, MEMF_CLEAR
);
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
)
217 /* Initialize for the fools that illegally used this field */
218 DOSBase
->dl_IntuitionBase
= TaggedOpenLibrary(TAGGEDOPEN_INTUITION
);
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
)
241 if (OpenDevice("timer.device", UNIT_VBLANK
, &DOSBase
->dl_TimeReq
->tr_node
, 0))
243 DeleteIORequest(DOSBase
->dl_TimeReq
);
244 DOSBase
->dl_TimeReq
= NULL
;
249 /* Call platform-specific init code (if any) */
250 if (!set_call_libfuncs(SETNAME(INITLIB
), 1, 1, DOSBase
))
256 /* debug.library is optional, so don't check result */
257 DebugBase
= OpenLibrary("debug.library", 0);
259 /* Initialization finished */
260 AddLibrary(&DOSBase
->dl_lib
);
266 if (CliInit(NULL
) == RETURN_OK
)
269 * We now restart the multitasking - this is done
270 * automatically by RemTask() when it switches.
274 /* We really really shouldn't ever get to this line. */
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,
293 if (dinfo
->di_DevInfo
!= BNULL
)
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
);
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
));
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"));
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
);
338 /* Remove all segments */
339 for (seg
= BADDR(dinfo
->di_ResList
); seg
!= NULL
; seg
= stmp
)
341 stmp
= BADDR(seg
->seg_Next
);
344 FreeMem(dinfo
, sizeof(*dinfo
));
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
)
378 /* I have one more opener. */
379 DOSBase
->dl_lib
.lib_OpenCnt
++;
385 AROS_LH0(BPTR
, CloseLib
,
386 struct DosLibrary
*, DOSBase
, 2, Dos
)
390 /* I have one fewer opener. */
391 DOSBase
->dl_lib
.lib_OpenCnt
--;