/*
 * fundamental constants
 */
#define SUPER_ADDR	2		/* address of superblock */
#define ROOT_ADDR	3		/* address of superblock */
#define	ERRREC		64		/* size of a error record */
#define	DIRREC		116		/* size of a directory ascii record */
#define	NAMELEN		28		/* size of names */
#define	NDBLOCK		6		/* number of direct blocks in Dentry */
#define	MAXDAT		(30*1024)		/* max allowable data message */
#define	MAXMSG		128		/* max size protocol message sans data */
#define	OFFMSG		60		/* offset of msg in buffer */
#define NDRIVE		16		/* size of drive structure */
#define NTLOCK		200		/* number of active file Tlocks */
#define	LRES		3		/* profiling resolution */
#define NATTID		10		/* the last 10 ID's in attaches */
#define	C0a		59		/* time constants for filters */
#define	C0b		60
#define	C1a		599
#define	C1b		600
#define	C2a		5999
#define	C2b		6000

/*
 *  more wonderful constants for authentication
 */
#include <auth.h>

/*
 * derived constants
 */
#define	BUFSIZE		(RBUFSIZE-sizeof(Tag))
#define DIRPERBUF	(BUFSIZE/sizeof(Dentry))
#define INDPERBUF	(BUFSIZE/sizeof(long))
#define INDPERBUF2	(INDPERBUF*INDPERBUF)
#define FEPERBUF	((BUFSIZE-sizeof(Super1)-sizeof(long))/sizeof(long))
#define	SMALLBUF	(MAXMSG)
#define	LARGEBUF	(MAXMSG+MAXDAT+256)
#define	RAGAP		(300*1024)/BUFSIZE		/* readahead parameter */
#define CEPERBK		((BUFSIZE-BKPERBLK*sizeof(long))/\
				(sizeof(Centry)*BKPERBLK))
#define	BKPERBLK	10

typedef struct	Alarm	Alarm;
typedef	struct	Conf	Conf;
typedef	struct	Label	Label;
typedef	struct	Lock	Lock;
typedef	struct	Mach	Mach;
typedef	struct	QLock	QLock;
typedef	struct	Ureg	Ureg;
typedef	struct	User	User;
typedef	struct	Fcall	Fcall;
typedef	struct	Fbuf	Fbuf;
typedef	struct	Super1	Super1;
typedef	struct	Superb	Superb;
typedef	struct	Filsys	Filsys;
typedef	struct	Startsb	Startsb;
typedef	struct	Dentry	Dentry;
typedef	struct	Tag	Tag;
typedef struct  Talarm	Talarm;
typedef	struct	Uid	Uid;
typedef struct	Device	Device;
typedef struct	Qid	Qid;
typedef	struct	Iobuf	Iobuf;
typedef	struct	Wpath	Wpath;
typedef	struct	File	File;
typedef	struct	Chan	Chan;
typedef	struct	Cons	Cons;
typedef	struct	Time	Time;
typedef	struct	Tm	Tm;
typedef	struct	Rtc	Rtc;
typedef	struct	Hiob	Hiob;
typedef	struct	RWlock	RWlock;
typedef	struct	Msgbuf	Msgbuf;
typedef	struct	Queue	Queue;
typedef	struct	Command	Command;
typedef	struct	Flag	Flag;
typedef	struct	Bp	Bp;
typedef	struct	Rabuf	Rabuf;
typedef	struct	Rendez	Rendez;
typedef	struct	Filter	Filter;
typedef		ulong	Float;
typedef	struct	Tlock	Tlock;
typedef	struct	Enpkt	Enpkt;
typedef	struct	Arppkt	Arppkt;
typedef	struct	Ippkt	Ippkt;
typedef	struct	Ilpkt	Ilpkt;
typedef	struct	Udppkt	Udppkt;
typedef	struct	Icmppkt	Icmppkt;
typedef	struct	Ifc	Ifc;
typedef	struct	Cache	Cache;
typedef	struct	Centry	Centry;
typedef	struct	Bucket	Bucket;

struct	Lock
{
	ulong*	sbsem;		/* addr of sync bus semaphore */
	ulong	pc;
	ulong	sr;
};

struct	Rendez
{
	Lock;
	User*	p;
};

struct	Filter
{
	ulong	count;			/* count and old count kept separate */
	ulong	oldcount;		/*	so interrput can read them */
	int	c1;			/* time const multiplier */
	int	c2;			/* time const divider */
	int	c3;			/* scale for printing */
	Float	filter;			/* filter */ 
};

struct	QLock
{
	Lock;			/* to use object */
	User*	head;		/* next process waiting for object */
	User*	tail;		/* last process waiting for object */
	char*	name;		/* for diagnostics */
	int	locked;		/* flag, is locked */
};

struct	RWlock
{
	int	nread;
	QLock	wr;
	QLock	rd;
};

/*
 * send/recv queue structure
 */
struct	Queue
{
	Lock;			/* to manipulate values */
	int	size;		/* size of queue */
	int	loc;		/* circular pointer */
	int	count;		/* how many in queue */
	User*	rhead;		/* process's waiting for send */
	User*	rtail;
	User*	whead;		/* process's waiting for recv */
	User*	wtail;
	void*	args[1];	/* list of saved pointers, [->size] */
};

struct	Tag
{
	short	pad;
	short	tag;
	long	path;
};

struct	Device
{
	uchar	type;
	uchar	init;
	Device*	link;			/* link for mcat/mlev */
	Device*	dlink;			/* link all devices */
	void*	private;
	long	size;
	union
	{
		struct			/* worm wren */
		{
			int	ctrl;
			int	targ;
			int	lun;
		} wren;
		struct			/* mcat mlev */
		{
			Device*	first;
			Device*	last;
			int	ndev;
		} cat;
		struct			/* cw */
		{
			Device*	c;
			Device*	w;
			Device*	ro;
		} cw;
		struct			/* juke */
		{
			Device*	j;
			Device*	m;
		} j;
		struct			/* ro */
		{
			Device*	parent;
		} ro;
		struct			/* fworm */
		{
			Device*	fw;
		} fw;
		struct			/* part */
		{
			Device*	d;
			long	base;
			long	size;
		} part;
		struct			/* part */
		{
			Device*	d;
		} swab;
	};
};

struct	Rabuf
{
	union
	{
		struct
		{
			Device*	dev;
			long	addr;
		};
		Rabuf*	link;
	};
};

/* DONT TOUCH, this is the disk structure */
struct	Qid
{
	long	path;
	long	version;
};

struct	Hiob
{
	Iobuf*	link;
	Lock;
};

enum
{
	Easize		= 6,		/* Ether address size */
	Pasize		= 4,		/* IP protocol address size */
};

typedef
struct
{
	Queue*	reply;		/* ethernet output */
	uchar	iphis[Pasize];	/* his ip address (index) */
	uchar	ipgate[Pasize];	/* his ip/gateway address */
	Chan*	link;		/* list of il channels */
} Enp;

enum
{
	Nqt=	8,
};

typedef
struct	Ilp
{
	Enp;			/* must be first -- botch */

	int	alloc;		/* 1 means allocated */
	int	srcp;		/* source port (index) */
	int	dstp;		/* dest port (index) */
	int	state;		/* connection state */

	Msgbuf*	unacked;
	Msgbuf*	unackedtail;

	Msgbuf*	outoforder;

	ulong	next;		/* id of next to send */
	ulong	recvd;		/* last packet received */
	ulong	start;		/* local start id */
	ulong	rstart;		/* remote start id */
	ulong	acksent;	/* Last packet acked */

	ulong	lastxmit;	/* time of last xmit */
	ulong	lastrecv;	/* time of last recv */
	ulong	timeout;	/* time out counter */
	ulong	acktime;	/* acknowledge timer */
	ulong	querytime;	/* Query timer */

	ulong	delay;		/* Average of the fixed rtt delay */
	ulong	rate;		/* Average byte rate */
	ulong	mdev;		/* Mean deviation of predicted to real rtt */
	ulong	maxrtt;		/* largest rtt seen */
	ulong	rttack;		/* The ack we are waiting for */
	int	rttlen;		/* Length of rttack packet */
	ulong	rttstart;	/* Time we issued rttack packet */
	ulong	unackedbytes;
	int	rexmit;		/* number of rexmits of *unacked */

	ulong	qt[Nqt+1];	/* state table for query messages */
	int	qtx;		/* ... index into qt */

	int	window;		/* maximum receive window */

	Rendez	syn;		/* connect hang out */
} Ilp;

struct	Chan
{
	char	type;			/* major driver type i.e. Dev* */
	char	whochan[50];
	char	whoname[NAMELEN];
	ulong	flags;
	int	chan;			/* overall channel number, mostly for printing */
	int	nmsgs;			/* outstanding messages, set under flock -- for flush */
	ulong	whotime;
	Filter	work;
	Filter	rate;
	int	nfile;			/* used by cmd_files */
	RWlock	reflock;
	Chan*	next;			/* link list of chans */
	Queue*	send;
	Queue*	reply;
	uchar	chal[CHALLEN];		/* locally generated challenge */
	uchar	rchal[CHALLEN];		/* remotely generated challenge */
	Lock	idlock;
	ulong	idoffset;		/* offset of id vector */
	ulong	idvec;			/* vector of acceptable id's */

	Ifc*	ifc;
	union
	{
		/*
		 * il ether circuit structure
		 */
		Ilp	ilp;
	};
};

struct	Filsys
{
	char*	name;			/* name of filsys */
	char*	conf;			/* symbolic configuration */
	Device*	dev;			/* device that filsys is on */
	int	flags;
		#define	FREAM		(1<<0)	/* mkfs */
		#define	FRECOVER	(1<<1)	/* install last dump */
		#define	FEDIT		(1<<2)	/* modified */
};

struct	Startsb
{
	char*	name;
	long	startsb;
};

struct	Time
{
	ulong	lasttoy;
	long	bias;
	long	offset;
};

/*
 * array of qids that are locked
 */
struct	Tlock
{
	Device*	dev;
	ulong	time;
	long	qpath;
	File*	file;
};

struct	Cons
{
	ulong	flags;		/* overall flags for all channels */
	QLock;			/* generic qlock for mutex */
	int	uid;		/* botch -- used to get uid on cons_create */
	int	gid;		/* botch -- used to get gid on cons_create */
	int	nuid;		/* number of uids */
	int	ngid;		/* number of gids */
	long	offset;		/* used to read files, c.f. fchar */
	int	chano;		/* generator for channel numbers */
	Chan*	chan;		/* console channel */
	Filsys*	curfs;		/* current filesystem */

	int	profile;	/* are we profiling? */
	long*	profbuf;
	ulong	minpc;
	ulong	maxpc;
	ulong	nprofbuf;

	long	nlarge;		/* number of large message buffers */
	long	nsmall;		/* ... small ... */
	long	nwormre;	/* worm read errors */
	long	nwormwe;	/* worm write errors */
	long	nwormhit;	/* worm read cache hits */
	long	nwormmiss;	/* worm read cache non-hits */
	int	noage;		/* dont update cache age, dump and check */
	long	nwrenre;	/* disk read errors */
	long	nwrenwe;	/* disk write errors */
	long	nreseq;		/* cache bucket resequence */

	Filter	work[3];	/* thruput in messages */
	Filter	rate[3];	/* thruput in bytes */
	Filter	bhit[3];	/* getbufs that hit */
	Filter	bread[3];	/* getbufs that miss and read */
	Filter	brahead[3];	/* messages to readahead */
	Filter	binit[3];	/* getbufs that miss and dont read */
};

struct	File
{
	QLock;
	Qid	qid;
	Wpath*	wpath;
	Chan*	cp;		/* null means a free slot */
	Tlock*	tlock;		/* if file is locked */
	File*	next;		/* in cp->flist */
	Filsys*	fs;
	long	addr;
	long	slot;
	long	lastra;		/* read ahead address */
	ushort	fid;
	short	uid;
	char	open;
		#define	FREAD	1
		#define	FWRITE	2
		#define	FREMOV	4
};

struct	Wpath
{
	Wpath*	up;		/* pointer upwards in path */
	long	addr;		/* directory entry addr */
	long	slot;		/* directory entry slot */
	short	refs;		/* number of files using this structure */
};

struct	Iobuf
{
	QLock;
	Device*	dev;
	Iobuf*	next;		/* for hash */
	Iobuf*	fore;		/* for lru */
	Iobuf*	back;		/* for lru */
	char*	iobuf;		/* only active while locked */
	char*	xiobuf;		/* "real" buffer pointer */
	long	addr;
	int	flags;
};

struct	Uid
{
	short	uid;		/* user id */
	short	lead;		/* leader of group */
	short	*gtab;		/* group table */
	int	ngrp;		/* number of group entries */
	char	name[NAMELEN];	/* user name */
};

/* DONT TOUCH, this is the disk structure */
struct	Dentry
{
	char	name[NAMELEN];
	short	uid;
	short	gid;
	ushort	mode;
		#define	DALLOC	0x8000
		#define	DDIR	0x4000
		#define	DAPND	0x2000
		#define	DLOCK	0x1000
		#define	DREAD	0x4
		#define	DWRITE	0x2
		#define	DEXEC	0x1
	short	wuid;
	Qid	qid;
	long	size;
	long	dblock[NDBLOCK];
	long	iblock;
	long	diblock;
	long	atime;
	long	mtime;
};

/* DONT TOUCH, this is the disk structure */
struct	Super1
{
	long	fstart;
	long	fsize;
	long	tfree;
	long	qidgen;		/* generator for unique ids */
	/*
	 * Stuff for WWC device
	 */
	long	cwraddr;	/* cfs root addr */
	long	roraddr;	/* dump root addr */
	long	last;		/* last super block addr */
	long	next;		/* next super block addr */
};

/* DONT TOUCH, this is the disk structure */
struct	Fbuf
{
	long	nfree;
	long	free[FEPERBUF];
};

/* DONT TOUCH, this is the disk structure */
struct	Superb
{
	Fbuf	fbuf;
	Super1;
};

struct	Fcall
{
	char	type;
	ushort	fid;
	short	err;
	short	tag;
	union
	{
		struct
		{
			short	uid;		/* T-Userstr */
			short	oldtag;		/* T-nFlush */
			Qid	qid;		/* R-Attach, R-Clwalk, R-Walk,
						 * R-Open, R-Create */
			char	rauth[AUTHENTLEN];	/* R-attach */
		};
		struct
		{
			char	uname[NAMELEN];	/* T-nAttach */
			char	aname[NAMELEN];	/* T-nAttach */
			char	ticket[TICKETLEN];	/* T-attach */
			char	auth[AUTHENTLEN];	/* T-attach */
		};
		struct
		{
			char	ename[ERRREC];	/* R-nError */
			char	chal[CHALLEN];	/* T-session, R-session */
			char	authid[NAMELEN];	/* R-session */
			char	authdom[DOMLEN];	/* R-session */
		};
		struct
		{
			char	name[NAMELEN];	/* T-Walk, T-Clwalk, T-Create, T-Remove */
			long	perm;		/* T-Create */
			ushort	newfid;		/* T-Clone, T-Clwalk */
			char	mode;		/* T-Create, T-Open */
		};
		struct
		{
			long	offset;		/* T-Read, T-Write */
			long	count;		/* T-Read, T-Write, R-Read */
			char*	data;		/* T-Write, R-Read */
		};
		struct
		{
			char	stat[DIRREC];	/* T-Wstat, R-Stat */
		};
	};
};

struct	Label
{
	ulong	pc;
	ulong	sp;
};

struct	Alarm
{
	Lock;
	Alarm*	next;
	int	busy;
	int	dt;		/* in ticks */
	void	(*f)(Alarm*, void*);
	void*	arg;
};

struct Talarm
{
	Lock;
	User	*list;
};

struct	Conf
{
	ulong	nmach;		/* processors */
	ulong	nproc;		/* processes */
	ulong	mem;		/* total physical bytes of memory */
	ulong	sparemem;	/* memory left for check/dump and chans */
	ulong	nalarm;		/* alarms */
	ulong	nuid;		/* distinct uids */
	ulong	nserve;		/* server processes */
	ulong	nfile;		/* number of fid -- system wide */
	ulong	nwpath;		/* number of active paths, derrived from nfile */
	ulong	gidspace;	/* space for gid names -- derrived from nuid */
	ulong	nlgmsg;		/* number of large message buffers */
	ulong	nsmmsg;		/* number of small message buffers */
	ulong	wcpsize;	/* memory for worm copies */
	ulong	recovcw;	/* recover addresses */
	ulong	recovro;
	ulong	firstsb;
	ulong	recovsb;
	uchar	nodump;		/* no periodic dumps */
	uchar	ripoff;
	uchar	dumpreread;	/* read and compare in dump copy */

	ulong	npage0;		/* total physical pages of memory */
	ulong	npage1;		/* total physical pages of memory */
	ulong	base0;		/* base of bank 0 */
	ulong	base1;		/* base of bank 1 */
};

/*
 * message buffers
 * 2 types, large and small
 */
struct	Msgbuf
{
	short	count;
	short	flags;
		#define	LARGE	(1<<0)
		#define	FREE	(1<<1)
		#define BFREE	(1<<2)
	Chan*	chan;
	Msgbuf*	next;
	ulong	param;
	int	category;
	char*	data;
	char*	xdata;
};

/*
 * message buffer categories
 */
enum
{
	Mxxx		= 0,
	Mbreply1,
	Mbreply2,
	Mbreply3,
	Mbreply4,
	Mbarp1,
	Mbarp2,
	Mbip1,
	Mbip2,
	Mbip3,
	Mbil1,
	Mbil2,
	Mbil3,
	Mbil4,
	Mbilauth,
	Maeth1,
	Maeth2,
	Maeth3,
	Mbeth1,
	Mbeth2,
	Mbeth3,
	Mbeth4,
	Mbsntp,
	MAXCAT,
};

struct	Mach
{
	int	machno;		/* physical id of processor */
	int	mmask;		/* 1<<m->machno */
	ulong	ticks;		/* of the clock since boot time */
	int	lights;		/* light lights, this processor */
	User*	proc;		/* current process on this processor */
	Label	sched;		/* scheduler wakeup */
	Lock	alarmlock;	/* access to alarm list */
	void*	alarm;		/* alarms bound to this clock */
	void	(*intr)(Ureg*, ulong);	/* pending interrupt */
	User*	intrp;		/* process that was interrupted */
	ulong	cause;		/* arg to intr */
	Ureg*	ureg;		/* arg to intr */
	uchar	stack[1];
};

#define	MAXSTACK 4000
#define	NHAS	100
struct	User
{
	Label	sched;
	Mach*	mach;		/* machine running this proc */
	User*	rnext;		/* next process in run queue */
	User*	qnext;		/* next process on queue for a QLock */
	void	(*start)(void);	/* startup function */
	char*	text;		/* name of this process */
	void*	arg;
	Filter	time[3];	/* cpu time used */
	int	exiting;
	int	pid;
	int	state;
	Rendez	tsleep;

	ulong	twhen;
	Rendez	*trend;
	User	*tlink;
	int	(*tfn)(void*);

	struct
	{
		QLock*	q[NHAS];/* list of locks this process has */
		QLock*	want;	/* lock waiting */
	} has;
	uchar	stack[MAXSTACK];
};

#define	PRINTSIZE	256
struct
{
	Lock;
	int	machs;
	int	exiting;
} active;

struct	Command
{
	char*	arg0;
	char*	help;
	void	(*func)(int, char*[]);
};

struct	Flag
{
	char*	arg0;
	char*	help;
	ulong	flag;
};

struct	Tm
{
	/* see ctime(3) */
	int	sec;
	int	min;
	int	hour;
	int	mday;
	int	mon;
	int	year;
	int	wday;
	int	yday;
	int	isdst;
};

struct	Rtc
{
	int	sec;
	int	min;
	int	hour;
	int	mday;
	int	mon;
	int	year;
};

/*
 * cw device
 */

/* DONT TOUCH, this is the disk structure */
struct	Cache
{
	long	maddr;		/* cache map addr */
	long	msize;		/* cache map size in buckets */
	long	caddr;		/* cache addr */
	long	csize;		/* cache size */
	long	fsize;		/* current size of worm */
	long	wsize;		/* max size of the worm */
	long	wmax;		/* highwater write */

	long	sbaddr;		/* super block addr */
	long	cwraddr;	/* cw root addr */
	long	roraddr;	/* dump root addr */

	long	toytime;	/* somewhere convienent */
	long	time;
};

/* DONT TOUCH, this is the disk structure */
struct	Centry
{
	ushort	age;
	short	state;
	long	waddr;		/* worm addr */
};

/* DONT TOUCH, this is the disk structure */
struct	Bucket
{
	long	agegen;		/* generator for ages in this bkt */
	Centry	entry[CEPERBK];
};

/*
 * scsi i/o
 */
enum
{
	SCSIread = 0,
	SCSIwrite = 1,
};

/*
 * Process states
 */
enum
{
	Dead = 0,
	Moribund,
	Zombie,
	Ready,
	Scheding,
	Running,
	Queueing,
	Sending,
	Recving,
	MMUing,
	Exiting,
	Inwait,
	Wakeme,
	Broken,
};

/*
 * Lights
 */
enum
{
	Lreal	= 0,	/* blink in clock interrupt */
	Lintr,		/* on while in interrupt */
	Lpanic,		/* in panic */
	Lcwmap,		/* in cw lookup */
};

/*
 * devnone block numbers
 */
enum
{
	Cwio1 	= 1,
	Cwio2,
	Cwxx1,
	Cwxx2,
	Cwxx3,
	Cwxx4,
	Cwdump1,
	Cwdump2,
	Cuidbuf,
	Cckbuf,
};

#define	MAXFDATA	(30*1024)
/*
 * P9 protocol message types
 */
/* DONT TOUCH, this the 9P protocol */
enum
{
	Tnop =		50,
	Rnop,
	Tosession =	52,
	Rosession,
	Terror =	54,	/* illegal */
	Rerror,
	Tflush =	56,
	Rflush,
	Toattach =	58,
	Roattach,
	Tclone =	60,
	Rclone,
	Twalk =		62,
	Rwalk,
	Topen =		64,
	Ropen,
	Tcreate =	66,
	Rcreate,
	Tread =		68,
	Rread,
	Twrite =	70,
	Rwrite,
	Tclunk =	72,
	Rclunk,
	Tremove =	74,
	Rremove,
	Tstat =		76,
	Rstat,
	Twstat =	78,
	Rwstat,
	Tclwalk =	80,
	Rclwalk,
	Tauth =		82,	/* illegal */
	Rauth,			/* illegal */
	Tsession =	84,
	Rsession,
	Tattach =	86,
	Rattach,

	MAXSYSCALL
};

/*
 * error codes generated from the file server
 */
enum
{
	Ebadspc = 1,
	Efid,
	Echar,
	Eopen,
	Ecount,
	Ealloc,
	Eqid,
	Eaccess,
	Eentry,
	Emode,
	Edir1,
	Edir2,
	Ephase,
	Eexist,
	Edot,
	Eempty,
	Ebadu,
	Enotu,
	Enotg,
	Ename,
	Ewalk,
	Eronly,
	Efull,
	Eoffset,
	Elocked,
	Ebroken,
	Eauth,
	Enoattach,
	MAXERR
};

/*
 * device types
 */
enum
{
	Devnone 	= 0,
	Devcon,			/* console */
	Devwren,		/* scsi disk drive */
	Devworm,		/* scsi video drive */
	Devlworm,		/* scsi video drive (labeled) */
	Devfworm,		/* fake read-only device */
	Devjuke,		/* jukebox */
	Devcw,			/* cache with worm */
	Devro,			/* readonly worm */
	Devcycl,		/* cyclone fiber uart */
	Devmcat,		/* multiple cat devices */
	Devmlev,		/* multiple interleave devices */
	Devil,			/* internet link */
	Devpart,		/* partition */
	Devfloppy,		/* floppy drive */
	Devide,			/* IDE drive */
	Devswab,		/* swab data between mem and device */
	MAXDEV
};

/*
 * tags on block
 */
/* DONT TOUCH, this is in disk structures */
enum
{
	Tnone		= 0,
	Tsuper,			/* the super block */
	Tdir,			/* directory contents */
	Tind1,			/* points to blocks */
	Tind2,			/* points to Tind1 */
	Tfile,			/* file contents */
	Tfree,			/* in free list */
	Tbuck,			/* cache fs bucket */
	Tvirgo,			/* fake worm virgin bits */
	Tcache,			/* cw cache things */
	Tconfig,		/* configuration block */
	MAXTAG
};

/*
 * flags to getbuf
 */
enum
{
	Bread	= (1<<0),	/* read the block if miss */
	Bprobe	= (1<<1),	/* return null if miss */
	Bmod	= (1<<2),	/* buffer is dirty, needs writing */
	Bimm	= (1<<3),	/* write immediately on putbuf */
	Bres	= (1<<4),	/* reserved, never renammed */
};

/*
 * open modes passed into P9 open/create
 */
/* DONT TOUCH, this the P9 protocol */
enum
{
	MREAD	= 0,
	MWRITE,
	MBOTH,
	MEXEC,
	MTRUNC	= (1<<4),	/* truncate on open */
	MCEXEC	= (1<<5),	/* close on exec (host) */
	MRCLOSE	= (1<<6),	/* remove on close */
};


/*
 * Ethernet header
 */
enum
{
	ETHERMINTU	= 60,		/* minimum transmit size */
	ETHERMAXTU	= 1514,		/* maximum transmit size */

	Arptype		= 0x0806,
	Iptype		= 0x0800,

	Icmpproto	= 1,
	Igmpproto	= 2,
	Tcpproto	= 6,
	Udpproto	= 17,
	Ilproto		= 40,

	Nqueue		= 20,
	Nfrag		= 6,		/* max number of non-contig ip fragments */
	Nrock		= 20,		/* number of partial ip assembly stations */
	Nb		= 211,		/* number of arp hash buckets */
	Ne		= 10,		/* number of entries in each arp hash bucket */

	Ensize		= 14,		/* ether header size */
	Ipsize		= 20,		/* ip header size -- doesnt include Ensize */
	Arpsize		= 28,		/* arp header size -- doesnt include Ensize */
	Ilsize		= 18,		/* il header size -- doesnt include Ipsize/Ensize */
	Udpsize		= 8,		/* il header size -- doesnt include Ipsize/Ensize */
	Udpphsize	= 12,		/* udp pseudo ip header size */

	IP_VER		= 0x40,			/* Using IP version 4 */
	IP_HLEN		= Ipsize/4,		/* Header length in longs */
	IP_DF		= 0x4000,		/* Don't fragment */
	IP_MF		= 0x2000,		/* More fragments */

	Arprequest	= 1,
	Arpreply,

	Ilfsport	= 17008,
	Ilauthport	= 17020,
	Ilfsout		= 5000,
	SNTP		= 123,
	SNTP_LOCAL	= 6001,
};

struct	Enpkt
{
	uchar	d[Easize];		/* destination address */
	uchar	s[Easize];		/* source address */
	uchar	type[2];		/* packet type */

	uchar	data[ETHERMAXTU-(6+6+2)];
	uchar	crc[4];
};

struct	Arppkt
{
	uchar	d[Easize];			/* ether header */
	uchar	s[Easize];
	uchar	type[2];

	uchar	hrd[2];				/* hardware type, must be ether==1 */
	uchar	pro[2];				/* protocol, must be ip */
	uchar	hln;				/* hardware address len, must be Easize */
	uchar	pln;				/* protocol address len, must be Pasize */
	uchar	op[2];
	uchar	sha[Easize];
	uchar	spa[Pasize];
	uchar	tha[Easize];
	uchar	tpa[Pasize];
};

struct	Ippkt
{
	uchar	d[Easize];		/* ether header */
	uchar	s[Easize];
	uchar	type[2];

	uchar	vihl;			/* Version and header length */
	uchar	tos;			/* Type of service */
	uchar	length[2];		/* packet length */
	uchar	id[2];			/* Identification */
	uchar	frag[2];		/* Fragment information */
	uchar	ttl;			/* Time to live */
	uchar	proto;			/* Protocol */
	uchar	cksum[2];		/* Header checksum */
	uchar	src[Pasize];		/* Ip source */
	uchar	dst[Pasize];		/* Ip destination */
};

struct	Ilpkt
{
	uchar	d[Easize];		/* ether header */
	uchar	s[Easize];
	uchar	type[2];

	uchar	vihl;			/* ip header */
	uchar	tos;
	uchar	length[2];
	uchar	id[2];
	uchar	frag[2];
	uchar	ttl;
	uchar	proto;
	uchar	cksum[2];
	uchar	src[Pasize];
	uchar	dst[Pasize];

	uchar	ilsum[2];		/* Checksum including header */
	uchar	illen[2];		/* Packet length */
	uchar	iltype;			/* Packet type */
	uchar	ilspec;			/* Special */
	uchar	ilsrc[2];		/* Src port */
	uchar	ildst[2];		/* Dst port */
	uchar	ilid[4];		/* Sequence id */
	uchar	ilack[4];		/* Acked sequence */
};

struct	Udppkt
{
	uchar	d[Easize];		/* ether header */
	uchar	s[Easize];
	uchar	type[2];

	uchar	vihl;			/* ip header */
	uchar	tos;
	uchar	length[2];
	uchar	id[2];
	uchar	frag[2];
	uchar	ttl;
	uchar	proto;
	uchar	cksum[2];
	uchar	src[Pasize];
	uchar	dst[Pasize];

	uchar	udpsrc[2];		/* Src port */
	uchar	udpdst[2];		/* Dst port */
	uchar	udplen[2];		/* Packet length */
	uchar	udpsum[2];		/* Checksum including header */
};

struct	Icmppkt
{
	uchar	d[Easize];		/* ether header */
	uchar	s[Easize];
	uchar	type[2];

	uchar	vihl;			/* ip header */
	uchar	tos;
	uchar	length[2];
	uchar	id[2];
	uchar	frag[2];
	uchar	ttl;
	uchar	proto;
	uchar	cksum[2];
	uchar	src[Pasize];
	uchar	dst[Pasize];

	uchar	icmptype;		/* Src port */
	uchar	icmpcode;		/* Dst port */
	uchar	icmpsum[2];		/* Checksum including header */

	uchar	icmpbody[10];		/* Depends on type */
};

struct	Ifc
{
	Lock;
	Queue*	reply;
	Filter	work[3];
	Filter	rate[3];
	ulong	rcverr;
	ulong	txerr;
	ulong	sumerr;
	ulong	rxpkt;
	ulong	txpkt;
	uchar	ea[Easize];		/* my ether address */
	uchar	ipa[Pasize];		/* my ip address, pulled from netdb */
	uchar	netgate[Pasize];	/* my ip gateway, pulled from netdb */
	ulong	ipaddr;
	ulong	mask;
	ulong	cmask;
	Ifc	*next;			/* List of configured interfaces */
};

extern	register	Mach*	m;
extern	register	User*	u;
extern  Talarm		talarm;

Conf	conf;
Cons	cons;
#define	MACHP(n)	((Mach*)(MACHADDR+n*BY2PG))

#pragma	varargck	type	"D"	Device*
#pragma	varargck	type	"T"	ulong
#pragma	varargck	type	"I"	uchar*
#pragma	varargck	type	"E"	uchar*
#pragma	varargck	type	"F"	Filter*
#pragma	varargck	type	"G"	int
