
/**
 **
 ** INCLUDE FILE FOR THE NETWORK FILESYSTEM - SERVICE END
 **
 **/

/* all the following structures are long word aligned (since they may be
 * allocated in joined chunks) */

#include "/par/parstuff.h"

/**
 **
 **            REQUEST STRUCTURES (MUST BE < 128 bytes in length)
 **  StdReq followed by the request number (see below for the request number)
 **/


struct NFSDummy {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
};

struct NFSOpenFile {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* only if "internallock" != NULL */
	long	action;			/* actual action we should use to open the file */
	long	internallock;	/* since this may be "assign'd" */

	/* long word aligned! actual name to come in the send_body part, with the first
     * byte containing the length, and the string needs to be NULL terminated */
};

struct NFSCloseFile {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* unused for the moment */
	long	remote_ifh;
};

/* when you send off a read or write request, use the supplied INIT_PKTMSG_ORIGINAL
 * to specify the length to be read (or written) with the result_body & len (or
 * for write, the send_body & len) pointing at the memory to which you wish the
 * server to fill (or send)
 *
 * on the server end, sr.result_len will contain the appropriate length to be
 * sent back (with the "destination" service set to SERV_RESULT) in the case
 * of a "read" request from a client machine
 *
 */

struct NFSRead {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* unused for the moment */
	long	remote_ifh;
	/* readlength = sr.result_len */
};

struct NFSWrite {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* unused for the moment */
	long	remote_ifh;
	/* the data to write is in the PktMsg associated with this request */
};

struct NFSSeek {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* unused for the moment */
	long	remote_ifh;
	long	position;
	long	mode;
};


/* the NFSCopyDir function also uses the same structure */
struct NFSLock {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* only if the internallock != NULL (else ignore) */
	long	internallock;	/* extra offset (must fill in remote_majic if set) */
	long	mode;			/* ignored for copylock */
	/* actual "name" comes in the "send-body" part of the net-pkt with the first
     * byte containing the length (BCPL style) - it MUST also be NULL terminated */
};

struct NFSFreeLock {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* unused for the moment */
	long	remote_il;		/* remote internal lock as per fl_Key */
};

struct NFSWaitChar {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */		
	long	remote_majic;	/* unused for the moment */
	long	remote_ifh;		/* slight variation on the normal format */
	long	timeout;
};

/* examine & exnext requests */
struct NFSExamine {
	struct	StdReq	sr;		/* MUST HAVE! do not write into */
	unsigned long request;	/* must be exactly here! */
	long	remote_majic;	/* unused for the moment */
	long	remote_il;		/* slight variation on the normal format */
	/* for the ExNext, the old fib is sent as pmr->pm.send_body */
};

/**
 **
 **					REPLY STRUCTURES, DMA'D BACK TO THE CALLER
 **
 **/

struct NFSOpenFileReturn {
	long	remote_res1;		/* boolean */
	long	remote_res2;
	long	remote_ifh;			/* index into remote array of internal fh's (arg1) */
	long	remote_ifh_Port;	/* actually means "interactive" */
	long	remote_majic;		/* unused for the moment - but it will be */
};


/** result from read/write/close/etc etc */
struct NFSStdReturn {
	long	remote_res1;
	long	remote_res2;
};

/** result from locateobject ("lock") and copydir ("copy_lock")*/
struct NFSLockReturn {
	long	remote_il;					/* NULL on failure (just like original res1) */
	long	remote_res2;
	long	remote_majic;		/* majic code to use when referring to this lock */
};


/** REQUEST defines - totally different from the dos ones! */
#define REQUEST_EXAMINELOCK 0
#define REQUEST_EXAMINE		REQUEST_EXAMINELOCK

#define REQUEST_OPENFILE	1
#define REQUEST_CLOSEFILE	2
#define REQUEST_READ		3
#define	REQUEST_WRITE		4
#define REQUEST_SEEK		5

#define REQUEST_LOCK		6			/* short for locateobject */
#define REQUEST_FREELOCK	7

#define REQUEST_WAITCHAR 	8			/* note this requires fa1 & timeout */

#define REQUEST_COPYLOCK	9
#define REQUEST_COPYDIR		REQUEST_COPYLOCK

#define REQUEST_EXAMINENEXT 10

#define REQUEST_DELETEOBJECT
#define REQUEST_CREATEDIR
#define REQUEST_PARENT

#define REQUEST_SETPROTECT
#define REQUEST_SETCOMMENT
#define REQUEST_RENAMEOBJECT

/** ALWAYS! when calling dos make sure the dos-packet is in this form! */
struct DosMsg {
	struct StandardPacket sp;
	void	(*code)(struct DosMsg *);	/* ALWAYS! fill this in! */
};


/** MACROS TO INIT DOS STANDARD PACKET MESSAGES */
#define INIT_STD_DOSPKTMSG(stdpkt, replyport) \
	\
	((stdpkt)->sp_Msg.mn_Node.ln_Type	= NT_MESSAGE,\
	(stdpkt)->sp_Msg.mn_Node.ln_Name	= (char *)(&(stdpkt)->sp_Pkt),\
	(stdpkt)->sp_Msg.mn_Length			= sizeof(struct StandardPacket),\
	(stdpkt)->sp_Msg.mn_ReplyPort = (stdpkt)->sp_Pkt.dp_Port = replyport,\
	(stdpkt)->sp_Pkt.dp_Link			= &(stdpkt)->sp_Msg)

#define INIT_STD_PKT(stdpkt, replyport) INIT_STD_DOSPKTMSG(stdpkt, replyport)

#define STD_PKT_ARGS1(stdpkt, replyport, action, arg1)\
	((stdpkt)->sp_Pkt.dp_Type = (action),\
	(stdpkt)->sp_Pkt.dp_Arg1 = (long)(arg1),\
	INIT_STD_PKT(stdpkt,replyport))

#define STD_PKT_ARGS2(stdpkt, replyport, action, arg1, arg2)\
	((stdpkt)->sp_Pkt.dp_Arg2 = (long)(arg2),\
	STD_PKT_ARGS1(stdpkt, replyport, action, arg1))

#define STD_PKT_ARGS3(stdpkt, replyport, action, arg1, arg2, arg3)\
	((stdpkt)->sp_Pkt.dp_Arg3 = (long)(arg3),\
	STD_PKT_ARGS2(stdpkt, replyport, action, arg1, arg2))

#define INIT_DOS_MSG(dm_o, replyport_o, code_o)\
	((dm_o)->code = (code_o),\
	INIT_STD_PKT(&((dm_o)->sp), replyport_o))



/** LIST MACROS - have an entry in your structure called next & prev and keep
 ** track of the first element in the list with "first_o" */

#define ADD_HEAD(thing_o, first_o) \
		\
	{	(thing_o)->prev = NULL;\
		if((thing_o)->next = first_o) first_o->prev = thing_o;\
		(first_o) = thing_o;\
	}

/* no return! */
#define REMOVE_FROM_LIST(thing_o, first_o) \
		\
	{	if((thing_o)->prev) (thing_o)->prev->next = (thing_o)->next; \
		else (first_o) = (thing_o)->next; \
		if((thing_o)->next) (thing_o)->next->prev = (thing_o)->prev; }




#ifndef BTOC
#define BTOC(bp)    ((void *)(((long)(bp)) << 2))
#endif
#ifndef CTOB
#define CTOB(cp)    ((BPTR)(((long)(cp)) >> 2))
#endif

