Added a test for MUIA_Listview_SelectChange.
[AROS.git] / rom / filesys / pfs3 / fs / boot.c
blob068f333d6e52ca48f20e247d6a69deeadbc60b16
2 /* $Id$ */
3 /* $Log: boot.c $
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
8 * Beta version string
10 * Revision 13.3 1998/05/27 20:16:13 Michiel
11 * AFS --> PFS2
13 * Revision 13.2 1997/03/03 22:04:04 Michiel
14 * Release 16.21
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
23 * -- version 16.2
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
49 * LITE stuff and
50 * Stackswap for V36
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
56 * multiuser stuff
58 * Revision 10.12 1995/06/15 18:56:53 Michiel
59 * pooled mem
61 * Revision 10.11 1995/06/08 15:20:53 Michiel
62 * multiuser changes
64 * Revision 10.10 1995/05/20 12:12:12 Michiel
65 * Updated messages to reflect Ami-FileLock
66 * CUTDOWN version
67 * protection update
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
73 * Release version
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
80 * Beta2
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
95 * first RCS revision
96 * */
98 /* Boot: Het omvattende programma */
99 //#define DEBUG 1
101 #include "versionhistory.doc"
103 /* LEVELS:
104 ** 1 = Boot.c
105 ** 2 = DosToHandlerInterface
106 ** 3 = Everything dirictly called from DTHI loop
107 ** 4 = Higher
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>
119 #include <dos/dos.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>
128 #if MULTIUSER
129 #include <libraries/multiuser.h>
130 #include <proto/multiuser.h>
131 #endif
132 #ifdef __MORPHOS__
133 #define muFSRendezVous() \
134 LP0(0x6C, BOOL, muFSRendezVous, \
135 , MULTIUSER_BASE_NAME, IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0)
136 #endif
138 #ifdef __SASC
139 #include <dos.h>
140 #endif
141 #include <stdio.h>
142 #include <string.h>
143 #include "debug.h"
145 #ifdef DEBUG
146 BOOL debug=FALSE;
147 #endif
149 #include "blocks.h"
150 #include "struct.h"
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"
160 /* protos */
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 *);
168 /* vars */
169 #ifdef BETAVERSION
170 CONST UBYTE version[] = "$VER: PFS-III " REVISION " BETA (" REVDATE ") "
171 "written by Michiel Pelt and copyright (c) 1994-2012 Peltin BV";
172 #else
173 #if MULTIUSER
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";
176 #else
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";
179 #endif
180 #endif
182 #if MULTIUSER
183 CONST struct muExtOwner NOBODY = {0,0,0};
184 #endif
187 /* proto */
188 static void SetTimer(int, globaldata *);
190 #if MULTIUSER
191 static BOOL FindInLibraryList (CONST_STRPTR, globaldata *);
192 #endif
194 /**********************************************************************/
195 /* DEBUG */
196 /**********************************************************************/
197 #ifdef DEBUG
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;}
206 #else
207 #define DebugOn
208 #define DebugOff
209 #define DebugMsg(m)
210 #define DebugMsgNum(msg,num)
211 #define DebugMsgName(msg, name)
212 #endif
214 /**********************************************************************/
215 /* MAIN */
216 /* MAIN */
217 /* MAIN */
218 /**********************************************************************/
219 #undef SysBase
221 LONG EntryPoint(struct ExecBase *SysBase)
223 /* globals */
224 struct globaldata *g;
225 struct MsgPort *msgport;
226 struct DosPacket *pkt;
227 struct DeviceNode *devnode;
228 struct FileSysStartupMsg *fssm;
229 struct Message *msg;
230 UBYTE *mountname;
231 ULONG signal, dossig, timesig, notifysig, sleepsig, waitmask;
233 /* init globaldata */
234 g = AllocMem (sizeof(struct globaldata), MEMF_CLEAR);
235 if (!g)
237 Alert (AG_NoMemory);
238 Wait (0);
240 g->g_SysBase = SysBase;
242 /* open libs */
243 IntuitionBase = (APTR)OpenLibrary ("intuition.library", MIN_LIB_VERSION);
244 #ifndef KS13WRAPPER
245 UtilityBase = OpenLibrary ("utility.library",0L);
246 #endif
247 DOSBase = (struct DosLibrary *)OpenLibrary ("dos.library", MIN_LIB_VERSION);
248 msgport = &((struct Process *)FindTask (NULL))->pr_MsgPort;
250 if (
251 !IntuitionBase ||
252 #ifndef KS13WRAPPER
253 !UtilityBase ||
254 #endif
255 !DOSBase)
257 NormalErrorMsg (AFS_ERROR_LIBRARY_PROBLEM, NULL, 1);
258 Wait (0);
261 //DebugMsg("Requester debug enabled");
262 #if KS13WRAPPER_DEBUG
263 DebugPutStr("Waiting for Start-up packet..\n");
264 #endif
265 /* get startpacket */
266 WaitPort (msgport);
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
276 #ifdef KS13WRAPPER
277 FixStartupPacket(pkt, g);
278 #endif
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");
290 #endif
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);
300 FreeVec (g);
301 return RETURN_FAIL;
304 #if KS13WRAPPER_DEBUG
305 DebugPutStr("Mount done..\n");
306 #endif
308 g->DoCommand = NormalCommands; //%4.5
309 g->inhibitcount = 0;
311 /* send startuppacket back */
312 RES1(pkt) = DOSTRUE;
313 ReturnPacket (pkt, msgport, g);
315 /* assuming disk present.. */
316 NewVolume (TRUE, g);
317 dossig = 1 << msgport->mp_SigBit;
318 timesig = 1 << g->timeport->mp_SigBit;
319 notifysig = 1 << g->notifyport->mp_SigBit;
320 #if EXTRAPACKETS
321 sleepsig = 1 << g->sleepport->mp_SigBit;
322 waitmask = sleepsig | dossig | timesig | notifysig | g->diskchangesignal | g->resethandlersignal;
323 #else
324 waitmask = dossig | timesig | notifysig | g->diskchangesignal | g->resethandlersignal;
325 #endif
326 g->timeout = 0;
328 #if MULTIUSER
329 g->muFS_ready = FALSE;
330 #endif
332 while (1)
334 signal = Wait (waitmask);
336 #if MULTIUSER
337 if (!g->muFS_ready)
339 if (FindInLibraryList ((CONST_STRPTR) "multiuser.library", g) &&
340 (muBase = (APTR)OpenLibrary ("multiuser.library", 39)))
342 muFSRendezVous ();
343 g->muFS_ready = TRUE;
346 #endif
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 */
362 if (g->timeout)
364 SetTimer(700000, g);
365 g->timeout--;
367 else
369 struct idlehandle *idle;
370 if (g->dirty)
372 /* Update disk but wait with turning out motor */
373 UpdateDisk(g);
374 SetTimer(200000, g);
375 for (idle = HeadOf(&g->idlelist); idle->next; idle = idle->next)
376 Signal (idle->task, 1L<<idle->dirtysignal);
378 else
380 g->request->iotd_Req.io_Command = CMD_UPDATE;
381 DoIO((struct IORequest *)g->request);
382 MotorOff(g);
383 g->timeron = FALSE;
384 for (idle = HeadOf(&g->idlelist); idle->next; idle = idle->next)
385 Signal (idle->task, 1L<<idle->cleansignal);
393 if (signal & dossig)
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));
402 #if MULTIUSER
403 /* get current task owner */
404 if (g->muFS_ready)
405 g->user = muGetTaskExtOwner (pkt->dp_Port->mp_SigTask);
406 else
407 g->user = (APTR) &NOBODY;
408 #endif
409 /* handle the packet */
410 (g->DoCommand) (pkt, g); //%4.5
412 /* unlock all blocks locked by DoCommand */
413 UNLOCKALL();
415 #if MULTIUSER
416 /* free structure previously allocated by muGetTaskOwner */
417 if (g->muFS_ready)
418 muFreeExtOwner (g->user);
419 #endif
421 if (!g->timeron && (g->timeout || g->dirty))
423 /* set timer for first period (always extended) */
424 SetTimer(200000, g);
425 g->timeron = TRUE;
428 ReturnPacket (pkt, msgport, g);
429 CheckUpdate (RTBF_CHECK_TH, g);
430 if (g->dieing)
431 goto terminate;
435 if (signal & notifysig)
437 struct NotifyMessage *nmsg;
438 struct NotifyRequest *nr;
440 while ((nmsg = (struct NotifyMessage *)GetMsg (g->notifyport)))
442 nr = nmsg->nm_NReq;
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);
448 else
450 nmsg->nm_NReq->nr_MsgCount--;
451 FreeMemP (nmsg, g);
456 #if EXTRAPACKETS
457 if (signal & sleepsig)
459 HandleSleepMsg (g);
461 #endif
463 if (signal & g->resethandlersignal)
465 if (g->inhibitcount == 0)
467 /* Update pending changes to disk before letting the system to reboot */
468 UpdateDisk(g);
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);
480 terminate:
482 Quit (g);
484 return RETURN_OK;
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);
508 #if MULTIUSER
509 static BOOL FindInLibraryList (CONST_STRPTR name, globaldata *g)
511 struct Node *n;
512 #ifdef __MORPHOS__
513 n = FindExecNode(EXECLIST_LIBRARY, name);
514 #else
515 Forbid();
516 n = FindName(&SysBase->LibList, (STRPTR)name);
517 Permit();
518 #endif
519 return (BOOL)(n != 0);
521 #endif
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;
529 struct Message *msg;
531 // DebugMsg("ACTION_DIE");
532 ENTER("dd_Quit");
534 UpdateDisk (g);
536 #if MULTIUSER
537 if (g->user->uid != muROOT_UID)
538 return;
539 #endif
541 //DebugPutStr("Removing volume..\n");
542 /* 'remove' disk */
543 volume = g->currentvolume;
544 if (volume)
545 DiskRemoveSequence(g);
547 //DebugPutStr("Uninstalling ResetHandler..\n");
548 UninstallResetHandler(g);
550 //DebugPutStr("Uninstalling DiskChangeHandler..\n");
551 /* remove diskchangehandler */
552 UninstallDiskChangeHandler(g);
554 #if 0
555 /* wait for wb to return locks */
556 Delay(50);
557 #endif
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)))
573 nr = nmsg->nm_NReq;
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);
579 else
581 nmsg->nm_NReq->nr_MsgCount--;
582 FreeMemP (nmsg, g);
586 //DebugPutStr("Forbid()..\n");
588 Forbid ();
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);
615 #if EXTRAPACKETS
616 DeleteMsgPort(g->sleepport);
617 #endif
619 //DebugPutStr("Freeing misc structures\n");
620 FreeVec (g->mountname);
621 FreeMemP (g->geom, g);
622 FreeVec (g->dc.ref);
623 FreeVec (g->dc.data);
624 DeallocLRU(g);
625 if (alloc_data.reservedtobefreed)
626 FreeMem (alloc_data.reservedtobefreed, sizeof(*alloc_data.reservedtobefreed) * alloc_data.rtbf_size);
628 //DebugPutStr("Permit()\n");
629 Permit ();
631 #if UNSAFEQUIT
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);
644 if (listentry)
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;
651 if (listentry)
652 RemoveListEntry (listentry, g);
653 g->action->dp_Res1 = DOSTRUE;
655 else
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");
664 //Delay (5);
665 g->devnode->dn_Task = NULL;
666 #endif
668 LibDeletePool (g->bufferPool);
669 LibDeletePool (g->mainPool);
671 #if MULTIUSER
672 if (muBase)
673 CloseLibrary((struct Library *) muBase);
674 #endif
675 #ifndef KS13WRAPPER
676 CloseLibrary(UtilityBase);
677 #endif
678 CloseLibrary((struct Library *) DOSBase);
679 CloseLibrary((struct Library *) IntuitionBase);
681 EXIT("dd_Quit");
683 FreeMem (g, sizeof(struct globaldata));
684 AfsDie ();
687 #undef SysBase
689 #ifdef __AROS__
690 LONG AROSEntryPoint(struct ExecBase *SysBase)
692 #ifdef KS13WRAPPER
693 #if KS13WRAPPER_DEBUG
694 DebugPutStr("PFS3 starting..\n");
695 #endif
696 return wrapper_stackswap(EntryPoint, SysBase);
697 #else
698 return EntryPoint(SysBase);
699 #endif
701 #else
702 LONG __saveds __startup Main(void)
704 return EntryPoint(*(struct ExecBase **)4L);
706 #endif