~kris/9p

9hist

4dd6ce204b7bffdb9d2917d7ab812bd2e74251df — David du Colombier 34 years ago ef9cf81
Plan 9 from Bell Labs 1991-11-15
M gnot/boot.h => gnot/boot.h +5 -5
@@ 4453,8 4453,8 @@ ulong bootcode[]={
	0x06e65742c,
	0x020286929,
	0x0696e636f,
	0x06e007474,
	0x079310023,
	0x06e006569,
	0x061310023,
	0x0772f6864,
	0x030006e65,
	0x07874206e,


@@ 4471,7 4471,7 @@ ulong bootcode[]={
	0x02c202865,
	0x029746865,
	0x0726e6574,
	0x000747479,
	0x000656961,
	0x030002377,
	0x0312f6864,
	0x031006174,


@@ 4485,7 4485,7 @@ ulong bootcode[]={
	0x039323030,
	0x020736572,
	0x069616c00,
	0x074747930,
	0x065696130,
	0x00023772f,
	0x068643000,
	0x061742674,


@@ 4504,7 4504,7 @@ ulong bootcode[]={
	0x06c2c2028,
	0x06929696e,
	0x0636f6e00,
	0x074747930,
	0x065696130,
	0x00023772f,
	0x068643000,
	0x073756e20,

M gnot/devduart.c => gnot/devduart.c +9 -9
@@ 608,13 608,13 @@ loop:

enum{
	Qdir=		0,
	Qtty0=		STREAMQID(0, Sdataqid),
	Qtty0ctl=	STREAMQID(0, Sctlqid),
	Qeia0=		STREAMQID(0, Sdataqid),
	Qeia0ctl=	STREAMQID(0, Sctlqid),
};

Dirtab duartdir[]={
	"tty0",		{Qtty0},	0,		0666,
	"tty0ctl",	{Qtty0ctl},	0,		0666,
	"eia0",		{Qeia0},	0,		0666,
	"eia0ctl",	{Qeia0ctl},	0,		0666,
};

#define	NDuartport	(sizeof duartdir/sizeof(Dirtab))


@@ 658,8 658,8 @@ void
duartstat(Chan *c, char *dp)
{
	switch(c->qid.path){
	case Qtty0:
		streamstat(c, dp, "tty0");
	case Qeia0:
		streamstat(c, dp, "eia0");
		break;
	default:
		devstat(c, dp, duartdir, NDuartport, devgen);


@@ 673,8 673,8 @@ duartopen(Chan *c, int omode)
	Duartport *dp;

	switch(c->qid.path){
	case Qtty0:
	case Qtty0ctl:
	case Qeia0:
	case Qeia0ctl:
		dp = &duartport[0];
		break;
	default:


@@ 712,7 712,7 @@ duartread(Chan *c, void *buf, long n, ulong offset)
	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, duartdir, NDuartport, devgen);
	case Qtty0ctl:
	case Qeia0ctl:
		if(offset)
			return 0;
		s = splhi();

M gnot/trap.c => gnot/trap.c +0 -2
@@ 137,8 137,6 @@ dumpregs(Ureg *ur)
	l = &ur->r0;
	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);

	dumpstack();
}

/*

M pc/clock.c => pc/clock.c +5 -6
@@ 87,11 87,10 @@ clock(Ureg *ur)
			else
				sched();
		}
		/*
		 *  notes for processes that might be spinning
		 *  in user mode.
		 */
		if((ur->cs&0xffff) == UESEL)
			notify(ur);
		if((ur->cs&0xffff) == UESEL){
			spllo();		/* in case we fault */
			(*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);	/* profiling clock */
			splhi();
		}
	}
}

M pc/devuart.c => pc/devuart.c +18 -18
@@ 557,17 557,17 @@ uartkproc(void *a)

enum{
	Qdir=		0,
	Qtty0=		STREAMQID(0, Sdataqid),
	Qtty0ctl=	STREAMQID(0, Sctlqid),
	Qtty1=		STREAMQID(1, Sdataqid),
	Qtty1ctl=	STREAMQID(1, Sctlqid),
	Qeia0=		STREAMQID(0, Sdataqid),
	Qeia0ctl=	STREAMQID(0, Sctlqid),
	Qeia1=		STREAMQID(1, Sdataqid),
	Qeia1ctl=	STREAMQID(1, Sctlqid),
};

Dirtab uartdir[]={
	"tty0",		{Qtty0},	0,		0666,
	"tty0ctl",	{Qtty0ctl},	0,		0666,
	"tty1",		{Qtty1},	0,		0666,
	"tty1ctl",	{Qtty1ctl},	0,		0666,
	"eia0",		{Qeia0},	0,		0666,
	"eia0ctl",	{Qeia0ctl},	0,		0666,
	"eia1",		{Qeia1},	0,		0666,
	"eia1ctl",	{Qeia1ctl},	0,		0666,
};

#define	NUart	(sizeof uartdir/sizeof(Dirtab))


@@ 618,11 618,11 @@ void
uartstat(Chan *c, char *dp)
{
	switch(c->qid.path){
	case Qtty0:
		streamstat(c, dp, "tty0");
	case Qeia0:
		streamstat(c, dp, "eia0");
		break;
	case Qtty1:
		streamstat(c, dp, "tty1");
	case Qeia1:
		streamstat(c, dp, "eia1");
		break;
	default:
		devstat(c, dp, uartdir, NUart, devgen);


@@ 636,12 636,12 @@ uartopen(Chan *c, int omode)
	Uart *up;

	switch(c->qid.path){
	case Qtty0:
	case Qtty0ctl:
	case Qeia0:
	case Qeia0ctl:
		up = &uart[0];
		break;
	case Qtty1:
	case Qtty1ctl:
	case Qeia1:
	case Qeia1ctl:
		up = &uart[1];
		break;
	default:


@@ 676,8 676,8 @@ uartread(Chan *c, void *buf, long n, ulong offset)
	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, uartdir, NUart, devgen);
	case Qtty1ctl:
	case Qtty0ctl:
	case Qeia1ctl:
	case Qeia0ctl:
		return 0;
	}
	return streamread(c, buf, n);

M port/devarp.c => port/devarp.c +5 -2
@@ 147,18 147,21 @@ arpopen(Chan *c, int omode)
void
arpcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
arpremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
arpwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}



@@ 212,7 215,7 @@ arpread(Chan *c, void *a, long n, ulong offset)
		sprint(buf, "hits: %d miss: %d failed: %d\n",
			arpstats.hit, arpstats.miss, arpstats.failed);

		return stringread(c, a, n, buf, offset);
		return stringread(a, n, buf, offset);
	default:
		n=0;
		break;


@@ 255,10 258,10 @@ arpwrite(Chan *c, char *a, long n, ulong offset)
	return n;
}


void
arpopn(Queue *q, Stream *s)
{
	USED(q, s);
}

void

M port/devbit.c => port/devbit.c +5 -0
@@ 240,18 240,21 @@ bitopen(Chan *c, int omode)
void
bitcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
bitremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
bitwstat(Chan *c, char *db)
{
	USED(c, db);
	error(Eperm);
}



@@ 1246,6 1249,7 @@ mouseputc(IOQ *q, int c)
	static int nb;
	static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7};

	USED(q);
	if((c&0xF0) == 0x80)
		nb=0;
	msg[nb] = c;


@@ 1264,5 1268,6 @@ mouseputc(IOQ *q, int c)
int
mousechanged(void *m)
{
	USED(m);
	return mouse.changed;
}

M port/devcons.c => port/devcons.c +4 -0
@@ 273,6 273,7 @@ kbdcr2nl(IOQ *q, int ch)
int
kbdputc(IOQ *q, int ch)
{
	USED(q);
	echo(ch);
	kbdq.c = ch;
	*kbdq.in++ = ch;


@@ 455,6 456,7 @@ consopen(Chan *c, int omode)
void
conscreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}



@@ 770,12 772,14 @@ conswrite(Chan *c, void *va, long n, ulong offset)
void
consremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
conswstat(Chan *c, char *dp)
{
	USED(c);
	error(Eperm);
}


M port/devdk.c => port/devdk.c +24 -4
@@ 14,6 14,10 @@ typedef struct Dkmsg	Dkmsg;
typedef struct Line	Line;
typedef struct Dk	Dk;

enum {
	Maxlines = 256,
};

/*
 *  types of possible dkcalls
 */


@@ 117,6 121,7 @@ struct Dk {
	int	closeall;	/* set when we receive a closeall message */
	Rendez	closeallr;	/* wait here for a closeall */
	Network	net;
	Netprot *prot;

	Block	*alloc;
};


@@ 256,7 261,7 @@ dkalloc(char *name, int ncsc, int lines)
	/*
	 *  allocate memory for line structures
	 */
	n = sizeof(Line*)*(dp->lines+1);
	n = sizeof(Line*)*(dp->lines);
	bp = allocb(n);
	if(bp->lim - bp->base < n){
		unlock(&dklock);


@@ 267,7 272,7 @@ dkalloc(char *name, int ncsc, int lines)
	bp->wptr += n;
	dp->alloc = bp;
	n = sizeof(Line)*(dp->lines);
	for(i = 0; i <= dp->lines; i++){
	for(i = 0; i < dp->lines; i++){
		if(bp->lim - bp->wptr < sizeof(Line)){
			bp = allocb(sizeof(Line)*n);
			memset(bp->base, 0, bp->lim-bp->base);


@@ 284,11 289,12 @@ dkalloc(char *name, int ncsc, int lines)
	 *  fill in the network structure
	 */
	dp->net.name = dp->name;
	dp->net.nconv = dp->lines+1;
	dp->net.nconv = dp->lines;
	dp->net.devp = &dkinfo;
	dp->net.protop = &urpinfo;
	dp->net.listen = dklisten;
	dp->net.clone = dkcloneline;
	dp->net.prot = dp->prot;
	dp->net.ninfo = 3;
	dp->net.info[0].name = "addr";
	dp->net.info[0].fill = dkfilladdr;


@@ 530,6 536,7 @@ dkstclose(Queue *q)
out:
	qlock(lp);
	lp->rq = 0;
	netdisown(&dp->net, lp->lineno);
	qunlock(lp);
}



@@ 695,7 702,10 @@ dkmuxconfig(Queue *q, Block *bp)
void
dkreset(void)
{
	int i;
	dk = (Dk*)ialloc(conf.dkif*sizeof(Dk), 0);
	for(i = 0; i < conf.dkif; i++)
		dk[i].prot = (Netprot*)ialloc(conf.nurp*sizeof(Netprot), 0);
	newqinfo(&dkmuxinfo);
}



@@ 827,7 837,7 @@ dkremove(Chan *c)
void	 
dkwstat(Chan *c, char *dp)
{
	error(Eperm);
	netwstat(c, dp, &dk[c->dev].net);
}

/*


@@ 852,6 862,10 @@ dkcloneline(Chan *c)
				continue;
			}
			lp->state = Lopened;

			/* current user becomes owner */
			netown(&dp->net, lp->lineno, u->p->user, 0);

			qunlock(lp);
			return lp->lineno;
		}


@@ 1125,9 1139,11 @@ dklisten(Chan *c)
	Line *lp;
	Dk *dp;
	int n, lineno, ts, window;
	int from;
	Chan *dc;

	dp = &dk[c->dev];
	from = STREAMID(c->qid.path);

	/*
	 *  open the data file


@@ 1270,6 1286,10 @@ dklisten(Chan *c)

		lp->timestamp = ts;
		lp->state = Lconnected;

		/* listener becomes owner */
		netown(&dp->net, lp->lineno, dp->prot[from].owner, 0);

		qunlock(lp);
		close(dc);
		poperror();

M port/devdup.c => port/devdup.c +5 -0
@@ 84,24 84,28 @@ dupopen(Chan *c, int omode)
void
dupcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
dupremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
dupwstat(Chan *c, char *dp)
{
	USED(c);
	error(Egreg);
}

void
dupclose(Chan *c)
{
	USED(c);
}

long


@@ 117,5 121,6 @@ dupread(Chan *c, void *va, long n, ulong offset)
long
dupwrite(Chan *c, void *va, long n, ulong offset)
{
	USED(c, va, n, offset);
	panic("dupwrite");
}

M port/devenv.c => port/devenv.c +2 -0
@@ 196,12 196,14 @@ envremove(Chan *c)
void
envwstat(Chan *c, char *db)
{
	USED(c, db);
	error(Eperm);
}

void
envclose(Chan * c)
{
	USED(c);
}

void

M port/devip.c => port/devip.c +20 -4
@@ 48,8 48,11 @@ ipinitifc(Ipifc *ifc, Qinfo *stproto, Ipconv *cp)
{
	int j;

	for(j = 0; j < conf.ip; j++, cp++)
	for(j = 0; j < conf.ip; j++, cp++){
		cp->index = j;
		cp->stproto = stproto;
		cp->ipinterface = ifc;
	}
	ifc->net.name = stproto->name;
	ifc->net.nconv = conf.ip;
	ifc->net.devp = &ipinfo;


@@ 57,6 60,7 @@ ipinitifc(Ipifc *ifc, Qinfo *stproto, Ipconv *cp)
	if(stproto != &udpinfo)
		ifc->net.listen = iplisten;
	ifc->net.clone = ipclonecon;
	ifc->net.prot = (Netprot *)ialloc(sizeof(Netprot) * conf.ip, 0);
	ifc->net.ninfo = 3;
	ifc->net.info[0].name = "remote";
	ifc->net.info[0].fill = ipremotefill;


@@ 136,16 140,17 @@ ipclonecon(Chan *c)
	Ipconv *new, *base;

	base = ipconv[c->dev];
	new = ipincoming(base);
	new = ipincoming(base, 0);
	if(new == 0)
		error(Enodev);
	return new - base;
}

Ipconv *
ipincoming(Ipconv *base)
ipincoming(Ipconv *base, Ipconv *from)
{
	Ipconv *new, *etab;
	Ipifc *ifc;

	etab = &base[conf.ip];
	for(new = base; new < etab; new++) {


@@ 156,6 161,13 @@ ipincoming(Ipconv *base)
				qunlock(new);
				continue;
			}
			ifc = base->ipinterface;
			if(from)
				/* copy ownership from listening channel */
				netown(&ifc->net, new->index, ifc->net.prot[from->index].owner, 0);
			else
				/* current user becomes owner */
				netown(&ifc->net, new->index, u->p->user, 0);
			new->ref = 1;
			qunlock(new);
			return new;


@@ 167,19 179,21 @@ ipincoming(Ipconv *base)
void
ipcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
ipremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
ipwstat(Chan *c, char *dp)
{
	error(Eperm);
	netwstat(c, dp, &ipifc[c->dev].net);
}

void


@@ 432,6 446,7 @@ udpstclose(Queue *q)
	ipc->ref = 0;

	closeipifc(ipc->ipinterface);
	netdisown(&ipc->ipinterface->net, ipc->index);
}

void


@@ 654,6 669,7 @@ tcpstclose(Queue *q)
		qunlock(tcb);
		break;
	}
	netdisown(&s->ipinterface->net, s->index);
}



M port/deviproute.c => port/deviproute.c +4 -0
@@ 244,24 244,28 @@ iprouteopen(Chan *c, int omode)
void
iproutecreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
iprouteremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
iproutewstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

void
iprouteclose(Chan *c)
{
	USED(c);
}

#define IPR_ENTRYLEN 54

M port/devkprof.c => port/devkprof.c +4 -0
@@ 86,24 86,28 @@ kprofopen(Chan *c, int omode)
void
kprofcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
kprofremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
kprofwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

void
kprofclose(Chan *c)
{
	USED(c);
}

long

M port/devlance.c => port/devlance.c +14 -1
@@ 94,6 94,7 @@ typedef struct {
	Lance;			/* host dependent lance params */
	int	prom;		/* number of promiscuous channels */
	Network	net;
	Netprot	prot[Ntypes];

	int	inited;
	uchar	*lmp;		/* location of parity test */


@@ 247,6 248,7 @@ lancestclose(Queue *q)
	et->q = 0;
	et->prom = 0;
	et->inuse = 0;
	netdisown(&l.net, et - l.e);
	qunlock(et);
}



@@ 257,6 259,7 @@ Proc *lanceout;
static int
isobuf(void *x)
{
	USED(x);
	return TSUCC(l.tc) != l.tl;
}
static void


@@ 379,6 382,7 @@ lancereset(void)
		l.net.listen = 0;
		l.net.clone = lanceclonecon;
		l.net.ninfo = 2;
		l.net.prot = l.prot;
		l.net.info[0].name = "stats";
		l.net.info[0].fill = lancestatsfill;
		l.net.info[1].name = "type";


@@ 549,6 553,7 @@ lanceopen(Chan *c, int omode)
void	 
lancecreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}



@@ 574,13 579,14 @@ lancewrite(Chan *c, void *a, long n, ulong offset)
void	 
lanceremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void	 
lancewstat(Chan *c, char *dp)
{
	error(Eperm);
	netwstat(c, dp, &l.net);
}

/*


@@ 591,12 597,14 @@ lancestatsfill(Chan *c, char* p, int n)
{
	char buf[256];

	USED(c);
	sprint(buf, "in: %d\nout: %d\ncrc errs %d\noverflows: %d\nframe errs %d\nbuff errs: %d\noerrs %d\naddr: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",
		l.inpackets, l.outpackets, l.crcs,
		l.overflows, l.frames, l.buffs, l.oerrs,
		l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);
	strncpy(p, buf, n);
}

static void
lancetypefill(Chan *c, char* p, int n)
{


@@ 613,6 621,7 @@ lanceclonecon(Chan *c)
{
	Ethertype *e;

	USED(c);
	for(e = l.e; e < &l.e[Ntypes]; e++){
		qlock(e);
		if(e->inuse || e->q){


@@ 620,6 629,7 @@ lanceclonecon(Chan *c)
			continue;
		}
		e->inuse = 1;
		netown(&l.net, e - l.e, u->p->user, 0);
		qunlock(e);
		return e - l.e;
	}


@@ 733,6 743,8 @@ static int
isinput(void *arg)
{
	Lancemem *lm = LANCEMEM;

	USED(arg);
	return l.self.first || (l.rl!=l.rc && (MPus(lm->rmr[l.rl].flags) & OWN)==0);
}



@@ 747,6 759,7 @@ lancekproc(void *arg)
	Msg *m;
	Block *bp;

	USED(arg);
	for(;;){
		qlock(&l.rlock);
		while(bp = getq(&l.self)){

M port/devmux.c => port/devmux.c +157 -68
@@ 15,13 15,16 @@ typedef struct Dtq Dtq;
enum
{
	Qdir	= 0,
	Qhead,
	Qhead	= 0,
	Qclone,
	Qoffset,
};

enum
{
	Nmux	=	20,
	Maxmsg	=	(32*1024),
	Flowctl	=	Maxmsg/2,
};

struct Dtq


@@ 31,6 34,9 @@ struct Dtq
	Lock	listlk;
	Block	*list;
	int	ndelim;
	int	nb;
	QLock	flow;
	Rendez	flowr;
};

struct Con


@@ 44,6 50,7 @@ struct Con
struct Mux
{
	Ref;
	int	type;
	char	name[NAMELEN];
	char	user[NAMELEN];
	ulong	perm;


@@ 56,9 63,12 @@ Mux	*muxes;

ulong	muxreadq(Mux *m, Dtq*, char*, ulong);
void	muxwriteq(Dtq*, char*, long, int, int);
void	muxflow(Dtq*);
Block  *muxclq(Dtq *q);

#define NMUX(c)		(((c->qid.path>>8)&0xffff)-1)
#define NQID(m, c)	(Qid){(m)<<8|(c)&0xff, 0}
#define NQID(m, c)	(Qid){(m+1)<<8|(c)&0xff, 0}
#define DQID(m)		(Qid){(m+1)<<8|CHDIR, 0}
#define NCON(c)		(c->qid.path&0xff)

int


@@ 68,6 78,7 @@ muxgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
	int mux;
	Con *cm;
	char buf[10];
	int nq;

	if(c->qid.path == CHDIR) {
		if(s >= conf.nmux)


@@ 76,7 87,7 @@ muxgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
		m = &muxes[s];
		if(m->name[0] == '\0')
			return 0;
		devdir(c, (Qid){CHDIR|((s+1)<<8), 0}, m->name, 0, m->user, m->perm, dp);
		devdir(c, DQID(s), m->name, 0, m->user, m->perm, dp);
		return 1;
	}



@@ 85,19 96,21 @@ muxgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)

	mux = NMUX(c);
	m = &muxes[mux];

	switch(s) {
	case Qhead:
		devdir(c, NQID(mux, Qhead), "head", m->headq.ndelim, m->user, m->perm, dp);
		devdir(c, NQID(mux, Qhead), "head", m->headq.nb, m->user, m->perm, dp);
		break;
	case Qclone:
		devdir(c, NQID(mux, Qclone), "clone", 0, m->user, m->perm, dp);
		break;
	default:
		cm = &m->connects[s-Qclone];
		nq = s-Qoffset;
		cm = &m->connects[nq];
		if(cm->ref == 0)
			return 0;
		sprint(buf, "%d", s-Qclone);
		devdir(c, NQID(mux, Qclone+s), buf, cm->conq.ndelim, cm->user, cm->perm, dp);
		sprint(buf, "%d", nq);
		devdir(c, NQID(mux, Qoffset+s), buf, cm->conq.nb, cm->user, cm->perm, dp);
		break;
	}
	return 1;


@@ 120,7 133,6 @@ muxattach(char *spec)
	Chan *c;

	c = devattach('m', spec);

	c->qid.path = CHDIR|Qdir;
	return c;
}


@@ 136,8 148,11 @@ muxclone(Chan *c, Chan *nc)

	m = &muxes[NMUX(c)];
	ncon = NCON(c);

	c = devclone(c, nc);

	if((c->flag&COPEN) == 0)
		return c;

	switch(ncon) {
	case Qhead:
		incref(m);


@@ 146,7 161,7 @@ muxclone(Chan *c, Chan *nc)
		break;
	default:
		lock(m);
		m->connects[ncon].ref++;
		m->connects[ncon-Qoffset].ref++;
		m->ref++;
		unlock(m);
	}


@@ 175,19 190,29 @@ muxopen(Chan *c, int omode)
{
	Mux *m;
	Con *cm, *e;
	int mux, ok;

	if(c->qid.path & CHDIR)
		return devopen(c, omode, 0, 0, muxgen);

	m = &muxes[NMUX(c)];
	mux = NMUX(c);
	m = &muxes[mux];
	switch(NCON(c)) {
	case Qhead:
		c = devopen(c, omode, 0, 0, muxgen);
		lock(m);
		if(m->headopen)
			ok = 0;
		else {
			ok = 1;
			m->headopen = 1;
			m->ref++;
		}
		unlock(m);
		if(!ok) {
			c->flag &= ~COPEN;
			errors("server channel busy");

		c = devopen(c, omode, 0, 0,muxgen);
		m->headopen = 1;
		incref(m);
		}
		break;
	case Qclone:
		if(m->headopen == 0)


@@ 203,18 228,20 @@ muxopen(Chan *c, int omode)
			unlock(m);
			errors("all cannels busy");
		}
		cm->ref++;
		cm->ref = 1;
		m->ref++;
		unlock(m);
		strncpy(cm->user, u->p->user, NAMELEN);
		cm->perm = 0600;
		c->qid = NQID(NMUX(c), cm-m->connects);
		c->qid = NQID(mux, (cm-m->connects)+Qoffset);
		break;
	default:
		c = devopen(c, omode, 0, 0,muxgen);
		cm = &m->connects[NCON(c)];
		c = devopen(c, omode, 0, 0, muxgen);
		cm = &m->connects[NCON(c)-Qoffset];
		lock(m);
		cm->ref++;
		incref(m);
		m->ref++;
		unlock(m);
		break;
	}



@@ 234,7 261,7 @@ muxcreate(Chan *c, char *name, int omode, ulong perm)

	m = muxes;
	for(e = &m[conf.nmux]; m < e; m++) {
		if(m->ref == 0 && canlock(m)) {
		if(m->name[0] == '\0' && m->ref == 0 && canlock(m)) {
			if(m->ref != 0) {
				unlock(m);
				continue;


@@ 291,7 318,6 @@ muxwstat(Chan *c, char *db)
	d.mode &= 0777;
	if(c->qid.path&CHDIR) {
		strcpy(m->name, d.name);
		strcpy(m->user, d.uid);
		m->perm = d.mode;
		return;
	}


@@ 303,7 329,7 @@ muxwstat(Chan *c, char *db)
		m->perm = d.mode;
		break;
	default:
		m->connects[nc].perm = d.mode;
		m->connects[nc-Qoffset].perm = d.mode;
		break;
	}
}


@@ 316,7 342,10 @@ muxclose(Chan *c)
	Mux *m;
	int nc;

	if(c->qid.path == CHDIR)
	if(c->qid.path&CHDIR)
		return;

	if((c->flag&COPEN) == 0)
		return;

	m = &muxes[NMUX(c)];


@@ 331,26 360,19 @@ muxclose(Chan *c)
			if(cm->ref)
				wakeup(&cm->conq.r);
		lock(m);
		if(--m->ref == 0) {
			f1 = m->headq.list;
			m->headq.list = 0;
		}
		if(--m->ref == 0)
			f1 = muxclq(&m->headq);
		unlock(m);
		break;
	case Qclone:
		panic("muxclose");
		break;
	default:
		lock(m);
		cm = &m->connects[nc];
		if(--cm->ref == 0) {
			f1 = cm->conq.list;
			cm->conq.list = 0;		
		}
		if(--m->ref == 0) {
			m->name[0] = '\0';
			f2 = m->headq.list;
			m->headq.list = 0;
		}
		cm = &m->connects[nc-Qoffset];
		if(--cm->ref == 0)
			f1 = muxclq(&cm->conq);
		if(--m->ref == 0)
			f1 = muxclq(&m->headq);
		unlock(m);
	}
	if(f1)


@@ 377,7 399,7 @@ muxread(Chan *c, void *va, long n, ulong offset)
	case Qclone:
		error(Eperm);
	default:
		cm = &m->connects[NCON(c)];
		cm = &m->connects[NCON(c)-Qoffset];
		bread = muxreadq(m, &cm->conq, va, n);
		break;
	}


@@ 390,7 412,7 @@ muxhdr(Mux *m, char *h)
{
	Con *c;

	if(h[0] != Tmux)
	if(h[0] != Tmux || h[2] != 0)
		error(Ebadmsg);

	c = &m->connects[h[1]];


@@ 410,11 432,14 @@ muxwrite(Chan *c, void *va, long n, ulong offset)
	Con *cm;
	int muxid;
	Block *f, *bp;
	char *a, hdr[2];
	char *a, hdr[3];

	if(c->qid.path & CHDIR)
	if(c->qid.path&CHDIR)
		error(Eisdir);

	if(n > Maxmsg)
		error(Etoobig);

	m = &muxes[NMUX(c)];
	switch(NCON(c)) {
	case Qclone:


@@ 435,7 460,7 @@ muxwrite(Chan *c, void *va, long n, ulong offset)
		if(m->headopen == 0)
			error(Ehungup);

		muxid = NCON(c);
		muxid = NCON(c)-Qoffset;
		muxwriteq(&m->headq, va, n, 1, muxid);
		break;
	}


@@ 447,7 472,7 @@ void
muxwriteq(Dtq *q, char *va, long n, int addid, int muxid)
{
	Block *head, *tail, *bp;
	ulong l;
	ulong l, bwrite;

	head = 0;
	SET(tail);


@@ 457,13 482,26 @@ muxwriteq(Dtq *q, char *va, long n, int addid, int muxid)
		nexterror();
	}

	bwrite = 0;
	while(n) {
		bp = allocb(n);
		bp->type = M_DATA;
		if(addid) {
			bp = allocb(n+3);
			bp->wptr[0] = Tmux;
			bp->wptr[1] = muxid;
			bp->wptr[2] = 0;
			bp->wptr += 3;
			bwrite += 3;
			addid = 0;
		}
		else
			bp = allocb(n);
		l = bp->lim - bp->wptr;
		if(l > n)
			l = n;
		memmove(bp->wptr, va, l);	/* Interruptable thru fault */
		va += l;
		bp->wptr += l;
		bwrite += l;
		n -= l;
		if(head == 0)
			head = bp;


@@ 473,16 511,45 @@ muxwriteq(Dtq *q, char *va, long n, int addid, int muxid)
	}
	poperror();
	tail->flags |= S_DELIM;

	if(q->nb > Flowctl)
		muxflow(q);

	lock(&q->listlk);
	for(tail = q->list; tail->next; tail = tail->next)
		;
	tail->next = head;
	if(q->list == 0)
		q->list = head;
	else {
		for(tail = q->list; tail->next; tail = tail->next)
			;
		tail->next = head;
	}
	q->ndelim++;
	q->nb += bwrite;
	unlock(&q->listlk);
	wakeup(&q->r);
}

int
nodata(Dtq *q)
muxflw(Dtq *q)
{
	return q->nb < Flowctl;
}

void
muxflow(Dtq *q)
{
	qlock(&q->flow);
	if(waserror()) {
		qunlock(&q->flow);
		nexterror();
	}
	sleep(&q->flowr, muxflw, q);
	poperror();
	qunlock(&q->flow);
}

int
havedata(Dtq *q)
{
	int n;



@@ 496,7 563,7 @@ ulong
muxreadq(Mux *m, Dtq *q, char *va, ulong n)
{
	int l, nread, gotdelim;
	Block *bp;
	Block *bp, *f1;

	qlock(&q->rd);
	bp = 0;


@@ 510,41 577,63 @@ muxreadq(Mux *m, Dtq *q, char *va, ulong n)
		unlock(&q->listlk);
		nexterror();
	}
	while(nodata(q))
		sleep(&q->r, nodata, q);

	if(m->headopen == 0)
		errors("server shutdown");
	while(!havedata(q)) {
		sleep(&q->r, havedata, q);
		if(m->headopen == 0)
			errors("server shutdown");
	}

	nread = 0;
	f1 = 0;
	lock(&q->listlk);
	while(n) {
		lock(&q->listlk);
		bp = q->list;
		q->list = bp->next;
		bp->next = 0;
		unlock(&q->listlk);

		if(f1) {
			freeb(f1);
			f1 = 0;
		}
		l = BLEN(bp);
		if(n < l)
			n = l;
		if(l > n)
			l = n;
		memmove(va, bp->rptr, l);	/* Interruptable thru fault */
		va += l;
		bp->rptr += l;
		n -= l;
		gotdelim = bp->flags&S_DELIM;
		nread += l;
		lock(&q->listlk);
		if(bp->rptr != bp->wptr) {
		if(bp->rptr == bp->wptr)
			f1 = bp;
		else {
			bp->next = q->list;
			q->list = bp;
		}
		else if(gotdelim)
		if(bp->flags&S_DELIM) {
			q->ndelim--;
		unlock(&q->listlk);
		if(bp->rptr == bp->wptr)
			freeb(bp);
		if(gotdelim)
			break;
		}
	}
	q->nb -= nread;
	unlock(&q->listlk);
	if(f1)
		freeb(f1);
	qunlock(&q->rd);
	poperror();
	if(q->nb < Flowctl)
		wakeup(&q->flowr);
	return nread;
}

Block *
muxclq(Dtq *q)
{
	Block *f;

	f = q->list;
	q->list = 0;
	q->nb = 0;
	q->ndelim = 0;
	return f;
}

M port/devnonet.c => port/devnonet.c +8 -4
@@ 303,6 303,7 @@ nonetopen(Chan *c, int omode)
void	 
nonetcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}



@@ 345,15 346,15 @@ nonetread(Chan *c, void *a, long n, ulong offset)
	cp = &noifc[c->dev].conv[STREAMID(c->qid.path)];
	switch(t){
	case Nraddrqid:
		return stringread(c, a, n, cp->raddr, offset);
		return stringread(a, n, cp->raddr, offset);
	case Naddrqid:
		return stringread(c, a, n, cp->addr, offset);
		return stringread(a, n, cp->addr, offset);
	case Nruserqid:
		return stringread(c, a, n, cp->ruser, offset);
		return stringread(a, n, cp->ruser, offset);
	case Nstatsqid:
		sprint(stats, "sent: %d\nrcved: %d\nrexmit: %d\nbad: %d\n",
			cp->sent, cp->rcvd, cp->rexmit, cp->bad);
		return stringread(c, a, n, stats, offset);
		return stringread(a, n, stats, offset);
	}
	error(Eperm);
}


@@ 401,12 402,14 @@ nonetwrite(Chan *c, void *a, long n, ulong offset)
void	 
nonetremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void	 
nonetwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}



@@ 1418,6 1421,7 @@ nokproc(void *arg)
	Noconv *cp, *ep;
	Nomsg *mp;

	USED(arg);
	cp = 0;
	ifc = 0;
	if(waserror()){

M port/devpipe.c => port/devpipe.c +3 -0
@@ 193,18 193,21 @@ pipeopen(Chan *c, int omode)
void
pipecreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Egreg);
}

void
piperemove(Chan *c)
{
	USED(c);
	error(Egreg);
}

void
pipewstat(Chan *c, char *db)
{
	USED(c, db);
	error(Eperm);
}


M port/devproc.c => port/devproc.c +3 -0
@@ 189,12 189,14 @@ procopen(Chan *c, int omode)
void
proccreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
procremove(Chan *c)
{
	USED(c);
	error(Eperm);
}



@@ 221,6 223,7 @@ procwstat(Chan *c, char *db)
void
procclose(Chan * c)
{
	USED(c);
}

long

M port/devroot.c => port/devroot.c +5 -0
@@ 101,6 101,7 @@ rootopen(Chan *c, int omode)
void	 
rootcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}



@@ 110,6 111,7 @@ rootcreate(Chan *c, char *name, int omode, ulong perm)
void	 
rootclose(Chan *c)
{
	USED(c);
}

#include	"boot.h"


@@ 156,17 158,20 @@ rootread(Chan *c, void *buf, long n, ulong offset)
long	 
rootwrite(Chan *c, void *buf, long n, ulong offset)
{
	USED(c, buf, n, offset);
	error(Egreg);
}

void	 
rootremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void	 
rootwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

M port/devscc.c => port/devscc.c +21 -18
@@ 524,17 524,17 @@ loop:

enum{
	Qdir=		0,
	Qtty0=		STREAMQID(0, Sdataqid),
	Qtty0ctl=	STREAMQID(0, Sctlqid),
	Qtty1=		STREAMQID(1, Sdataqid),
	Qtty1ctl=	STREAMQID(1, Sctlqid),
	Qeia0=		STREAMQID(0, Sdataqid),
	Qeia0ctl=	STREAMQID(0, Sctlqid),
	Qeia1=		STREAMQID(1, Sdataqid),
	Qeia1ctl=	STREAMQID(1, Sctlqid),
};

Dirtab sccdir[]={
	"tty0",		{Qtty0},	0,		0666,
	"tty0ctl",	{Qtty0ctl},	0,		0666,
	"tty1",		{Qtty1},	0,		0666,
	"tty1ctl",	{Qtty1ctl},	0,		0666,
	"eia0",		{Qeia0},	0,		0666,
	"eia0ctl",	{Qeia0ctl},	0,		0666,
	"eia1",		{Qeia1},	0,		0666,
	"eia1ctl",	{Qeia1ctl},	0,		0666,
};

#define	NSCC	(sizeof sccdir/sizeof(Dirtab))


@@ 585,11 585,11 @@ void
sccstat(Chan *c, char *dp)
{
	switch(c->qid.path){
	case Qtty0:
		streamstat(c, dp, "tty0");
	case Qeia0:
		streamstat(c, dp, "eia0");
		break;
	case Qtty1:
		streamstat(c, dp, "tty1");
	case Qeia1:
		streamstat(c, dp, "eia1");
		break;
	default:
		devstat(c, dp, sccdir, NSCC, devgen);


@@ 603,12 603,12 @@ sccopen(Chan *c, int omode)
	SCC *sp;

	switch(c->qid.path){
	case Qtty0:
	case Qtty0ctl:
	case Qeia0:
	case Qeia0ctl:
		sp = &scc[0];
		break;
	case Qtty1:
	case Qtty1ctl:
	case Qeia1:
	case Qeia1ctl:
		sp = &scc[1];
		break;
	default:


@@ 627,6 627,7 @@ sccopen(Chan *c, int omode)
void
scccreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}



@@ 645,10 646,10 @@ sccread(Chan *c, void *buf, long n, ulong offset)
	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, sccdir, NSCC, devgen);
	case Qtty1ctl:
	case Qeia1ctl:
		++sp;
		/* fall through */
	case Qtty0ctl:
	case Qeia0ctl:
		if(offset)
			return 0;
		s = splhi();


@@ 668,11 669,13 @@ sccwrite(Chan *c, void *va, long n, ulong offset)
void
sccremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
sccwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

M port/devsrv.c => port/devsrv.c +2 -0
@@ 150,12 150,14 @@ srvremove(Chan *c)
void
srvwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Egreg);
}

void
srvclose(Chan *c)
{
	USED(c);
}

long

M port/ipdat.h => port/ipdat.h +2 -1
@@ 264,6 264,7 @@ struct Ipconv
{
	QLock;				/* Ref count lock */
	int 	ref;
	int	index;
	Qinfo	*stproto;		/* Stream protocol for this device */
	Ipaddr	dst;			/* Destination from connect */
	Port	psrc;			/* Source port */


@@ 450,7 451,7 @@ int	seq_gt(int, int);
void	appendb(Block **, Block *);
Ipconv	*ip_conn(Ipconv *, Port, Port, Ipaddr dest, char proto);
void	ipmkdir(Qinfo *, Dirtab *, Ipconv *);
Ipconv	*ipincoming(Ipconv*);
Ipconv	*ipincoming(Ipconv*, Ipconv*);
int	inb_window(Tcpctl *, int);
Block	*htontcp(Tcp *, Block *, Tcphdr *);
void	start_timer(Timer *);

M port/net.c => port/net.c +91 -14
@@ 25,6 25,11 @@ netgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
	Qid q;
	char buf[32];
	Network *np = vp;
	int t;
	int id;
	Netprot *p;
	int perm;
	char *o;

	q.vers = 0;



@@ 34,7 39,7 @@ netgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
		case 0:
			q.path = CHDIR | Q2nd;
			strcpy(buf, np->name);
			devdir(c, q, buf, 0, eve, 0666, dp);
			devdir(c, q, buf, 0, eve, 0555, dp);
			break;
		default:
			return -1;


@@ 43,41 48,51 @@ netgen(Chan *c, void *vp, int ntab, int i, Dir *dp)
	}

	/* second level contains clone plus all the conversations */
	if(STREAMTYPE(c->qid.path) == Q2nd){
	t = STREAMTYPE(c->qid.path);
	if(t == Q2nd || t == Qclone){
		if(i == 0){
			q.path = Qclone;
			devdir(c, q, "clone", 0, eve, 0666, dp);
		}else if(i <= np->nconv){
			q.path = CHDIR|STREAMQID(i-1, Q3rd);
			sprint(buf, "%d", i-1);
			devdir(c, q, buf, 0, eve, 0666, dp);
			devdir(c, q, buf, 0, eve, 0555, dp);
		}else
			return -1;
		return 1;
	}

	/* third level depends on the number of info files */
	id = STREAMID(c->qid.path);
	p = &np->prot[id];
	if(*p->owner){
		o = p->owner;
		perm = p->mode;
	} else {
		o = eve;
		perm = 0666;
	}
	switch(i){
	case 0:
		q.path = STREAMQID(STREAMID(c->qid.path), Sdataqid);
		devdir(c, q, "data", 0, eve, 0666, dp);
		devdir(c, q, "data", 0, o, perm, dp);
		break;
	case 1:
		q.path = STREAMQID(STREAMID(c->qid.path), Sctlqid);
		devdir(c, q, "ctl", 0, eve, 0666, dp);
		devdir(c, q, "ctl", 0, o, perm, dp);
		break;
	case 2:
		if(np->listen == 0)
			return 0;
		q.path = STREAMQID(STREAMID(c->qid.path), Qlisten);
		devdir(c, q, "listen", 0, eve, 0666, dp);
		devdir(c, q, "listen", 0, o, perm, dp);
		break;
	default:
		i -= 3;
		if(i >= np->ninfo)
			return -1;
		q.path = STREAMQID(STREAMID(c->qid.path), Qinf+i);
		devdir(c, q, np->info[i].name, 0, eve, 0666, dp);
		devdir(c, q, np->info[i].name, 0, eve, 0444, dp);
		break;
	}
	return 1;


@@ 117,7 132,7 @@ netstat(Chan *c, char *db, Network *np)
			 * here, which is good because we've lost the name by now.
			 */
			if(c->qid.path & CHDIR){
				devdir(c, c->qid, ".", 0L, eve, CHDIR|0700, &dir);
				devdir(c, c->qid, ".", 0L, eve, CHDIR|0555, &dir);
				convD2M(&dir, db);
				return;
			}


@@ 134,10 149,28 @@ netstat(Chan *c, char *db, Network *np)
		}
}

void
netwstat(Chan *c, char *db, Network *np)
{
	Dir dir;
	Netprot *p;

	p = &np->prot[STREAMID(c->qid.path)];
	lock(np);
	if(strncmp(p->owner, u->p->user, NAMELEN)){
		unlock(np);
		error(Eperm);
	}
	convM2D(db, &dir);
	strncpy(p->owner, dir.uid, NAMELEN);
	p->mode = dir.mode;
	unlock(np);
}

Chan *
netopen(Chan *c, int omode, Network *np)
{
	int conv;
	int id;

	if(c->qid.path & CHDIR){
		if(omode != OREAD)


@@ 146,14 179,19 @@ netopen(Chan *c, int omode, Network *np)
		switch(STREAMTYPE(c->qid.path)){
		case Sdataqid:
		case Sctlqid:
			id = STREAMID(c->qid.path);
			if(netown(np, id, u->p->user, omode&7) < 0)
				error(Eperm);
			break;
		case Qlisten:
			conv = (*np->listen)(c);
			c->qid.path = STREAMQID(conv, Sctlqid);
			streamopen(c, np->devp);
			id = (*np->listen)(c);
			streamclose(c);
			c->qid.path = STREAMQID(id, Sctlqid);
			break;
		case Qclone:
			conv = (*np->clone)(c);
			c->qid.path = STREAMQID(conv, Sctlqid);
			id = (*np->clone)(c);
			c->qid.path = STREAMQID(id, Sctlqid);
			break;
		default:
			if(omode != OREAD)


@@ 191,5 229,44 @@ netread(Chan *c, void *a, long n, ulong offset, Network *np)
		error(Ebadusefd);

	(*np->info[t-Qinf].fill)(c, buf, sizeof(buf));
	return stringread(c, a, n, buf, offset);
	return stringread(a, n, buf, offset);
}

int
netown(Network *np, int id, char *o, int omode)
{
	static int access[] = { 0400, 0200, 0600, 0100 };
	Netprot *p;
	int mode;
	int t;

	p = &np->prot[id];
	lock(np);
	if(*p->owner){
		if(strncmp(o, p->owner, NAMELEN) == 0)	/* User */
			mode = p->mode;
		else if(strncmp(o, eve, NAMELEN) == 0)	/* Bootes is group */
			mode = p->mode<<3;
		else
			mode = p->mode<<6;		/* Other */

		t = access[omode&3];
		if((t & mode) == t){
			unlock(np);
			return 0;
		} else {
			unlock(np);
			return -1;
		}
	}
	strncpy(p->owner, o, NAMELEN);
	np->prot[id].mode = 0660;
	unlock(np);
	return 0;
}

void
netdisown(Network *np, int id)
{
	*np->prot[id].owner = 0;
}

M port/page.c => port/page.c +1 -0
@@ 223,6 223,7 @@ newpage(int clear, Segment **s, ulong va)
int
ispages(void *p)
{
	USED(p);
	return palloc.freecount >= HIGHWATER;
}


M port/portdat.h => port/portdat.h +11 -3
@@ 10,13 10,14 @@ typedef struct Env	Env;
typedef struct Envval	Envval;
typedef struct Etherpkt	Etherpkt;
typedef struct Fgrp	Fgrp;
typedef struct Ifile	Ifile;
typedef struct Image	Image;
typedef struct IOQ	IOQ;
typedef struct KIOQ	KIOQ;
typedef struct List	List;
typedef struct Mount	Mount;
typedef struct Mhead	Mhead;
typedef struct Netinf	Netinf;
typedef struct Netprot	Netprot;
typedef struct Network	Network;
typedef struct Note	Note;
typedef struct Page	Page;


@@ 622,13 623,19 @@ enum {
/*
 *  a multiplexed network
 */
struct Ifile
struct Netprot
{
	ulong	mode;
	char	owner[NAMELEN];
};
struct Netinf
{
	char	*name;
	void	(*fill)(Chan*, char*, int);
};
struct Network
{
	Lock;
	char	*name;
	int	nconv;			/* max # of conversations */
	Qinfo	*devp;			/* device end line disc */


@@ 636,7 643,8 @@ struct Network
	int	(*listen)(Chan*);
	int	(*clone)(Chan*);
	int	ninfo;
	Ifile	info[5];
	Netinf	info[5];
	Netprot	*prot;			/* protections */
};
#define MAJOR(q) ((q) >> 8)
#define MINOR(q) ((q) & 0xff)

M port/portfns.h => port/portfns.h +4 -4
@@ 1,7 1,4 @@

#define	SET(x)	x = 0
#define	USED(x)	if(x)

Alarm*	alarm(int, void (*)(Alarm*), void*);
void	alarminit(void);
Block*	allocb(ulong);


@@ 123,11 120,14 @@ void	mouseclock(void);
int	mouseputc(IOQ*, int);
Chan*	namec(char*, int, int, ulong);
void	nameok(char*);
void	netdisown(Network*, int);
int	netgen(Chan*, void*, int, int, Dir*);
Chan*	netopen(Chan*, int, Network*);
int	netown(Network*, int, char*, int);
long	netread(Chan*, void*, long, ulong, Network*);
void	netstat(Chan*, char*, Network*);
int	netwalk(Chan*, char*, Network*);
void	netwstat(Chan*, char*, Network*);
Alarm*	newalarm(void);
Chan*	newchan(void);
Egrp*	newegrp(void);


@@ 224,7 224,7 @@ int	streamparse(char*, Block*);
long	streamread(Chan*, void*, long);
void	streamstat(Chan*, char*, char*);
long	streamwrite(Chan*, void*, long, int);
long	stringread(Chan*, void*, long, char*, ulong);
long	stringread(void*, long, char*, ulong);
void	swapinit(void);
long	syscall(Ureg*);
void	tcpinit(void);

M port/print.c => port/print.c +5 -0
@@ 240,6 240,8 @@ dconv(Op *op)
static	int
hconv(Op *op)
{

	USED(op);
	return -FSHORT;
}



@@ 247,6 249,7 @@ static	int
lconv(Op *op)
{

	USED(op);
	return -FLONG;
}



@@ 268,6 271,8 @@ sconv(Op *op)
static	int
uconv(Op *op)
{

	USED(op);
	return -FUNSIGN;
}


M port/proc.c => port/proc.c +2 -4
@@ 384,9 384,6 @@ postnote(Proc *p, int dolock, char *n, int flag)
	Rendez *r;
	Proc *d, **l;

	SET(k);
	USED(k);

	if(dolock)
		lock(&p->debug);



@@ 396,10 393,11 @@ postnote(Proc *p, int dolock, char *n, int flag)
		errors("noted process disappeared");
	}

	SET(k);
	if(u == 0 || p != u->p){
		k = kmap(p->upage);
		up = (User*)VA(k);
	}else 
	}else
		up = u;



M port/segment.c => port/segment.c +1 -0
@@ 418,6 418,7 @@ segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
	ulong newtop;
	int i, sno;

	USED(p);
	if(va&KZERO)					/* BUG: Only ok for now */
		errors("bad virtual address");


M port/stil.c => port/stil.c +3 -2
@@ 1,4 1,4 @@
/*

/*
 * stil - Internet link protocol
 */
#include	"u.h"


@@ 93,6 93,7 @@ ilclose(Queue *q)
		ic->state = Ilclosed;
		break;
	}
	netdisown(&s->ipinterface->net, s->index);
}

void


@@ 256,7 257,7 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
		if(s->ilctl.state == Illistening)
		if(s->pdst == 0)
		if(s->dst == 0) {
			new = ipincoming(ipc);
			new = ipincoming(ipc, s);
			if(new == 0)
				goto reset;


M port/stip.c => port/stip.c +1 -0
@@ 131,6 131,7 @@ newipifc(uchar ptcl, void (*recvfun)(Ipconv *, Block *bp),
static void
ipetherclose(Queue *q)
{
	USED(q);
}

void

M port/stream.c => port/stream.c +3 -2
@@ 689,6 689,7 @@ prepend(Block *bp, int n)
void
nullput(Queue *q, Block *bp)
{
	USED(q);
	if(bp->type == M_HANGUP)
		freeb(bp);
	else {


@@ 1065,7 1066,7 @@ stputq(Queue *q, Block *bp)
 *  read a string.  update the offset accordingly.
 */
long
stringread(Chan *c, uchar *buf, long n, char *str, ulong offset)
stringread(uchar *buf, long n, char *str, ulong offset)
{
	long i;



@@ 1092,7 1093,7 @@ streamctlread(Chan *c, void *vbuf, long n)
	s = c->stream;
	if(STREAMTYPE(c->qid.path) == Sctlqid){
		sprint(num, "%d", s->id);
		return stringread(c, buf, n, num, c->offset);
		return stringread(buf, n, num, c->offset);
	} else {
		if(CHDIR & c->qid.path)
			return devdirread(c, vbuf, n, 0, 0, streamgen);

M port/sturp.c => port/sturp.c +1 -1
@@ 167,7 167,7 @@ urpopen(Queue *q, Stream *s)
	if(up == &urp[conf.nurp]){
		q->ptr = 0;
		WR(q)->ptr = 0;
		error(Egreg);
		errors("out of urp structures");
	}

	q->ptr = q->other->ptr = up;

M port/swap.c => port/swap.c +2 -0
@@ 103,6 103,7 @@ pager(void *junk)
	Segment *s;
	int i;

	USED(junk);
	p = proctab(0);
	ep = &p[conf.nproc];
	for(;;) {


@@ 320,6 321,7 @@ executeio(void)
int
needpages(void *p)
{
	USED(p);
	return palloc.freecount < HIGHWATER+MAXHEADROOM;
}


M port/sysproc.c => port/sysproc.c +5 -0
@@ 21,6 21,7 @@ sysr1(ulong *arg)
long
sysfork(ulong *arg)
{
	USED(arg);
	return rfork(Forkfd);
}



@@ 393,6 394,7 @@ shargs(char *s, int n, char **ap)
int
return0(void *a)
{
	USED(a);
	return 0;
}



@@ 443,6 445,7 @@ syswait(ulong *arg)
long
sysdeath(ulong *arg)
{
	USED(arg);
	pprint("deprecated system call");
	pexit("Suicide", 0);
}


@@ 500,6 503,7 @@ sysforkpgrp(ulong *arg)
long
sysnotify(ulong *arg)
{
	USED(arg);
	if(arg[0] != 0)
		validaddr(arg[0], sizeof(ulong), 0);
	u->notify = (int(*)(void*, char*))(arg[0]);


@@ 509,6 513,7 @@ sysnotify(ulong *arg)
long
sysnoted(ulong *arg)
{
	USED(arg);
	if(u->notified == 0)
		error(Egreg);
	return 0;

M port/tcpinput.c => port/tcpinput.c +1 -1
@@ 81,7 81,7 @@ tcp_input(Ipconv *ipc, Block *bp)
				if(s->curlog >= s->backlog)
					goto clear;

				new = ipincoming(ipc);
				new = ipincoming(ipc, s);
				if(new == 0)
					goto clear;


M port/tcptimer.c => port/tcptimer.c +1 -0
@@ 19,6 19,7 @@ tcpackproc(void *junk)
	Timer *t,*tp;
	Timer *expired;

	USED(junk);
	for(;;) {
		expired = 0;


M power/devduart.c => power/devduart.c +4 -4
@@ 696,8 696,8 @@ duartreset(void)
	nduartport = 2*conf.nmach;
	duartdir = ialloc(nduartport*2*sizeof(Dirtab), 0);
	for(i = 0; i < nduartport; i++){
		sprint(duartdir[2*i].name, "tty%d", i);
		sprint(duartdir[2*i+1].name, "tty%dctl", i);
		sprint(duartdir[2*i].name, "eia%d", i);
		sprint(duartdir[2*i+1].name, "eia%dctl", i);
		duartdir[2*i].length = duartdir[2*i+1].length = 0;
		duartdir[2*i].perm = duartdir[2*i+1].perm = 0666;
		duartdir[2*i].qid.path = STREAMQID(i, Sdataqid);


@@ 745,7 745,7 @@ duartstat(Chan *c, char *dp)
{
	switch(STREAMTYPE(c->qid.path)){
	case Sdataqid:
		streamstat(c, dp, "tty0");
		streamstat(c, dp, "eia0");
		break;
	default:
		devstat(c, dp, duartdir, 2*nduartport, devgen);


@@ 779,7 779,7 @@ duartopen(Chan *c, int omode)
void
duartcreate(Chan *c, char *name, int omode, ulong perm)
{
	errors("only God can create a tty");
	errors(Eperm);
}

void

M power/main.c => power/main.c +1 -1
@@ 578,6 578,7 @@ confinit(void)
	conf.nnoifc = 1;
	conf.nnoconv = 32;
	conf.nurp = 25;
	conf.dkif = 1;
	conf.nqueue = 5 * conf.nstream;
	conf.nblock = 10 * conf.nstream;
	conf.ipif = 8;


@@ 593,7 594,6 @@ confinit(void)

	conf.copymode = 1;		/* copy on reference */
	conf.cntrlp = 1;
	conf.dkif = 2;
}

/*

M ss/clock.c => ss/clock.c +1 -1
@@ 13,7 13,7 @@ delay(int ms)
	ulong t, *p;
	int i;

	ms *= 2000;	/* experimentally determined */
	ms *= 3000;	/* experimentally determined */
	for(i=0; i<ms; i++)
		;
}

M ss/dat.h => ss/dat.h +1 -0
@@ 52,6 52,7 @@ struct	FPsave
{
	long	fsr;
	long	fpreg[32];
	long	pad;		/* so fsr can be guaranteed at 4 mod 8 */
};

struct Conf

M ss/l.s => ss/l.s +11 -5
@@ 468,10 468,15 @@ TEXT	putsegm(SB), $0
	MOVW	R8, (R7, 3)
	RETURN

/*
 * in savefpregs and restfpregs, incoming R7 points to doubleword
 * below where F0 will go; doubleword align in and backfill FSR
 */
TEXT	savefpregs(SB), $0

	MOVW	FSR, 0(R7)
	ADD	$4, R7		/* assumes R7 is now MOVD-aligned */
	ADD	$8, R7
	ANDN	$7, R7		/* now MOVD-aligned */
	MOVW	FSR, -4(R7)

	MOVD	F0, (0*4)(R7)
	MOVD	F2, (2*4)(R7)


@@ 501,10 506,11 @@ TEXT	restfpregs(SB), $0
	OR	$PSREF, R8
	MOVW	R8, PSR

	NOOP
	ADD	$8, R7
	ANDN	$7, R7		/* now MOVD-aligned */
	OR	R0, R0

	MOVW	(R7), FSR
	ADD	$4, R7		/* assumes R7 is now MOVD-aligned */
	MOVW	-4(R7), FSR

	MOVD	(0*4)(R7), F0
	MOVD	(2*4)(R7), F2

M ss/main.c => ss/main.c +0 -2
@@ 40,8 40,6 @@ main(void)
	alarminit();
	chandevreset();
	streaminit();
/*	serviceinit(); /**/
/*	filsysinit(); /**/
	pageinit();
	userinit();
	clockinit();

M ss/trap.c => ss/trap.c +1 -1
@@ 414,7 414,7 @@ setregisters(Ureg *xp, char *pureg, char *uva, int n)
{
	ulong psr;

	status = xp->psr;
	psr = xp->psr;
	memmove(pureg, uva, n);
	xp->psr = psr;
}