/********************************************************************
 ** FILE SYSTEM THINGY
 **
 ** (c) Spak, Darrell Tam, c9107253@firebird.newcastle.edu.au (1994)
 ** phone (Australia) 049-829-710
 **                    49-829-710
 ** (c) SST 1994
 **
 ** MAIN PROGRAM INITIALIZATION ROUTINES
 **
 ** Based on Mat Dillon's nfs code
 **
 ** Should really have custom startup code since this is to be
 ** started by dos (as a device handler) - at the moment it is being
 ** linked with a slightly modified std c-startup code
 **
 ** TABS to 4
 ********************************************************************/

/* things to do:

finish this part

*/



#include "/snd/everything.h"
#include "/snd/gfxthings_protos.h"
#include "deadheads.h"			/* global variable type stuff */
#include "caller_protos.h"		/* packet handle routines */
#include "root_protos.h"		/* the root thing routines */
#include "globs_protos.h"
#include "lowest_protos.h"
#include "xtra_protos.h"

/********************************************************************/
			int DoStartup(struct DosPacket *packet)
/********************************************************************/
{
char	*volname, *startup, temp[100];
/*struct	FileSysStartupMsg *fs;
struct	DosEnvec *de; */

	OurNode	= BTOC(packet->dp_Arg3);
	if(! (DevList = DosAlloc(sizeof(struct DeviceList))) )
		return(ERROR_NO_FREE_STORE);

	startup = BTOC(OurNode->dn_Startup);
	dbmov(&startup[1], temp, startup[0]);
	temp[startup[0]] = '\0';

/** DO THE STARTUP STUFF */
/*	fs = BTOC(OurNode->dn_Startup);				/* startup stuff */
	de = BTOC(fs->fssm_Environ);				/* dos envec */ */
	MyPrint(win1, temp);
{ char tt[40]; spf(tt, 40, "%lx %lx %lx %lx %lx %lx",
		BTOC(packet->dp_Arg1), BTOC(packet->dp_Arg2),
		BTOC(packet->dp_Arg4), BTOC(packet->dp_Arg5),
		BTOC(packet->dp_Arg6), BTOC(packet->dp_Arg7)); MyPrint(win1, tt); }
	if(!OpenRoot(temp))
		return(ERROR_OBJECT_NOT_FOUND);

/** GET A NAME FOR US */
	MyPrint(win1, "Starting, volume name =");
	if( !(volname = AllocRemember(&globmem, 40, MEMF_PUBLIC | MEMF_CLEAR) ))
		return(ERROR_NO_FREE_STORE);
	volname[0] = 6; volname[1] = 'Y'; volname[2] = 'e'; volname[3] = 'l';
	volname[4] = 'l'; volname[5] = 'o'; volname[6] = 'w';
	MyPrintBCPL(win1, CTOB(volname));


/** UPDATE THIS SINCE WE MUST HAVE ONLY ONE TASK */
	OurNode->dn_Task = OurPort;

/** DISK VOLUME NODE */
	DevList->dl_Type = DLT_VOLUME;
	DevList->dl_Task = OurPort;
	DevList->dl_Lock = NULL;
	DevList->dl_LockList = NULL;
	DevList->dl_DiskType = ID_DOS_DISK;
	DevList->dl_Name = CTOB(volname);

/** PUT IN THE VOLUME NODE */
{ struct DosInfo
	*di = BTOC(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
	Forbid();
	DevList->dl_Next = di->di_DevInfo;
	di->di_DevInfo = (long)CTOB(DevList);
	Permit();
}

	return(0);
}

/********************************************************************/
void	DoDosPkt(struct Message *msg,
			struct DosPacket *dospkt, struct MsgPort *theirport)
/********************************************************************/
{
long res;
	dospkt->dp_Link = msg;			/* just in case */
	dospkt->dp_Res1 = -1;			/* default to ok */
	dospkt->dp_Res2 = -1;
	MyPrint(win1, PacketName(dospkt->dp_Type));

/** USE THE MAJIC CALLING ROUTINE */
	if( res = (((long (*)(struct DosPacket *, struct MsgPort *))
		which_action(dospkt->dp_Type))(dospkt, theirport) )
			& AR_FLAG_RETURNDOSMSG )
					PutMsg(theirport, msg);
}


/********************************************************************/
				void main()
/********************************************************************/
{


/** INIT EVERYTHING THAT WE NEED */
	win1 = NULL;
	DevList = NULL;
	globmem = NULL; IntuitionBase = NULL; GfxBase = NULL;
	dbzero(netservport, sizeof(netservport));
	localrepport = NULL;
	netrepport = NULL;
	OurProc = (struct Process *)FindTask(NULL);
	OurPort =  &OurProc->pr_MsgPort;
	first_fa1 = NULL; first_lk = NULL;

	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0))
	|| !(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0)) )
			goto nomore;
	OpenGfx();
	MyPrint(win1, "starting everything ");

{ char tt[40]; spf(tt,40,"pr_winptr=%ld", OurProc->pr_WindowPtr); MyPrint(win1, tt); }



/** GET THE STARTUP PACKET FROM DOS */
{
long error;
struct DosPacket *dospkt;
	MyPrint(win1, "Waiting for the startup packet");
	WaitPort(OurPort);
	MyPrint(win1, "Getting the startup packet");
	dospkt = (struct DosPacket *)(GetMsg(OurPort))->mn_Node.ln_Name;

	if(error = DoStartup(dospkt)) {
		dospkt->dp_Res1 = 0; dospkt->dp_Res2 = error;
		RETURN_DOS_PKT(dospkt, OurPort);
		goto nomore;
	} else {
		dospkt->dp_Res1 = -1; dospkt->dp_Res2 = 0;
		RETURN_DOS_PKT(dospkt, OurPort);
	}
}


/** TRY AND FIND A NETWORK PORT */
	if(netservport[0] = FindPort("ParServer"))
		MyPrint(win1, "found A network server (ParServer)\n");


/** DO THE LOOPITY LOOP LOOP */
{ char te[60]; spf(te, 60, "starting (port=%lx, proc=%lx)", OurPort, OurProc); MyPrint(win1, te); }

{
struct	DosPacket		*dospkt;
struct	Message			*msg;
struct	DoofusPktMsg	*dnpm;
long	mask,
		nmask = 1<<netrepport->mp_SigBit,			/* network reply port */
		wmask = 1<<win1->UserPort->mp_SigBit,		/* window port */
		hmask = 1<<OurPort->mp_SigBit,				/* handler port (ours) */
		rmask = 1<<localrepport->mp_SigBit,			/* local re-route port */
		waitmask = nmask | wmask | hmask | rmask;
struct	MsgPort *theirport;

	for(notdone = 1; notdone; ) {

		mask = Wait(waitmask);

	/** HANDLE THE PACKET(S) SENT TO US FROM DOS */
		while (msg = GetMsg(OurPort)) {
			dospkt = (struct DosPacket *)msg->mn_Node.ln_Name;
			theirport = dospkt->dp_Port;
			dospkt->dp_Port = OurPort;				/* default back to this port */
			DoDosPkt(msg, dospkt, theirport);
		}

	/** HANDLE ANY RETURN "DOOFUS" PACKETS - NETWORK OR DOS */
		while (dnpm = (struct DoofusPktMsg *)GetMsg(netrepport)) {
		long	tmp;
			theirport = dnpm->dp_returnport;
			msg = dnpm->dp_original->dp_Link;
			/* really needs to do some error handling as well */
			if((tmp = (dnpm->code(dnpm))) & AR_FLAG_RETURNDOSMSG)
														PutMsg(theirport, msg);
			if(tmp & AR_FLAG_FREEDOOF) FREE_DOOFPKTMSG(dnpm);

		}

	/** MSG'S HAVE BEEN SENT HERE FROM A SOFTWARE INTERRUPT PORT
	 ** - the files being manipulated are interative and each requires
	 **   its very own port, mn_ReplyPort SHOULD already be valid, being
	 **   filled in by the software interrupt
	 **/
		if(mask & rmask) {
			while(msg = GetMsg(localrepport))
				DoDosPkt(msg,
					(struct DosPacket *)msg->mn_Node.ln_Name, msg->mn_ReplyPort);
		}

	/** HANDLE THE WINDOW */
		if( HandleWin1() == IDCMP_CLOSEWINDOW) notdone = 0;
	}
}




/* this has no checking for active messages. this is to be added later */

/** HAVE TO DO THIS SO WE CAN REARRANGE SOME LISTS & CLEAN UP */
	Forbid();

/** WE ARE NO LONGER LOADED IN MEMORY */
	OurNode->dn_Task = NULL;

/** REMOVE OUR VOLUME ENTRY */
{
struct	DosInfo *di = BTOC(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
struct	DeviceList *dl;
void	*dlp;

	dlp = &di->di_DevInfo;
	for(dl = BTOC(di->di_DevInfo); dl && dl != DevList; dl = BTOC(dl->dl_Next))
		dlp = &dl->dl_Next;
	if (dl == DevList) {
		*(BPTR *)dlp = dl->dl_Next;
		DosFree((ULONG *)dl);
	} else {
		;
	}
}

/** LET EVERYONE ELSE RUN TOO */
	Permit();

nomore:
	CloseRoot();
	CloseGfx();
	FreeRemember(&globmem, TRUE);
	if(GfxBase) CloseLibrary((struct Library *)GfxBase);
	if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
}

