4 * Revision 13.5 1999/05/14 11:31:34 Michiel
5 * Long filename support implemented; bugfixes
7 * Revision 13.4 1998/09/27 11:26:37 Michiel
10 * Revision 13.3 1998/05/27 20:16:13 Michiel
13 * Revision 13.2 1997/03/03 22:04:04 Michiel
16 * Revision 13.1 1996/03/29 16:57:43 Michiel
17 * Improved Quit() which deals properly with locked and open files
19 * Revision 12.7 1995/11/07 14:51:26 Michiel
20 * call to CheckUpdate added
22 * Revision 12.6 1995/11/02 16:34:59 Michiel
25 * Revision 12.5 1995/10/04 14:05:09 Michiel
26 * using new memorypool functions (from support.c 10.9)
28 * Revision 12.4 1995/09/01 11:17:04 Michiel
29 * ErrorMsg adaption (see disk.c and volume.c)
31 * Revision 12.3 1995/08/21 04:19:40 Michiel
32 * added handler part for MODE_SLEEP
34 * Revision 12.2 1995/08/17 08:46:34 Michiel
35 * adapted to new dostohandlerinterface
37 * Revision 12.1 1995/07/27 12:25:15 Michiel
38 * Using new startup code (in assroutines)
39 * Includes new die function Quit
41 * Revision 10.17 1995/07/11 17:29:31 Michiel
42 * ErrorMsg () calls use messages.c variables now.
44 * Revision 10.16 1995/07/10 04:55:17 Michiel
45 * StackSwap V36 didn't work due to compiler problems.
46 * Now implemented in assembler (AssRoutines.asm)
48 * Revision 10.15 1995/07/07 14:43:08 Michiel
52 * Revision 10.14 1995/06/23 17:26:10 Michiel
53 * added use of global g->action
55 * Revision 10.13 1995/06/23 11:35:46 Michiel
58 * Revision 10.12 1995/06/15 18:56:53 Michiel
61 * Revision 10.11 1995/06/08 15:20:53 Michiel
64 * Revision 10.10 1995/05/20 12:12:12 Michiel
65 * Updated messages to reflect Ami-FileLock
69 * Revision 10.9 1995/03/30 18:56:54 Michiel
70 * Handling of notify reply messages added
72 * Revision 10.8 1995/02/15 16:43:39 Michiel
74 * Using new headers (struct.h & blocks.h)
76 * Revision 10.7 1995/01/18 04:29:34 Michiel
77 * Bugfixes. Now ready for beta release.
79 * Revision 10.6 1994/11/17 15:57:48 Michiel
82 * Revision 10.5 1994/11/15 18:20:08 Michiel
83 * Immediately checks exec version now
85 * Revision 10.4 1994/11/08 11:14:53 Michiel
86 * Applied 9.5.4 fix (timeron/timeout bug)
88 * Revision 10.3 1994/10/29 08:49:24 Michiel
89 * changed process references to msgport references
91 * Revision 10.2 1994/10/27 11:28:24 Michiel
92 * *** empty log message ***
94 * Revision 10.1 1994/10/24 11:16:28 Michiel
98 /* Boot: Het omvattende programma */
101 #include "versionhistory.doc"
105 ** 2 = DosToHandlerInterface
106 ** 3 = Everything dirictly called from DTHI loop
110 #define RES1(p) (p->dp_Res1)
111 #define RES2(p) (p->dp_Res2)
112 #define __USE_SYSBASE
114 #include <exec/types.h>
115 #include <exec/memory.h>
116 #include <exec/alerts.h>
117 #include <exec/tasks.h>
118 #include <exec/execbase.h>
120 #include <dos/dosextens.h>
121 #include <dos/filehandler.h>
122 #include <devices/trackdisk.h>
123 #include <devices/timer.h>
124 #include <proto/dos.h>
125 #include <proto/exec.h>
126 #include <proto/utility.h>
127 #include <proto/intuition.h>
129 #include <libraries/multiuser.h>
130 #include <proto/multiuser.h>
133 #define muFSRendezVous() \
134 LP0(0x6C, BOOL, muFSRendezVous, \
135 , MULTIUSER_BASE_NAME, IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0)
151 #include "directory_protos.h"
152 #include "volume_protos.h"
153 #include "init_protos.h"
154 #include "disk_protos.h"
155 #include "update_protos.h"
156 #include "ass_protos.h"
157 #include "lock_protos.h"
158 #include "lru_protos.h"
161 // extern void __saveds EntryWithNewStack(void);
162 LONG
EntryPoint(struct ExecBase
*);
163 void NormalCommands(struct DosPacket
*, globaldata
*);
164 void HandleSleepMsg (globaldata
*g
);
165 void ReturnPacket(struct DosPacket
*, struct MsgPort
*, globaldata
*);
166 static void Quit(globaldata
*);
170 CONST UBYTE version
[] = "$VER: PFS-III " REVISION
" BETA (" REVDATE
") "
171 "written by Michiel Pelt and copyright (c) 1994-2012 Peltin BV";
174 CONST UBYTE version
[] = "$VER: " "Professional-File-System-III " REVISION
" MULTIUSER-VERSION (" REVDATE
") "
175 "written by Michiel Pelt and copyright (c) 1994-2012 Peltin BV";
177 CONST UBYTE version
[] = "$VER: " "Professional-File-System-III " REVISION
" PROFESSIONAL-VERSION (" REVDATE
") "
178 "written by Michiel Pelt and copyright (c) 1994-2012 Peltin BV";
183 CONST
struct muExtOwner NOBODY
= {0,0,0};
188 static void SetTimer(int, globaldata
*);
191 static BOOL
FindInLibraryList (CONST_STRPTR
, globaldata
*);
194 /**********************************************************************/
196 /**********************************************************************/
198 static UBYTE debugbuf
[120];
199 #define DebugOn debug += 1
200 #define DebugOff debug = 0
201 #define DebugMsg(msg) NormalErrorMsg(msg, NULL)
202 #define DebugMsgNum(msg, num) sprintf(debugbuf, "%s %ld.", msg, num); \
203 if(debug) {NormalErrorMsg(debugbuf, NULL); debug=0;}
204 #define DebugMsgName(msg, name) sprintf(debugbuf, "%s >%s<.", msg, name); \
205 if(debug) {NormalErrorMsg(debugbuf, NULL); debug=0;}
210 #define DebugMsgNum(msg,num)
211 #define DebugMsgName(msg, name)
214 /**********************************************************************/
218 /**********************************************************************/
221 LONG
EntryPoint(struct ExecBase
*SysBase
)
224 struct globaldata
*g
;
225 struct MsgPort
*msgport
;
226 struct DosPacket
*pkt
;
227 struct DeviceNode
*devnode
;
228 struct FileSysStartupMsg
*fssm
;
231 ULONG signal
, dossig
, timesig
, notifysig
, sleepsig
, waitmask
;
233 /* init globaldata */
234 g
= AllocMem (sizeof(struct globaldata
), MEMF_CLEAR
);
240 g
->g_SysBase
= SysBase
;
243 IntuitionBase
= (APTR
)OpenLibrary ("intuition.library", MIN_LIB_VERSION
);
245 UtilityBase
= OpenLibrary ("utility.library",0L);
247 DOSBase
= (struct DosLibrary
*)OpenLibrary ("dos.library", MIN_LIB_VERSION
);
248 msgport
= &((struct Process
*)FindTask (NULL
))->pr_MsgPort
;
257 NormalErrorMsg (AFS_ERROR_LIBRARY_PROBLEM
, NULL
, 1);
261 //DebugMsg("Requester debug enabled");
262 #if KS13WRAPPER_DEBUG
263 DebugPutStr("Waiting for Start-up packet..\n");
265 /* get startpacket */
267 msg
= GetMsg (msgport
);
268 pkt
= (struct DosPacket
*)msg
->mn_Node
.ln_Name
;
270 /* The startpakket contains:
272 * ARG1 = BSTR to mount name
273 * ARG2 = Value from dn_Startup
274 * ARG3 = BPTR to DeviceNode
277 FixStartupPacket(pkt
, g
);
279 mountname
= (UBYTE
*)BADDR(pkt
->dp_Arg1
);
280 fssm
= (struct FileSysStartupMsg
*)BADDR(pkt
->dp_Arg2
);
281 devnode
= (struct DeviceNode
*)BADDR(pkt
->dp_Arg3
);
283 /* Enter Process ID, so that following references
284 * to our handler do not generate new processes
286 devnode
->dn_Task
= msgport
;
288 #if KS13WRAPPER_DEBUG
289 DebugPutStr("Mounting..\n");
291 DB(Trace(1,"boot","g=%lx\n",g
));
292 if (!Initialize ((DSTR
)mountname
, fssm
, devnode
, g
))
294 NormalErrorMsg (AFS_ERROR_INIT_FAILED
, NULL
, 1);
295 if (g
->mountname
) FreeVec (g
->mountname
);
296 if (g
->geom
) FreeMemP (g
->geom
, g
);
297 RES2(pkt
) = ERROR_NOT_A_DOS_DISK
;
298 RES1(pkt
) = DOSFALSE
;
299 ReturnPacket (pkt
, msgport
, g
);
304 #if KS13WRAPPER_DEBUG
305 DebugPutStr("Mount done..\n");
308 g
->DoCommand
= NormalCommands
; //%4.5
311 /* send startuppacket back */
313 ReturnPacket (pkt
, msgport
, g
);
315 /* assuming disk present.. */
317 dossig
= 1 << msgport
->mp_SigBit
;
318 timesig
= 1 << g
->timeport
->mp_SigBit
;
319 notifysig
= 1 << g
->notifyport
->mp_SigBit
;
321 sleepsig
= 1 << g
->sleepport
->mp_SigBit
;
322 waitmask
= sleepsig
| dossig
| timesig
| notifysig
| g
->diskchangesignal
| g
->resethandlersignal
;
324 waitmask
= dossig
| timesig
| notifysig
| g
->diskchangesignal
| g
->resethandlersignal
;
329 g
->muFS_ready
= FALSE
;
334 signal
= Wait (waitmask
);
339 if (FindInLibraryList ((CONST_STRPTR
) "multiuser.library", g
) &&
340 (muBase
= (APTR
)OpenLibrary ("multiuser.library", 39)))
343 g
->muFS_ready
= TRUE
;
348 if (signal
& g
->diskchangesignal
&& g
->inhibitcount
<=0 )
350 //DebugMsg("DISKCHANGE SIGNAL!!");
351 DB(Trace(1, "boot", "DiskChange\n"));
352 NewVolume(TRUE
, g
); /* %10 set to TRUE */
355 if (signal
& timesig
)
357 if ((msg
= GetMsg(g
->timeport
)))
359 if (g
->inhibitcount
== 0)
361 /* postpone until timeoutcounter 'timeout' is 0 */
369 struct idlehandle
*idle
;
372 /* Update disk but wait with turning out motor */
375 for (idle
= HeadOf(&g
->idlelist
); idle
->next
; idle
= idle
->next
)
376 Signal (idle
->task
, 1L<<idle
->dirtysignal
);
380 g
->request
->iotd_Req
.io_Command
= CMD_UPDATE
;
381 DoIO((struct IORequest
*)g
->request
);
384 for (idle
= HeadOf(&g
->idlelist
); idle
->next
; idle
= idle
->next
)
385 Signal (idle
->task
, 1L<<idle
->cleansignal
);
395 while ((msg
= GetMsg(msgport
)))
397 g
->action
= pkt
= (struct DosPacket
*)msg
->mn_Node
.ln_Name
;
399 DB(if(pkt
->dp_Type
!= ACTION_EXAMINE_NEXT
&& pkt
->dp_Type
!= ACTION_IS_FILESYSTEM
))
400 DB(Trace(2, "boot", "Pakket %ld\n", pkt
->dp_Type
));
403 /* get current task owner */
405 g
->user
= muGetTaskExtOwner (pkt
->dp_Port
->mp_SigTask
);
407 g
->user
= (APTR
) &NOBODY
;
409 /* handle the packet */
410 (g
->DoCommand
) (pkt
, g
); //%4.5
412 /* unlock all blocks locked by DoCommand */
416 /* free structure previously allocated by muGetTaskOwner */
418 muFreeExtOwner (g
->user
);
421 if (!g
->timeron
&& (g
->timeout
|| g
->dirty
))
423 /* set timer for first period (always extended) */
428 ReturnPacket (pkt
, msgport
, g
);
429 CheckUpdate (RTBF_CHECK_TH
, g
);
435 if (signal
& notifysig
)
437 struct NotifyMessage
*nmsg
;
438 struct NotifyRequest
*nr
;
440 while ((nmsg
= (struct NotifyMessage
*)GetMsg (g
->notifyport
)))
443 if (nr
->nr_Flags
& NRF_MAGIC
)
445 nr
->nr_Flags
^= NRF_MAGIC
;
446 PutMsg (nr
->nr_stuff
.nr_Msg
.nr_Port
, &nmsg
->nm_ExecMessage
);
450 nmsg
->nm_NReq
->nr_MsgCount
--;
457 if (signal
& sleepsig
)
463 if (signal
& g
->resethandlersignal
)
465 if (g
->inhibitcount
== 0)
467 /* Update pending changes to disk before letting the system to reboot */
471 /* Make sure any disk buffers have been flushed to disk */
472 g
->request
->iotd_Req
.io_Command
= CMD_UPDATE
;
473 DoIO((struct IORequest
*)g
->request
);
475 /* Mark the reset handler as done (system might reboot right after) */
476 HandshakeResetHandler(g
);
487 #define SysBase g->g_SysBase
489 void ReturnPacket (struct DosPacket
*packet
, struct MsgPort
*sender
, globaldata
*g
)
491 struct MsgPort
*rec
= packet
->dp_Port
;
493 packet
->dp_Link
->mn_Node
.ln_Name
= (UBYTE
*)packet
;
494 packet
->dp_Link
->mn_Node
.ln_Succ
= NULL
;
495 packet
->dp_Link
->mn_Node
.ln_Pred
= NULL
;
496 packet
->dp_Port
= sender
;
497 PutMsg (rec
, packet
->dp_Link
);
500 static void SetTimer (int micros
, globaldata
*g
)
502 g
->trequest
->tr_node
.io_Command
= TR_ADDREQUEST
;
503 g
->trequest
->tr_time
.tv_secs
= 0;
504 g
->trequest
->tr_time
.tv_micro
= micros
;
505 SendIO ((struct IORequest
*)g
->trequest
);
509 static BOOL
FindInLibraryList (CONST_STRPTR name
, globaldata
*g
)
513 n
= FindExecNode(EXECLIST_LIBRARY
, name
);
516 n
= FindName(&SysBase
->LibList
, (STRPTR
)name
);
519 return (BOOL
)(n
!= 0);
523 /* When does this routine get called? NOT with 'assign dismount'! */
524 static void Quit (globaldata
*g
)
526 struct volumedata
*volume
;
527 struct NotifyMessage
*nmsg
;
528 struct NotifyRequest
*nr
;
531 // DebugMsg("ACTION_DIE");
537 if (g
->user
->uid
!= muROOT_UID
)
541 //DebugPutStr("Removing volume..\n");
543 volume
= g
->currentvolume
;
545 DiskRemoveSequence(g
);
547 //DebugPutStr("Uninstalling ResetHandler..\n");
548 UninstallResetHandler(g
);
550 //DebugPutStr("Uninstalling DiskChangeHandler..\n");
551 /* remove diskchangehandler */
552 UninstallDiskChangeHandler(g
);
555 /* wait for wb to return locks */
559 //DebugPutStr("Answering queued packets\n");
560 /* check if packets queued */
561 while ((msg
= GetMsg(g
->msgport
)))
563 g
->action
= (struct DosPacket
*)msg
->mn_Node
.ln_Name
;
564 g
->action
->dp_Res1
= DOSFALSE
;
565 g
->action
->dp_Res2
= ERROR_DEVICE_NOT_MOUNTED
;
566 ReturnPacket (g
->action
, g
->msgport
, g
);
569 //DebugPutStr("Answering queued notifications\n");
570 /* check if notifypackets queued */
571 while ((nmsg
= (struct NotifyMessage
*)GetMsg (g
->notifyport
)))
574 if (nr
->nr_Flags
& NRF_MAGIC
)
576 nr
->nr_Flags
^= NRF_MAGIC
;
577 PutMsg (nr
->nr_stuff
.nr_Msg
.nr_Port
, &nmsg
->nm_ExecMessage
);
581 nmsg
->nm_NReq
->nr_MsgCount
--;
586 //DebugPutStr("Forbid()..\n");
590 /* remove devicenode */
591 RemDosEntry ((struct DosList
*)g
->devnode
);
592 // FreeDosEntry ((struct DosList *)g->devnode);
594 //DebugPutStr("Freeing timer request\n");
595 /* cleanup timer device (OK) */
596 /* FreeSignal wil even niet..(signalnr!) */
597 if(!(CheckIO((struct IORequest
*)g
->trequest
)))
598 AbortIO((struct IORequest
*)g
->trequest
);
599 WaitIO((struct IORequest
*)g
->trequest
);
600 CloseDevice((struct IORequest
*)g
->trequest
);
601 DeleteIORequest((struct IORequest
*)g
->trequest
);
602 DeleteMsgPort(g
->timeport
);
604 //DebugPutStr("Freeing device request\n");
605 /* clean up device */
606 if(!(CheckIO((struct IORequest
*)g
->request
)))
607 AbortIO((struct IORequest
*)g
->request
);
608 WaitIO((struct IORequest
*)g
->request
);
609 CloseDevice((struct IORequest
*)g
->request
);
610 DeleteIORequest((struct IORequest
*)g
->request
);
611 DeleteMsgPort(g
->port
);
613 //DebugPutStr("Freeing ports\n");
614 DeleteMsgPort(g
->notifyport
);
616 DeleteMsgPort(g
->sleepport
);
619 //DebugPutStr("Freeing misc structures\n");
620 FreeVec (g
->mountname
);
621 FreeMemP (g
->geom
, g
);
623 FreeVec (g
->dc
.data
);
625 if (alloc_data
.reservedtobefreed
)
626 FreeMem (alloc_data
.reservedtobefreed
, sizeof(*alloc_data
.reservedtobefreed
) * alloc_data
.rtbf_size
);
628 //DebugPutStr("Permit()\n");
632 /* wait 'till all locks freed */
633 while (volume
&& !IsMinListEmpty(&volume
->fileentries
))
635 listentry_t
*listentry
;
637 //DebugPutStr("Locks still remaining... Waiting..\n");
638 Wait (1 << g
->msgport
->mp_SigBit
);
639 msg
= GetMsg (g
->msgport
);
640 g
->action
= (struct DosPacket
*)msg
->mn_Node
.ln_Name
;
641 if (g
->action
->dp_Type
== ACTION_FREE_LOCK
)
643 listentry
= ListEntryFromLock (g
->action
->dp_Arg1
);
645 RemoveListEntry (listentry
, g
);
646 g
->action
->dp_Res1
= DOSTRUE
;
648 else if (g
->action
->dp_Type
== ACTION_END
)
650 listentry
= (listentry_t
*)g
->action
->dp_Arg1
;
652 RemoveListEntry (listentry
, g
);
653 g
->action
->dp_Res1
= DOSTRUE
;
657 g
->action
->dp_Res1
= DOSFALSE
;
658 g
->action
->dp_Res2
= ERROR_DEVICE_NOT_MOUNTED
;
661 ReturnPacket (g
->action
, g
->msgport
, g
);
663 //DebugPutStr("All locks freed.\n");
665 g
->devnode
->dn_Task
= NULL
;
668 LibDeletePool (g
->bufferPool
);
669 LibDeletePool (g
->mainPool
);
673 CloseLibrary((struct Library
*) muBase
);
676 CloseLibrary(UtilityBase
);
678 CloseLibrary((struct Library
*) DOSBase
);
679 CloseLibrary((struct Library
*) IntuitionBase
);
683 FreeMem (g
, sizeof(struct globaldata
));
690 LONG
AROSEntryPoint(struct ExecBase
*SysBase
)
693 #if KS13WRAPPER_DEBUG
694 DebugPutStr("PFS3 starting..\n");
696 return wrapper_stackswap(EntryPoint
, SysBase
);
698 return EntryPoint(SysBase
);
702 LONG __saveds __startup
Main(void)
704 return EntryPoint(*(struct ExecBase
**)4L);