~kris/9p

9hist

f92bbf246edd34b6643f99f407ed43f8d42b5cb6 — David du Colombier 34 years ago a029b71
Plan 9 from Bell Labs 1991-11-06
M port/devXXX.c => port/devXXX.c +2 -2
@@ 91,7 91,7 @@ XXXclose(Chan *c)
}

long
XXXread(Chan *c, void *a, long n)
XXXread(Chan *c, void *a, long n, ulong offset)
{
	switch((int)(c->qid.path&~CHDIR)){
	case XXXdirqid:


@@ 106,7 106,7 @@ XXXread(Chan *c, void *a, long n)
}

long
XXXwrite(Chan *c, char *a, long n)
XXXwrite(Chan *c, char *a, long n, ulong offset)
{
	switch((int)(c->qid.path&~CHDIR)){
	case XXXdataqid:

M port/devlance.c => port/devlance.c +107 -31
@@ 109,6 109,8 @@ typedef struct {
	int	debug;
	int	kstarted;

	Queue	self;	/* packets turned around at the interface */

	/* sadistics */

	int	inpackets;


@@ 185,6 187,7 @@ static SoftLance l;
static void lancekproc(void *);
static void lancestart(int, int);
static void lancedump(void);
static void lanceup(Etherpkt*, int);

/*
 *  lance stream module definition


@@ 241,6 244,45 @@ lancestclose(Queue *q)
}

/*
 *  expand a block list to be one byte, len bytes long
 */
static Block*
expandb(Block *bp, int len)
{
	Block *nbp, *new;
	int i;

	new = allocb(len);
	if(new == 0){
		freeb(bp);
		return 0;
	}

	/*
	 *  copy bytes into new block
	 */
	for(nbp = bp; len>0 && nbp; nbp = nbp->next){
		i = BLEN(bp);
		if(i > len) {
			memmove(new->wptr, nbp->rptr, len);
			new->wptr += len;
			break;
		} else {
			memmove(new->wptr, nbp->rptr, i);
			new->wptr += i;
			len -= i;
		}
	}
	if(len){
		memset(new->wptr, 0, len);
		new->wptr += len;
	}
	freeb(bp);
	return new;

}

/*
 *  the ``connect'' control message specifyies the type
 */
Proc *lanceout;


@@ 275,6 317,27 @@ lanceoput(Queue *q, Block *bp )
	}

	/*
	 *  give packet a local address, return upstream if destined for
	 *  this machine.
	 */
	if(BLEN(bp) < ETHERHDRSIZE){
		bp = pullup(bp, ETHERHDRSIZE);
		if(bp == 0)
			return;
	}
	p = (Etherpkt *)bp->rptr;
	memmove(p->s, l.ea, sizeof(l.ea));
	if(memcmp(l.ea, p->d, sizeof(l.ea)) == 0){
		len = blen(bp);
		bp = expandb(bp, len >= 60 ? len : 60);
		if(bp){
			putq(&l.self, bp);
			wakeup(&l.rr);
		}
		return;
	}

	/*
	 *  only one transmitter at a time
	 */
	qlock(&l.tlock);


@@ 305,11 368,6 @@ lanceoput(Queue *q, Block *bp )
	}

	/*
	 *  give packet a local address
	 */
	memmove(p->s, l.ea, sizeof(l.ea));

	/*
	 *  pad the packet (zero the pad)
	 */
	if(len < 60){


@@ 671,27 729,47 @@ lanceintr(void)
/*
 *  send a packet upstream
 */
void
lanceup(Ethertype *e, Etherpkt *p, int len)
static void
lanceup(Etherpkt *p, int len)
{
	Block *bp;
	Ethertype *e;
	int t;

	/*
	 *  only a trace channel gets packets destined for other machines
	 */
	if(e->type != -1 && p->d[0]!=0xff && memcmp(p->d, l.ea, sizeof(p->d))!=0)
		return;

	if(waserror())
		return;
	if(e->q && e->q->next->len<=Streamhi){
		bp = allocb(len);
		memmove(bp->rptr, (uchar *)p, len);
		bp->wptr += len;
		bp->flags |= S_DELIM;
		PUTNEXT(e->q, bp);
	t = (p->type[0]<<8) | p->type[1];
	for(e = &l.e[0]; e < &l.e[Ntypes]; e++){
		/*
		 *  check before locking just to save a lock
		 */
		if(e->q==0 || (t!=e->type && e->type!=-1))
			continue;

		/*
		 *  only a trace channel gets packets destined for other machines
		 */
		if(e->type!=-1 && p->d[0]!=0xff && memcmp(p->d, l.ea, sizeof(p->d))!=0)
			continue;

		/*
		 *  check after locking to make sure things didn't
		 *  change under foot
		 */
		if(!canqlock(e))
			continue;
		if(e->q==0 || e->q->next->len>Streamhi || (t!=e->type && e->type!=-1)){
			qunlock(e);
			continue;
		}
		if(!waserror()){
			bp = allocb(len);
			memmove(bp->rptr, (uchar *)p, len);
			bp->wptr += len;
			bp->flags |= S_DELIM;
			PUTNEXT(e->q, bp);
		}
		poperror();
		qunlock(e);
	}
	poperror();
}

/*


@@ 701,7 779,7 @@ static int
isinput(void *arg)
{
	Lancemem *lm = LANCEMEM;
	return l.rl!=l.rc && (MPus(lm->rmr[l.rl].flags) & OWN)==0;
	return l.self.first || (l.rl!=l.rc && (MPus(lm->rmr[l.rl].flags) & OWN)==0);
}

static void


@@ 713,9 791,14 @@ lancekproc(void *arg)
	int t;
	Lancemem *lm = LANCEMEM;
	Msg *m;
	Block *bp;

	for(;;){
		qlock(&l.rlock);
		while(bp = getq(&l.self)){
			lanceup((Etherpkt*)bp->rptr, BLEN(bp));
			freeb(bp);
		}
		for(; l.rl!=l.rc && (MPus(lm->rmr[l.rl].flags) & OWN)==0 ; l.rl=RSUCC(l.rl)){
			l.inpackets++;
			m = &(lm->rmr[l.rl]);


@@ 736,15 819,8 @@ lancekproc(void *arg)
			 *  stuff packet up each queue that wants it
			 */
			p = &l.rp[l.rl];
			t = (p->type[0]<<8) | p->type[1];
			len = MPus(m->cntflags) - 4;
			for(e = &l.e[0]; e < &l.e[Ntypes]; e++){
				if(e->q!=0 && (t==e->type||e->type==-1) && canqlock(e)){
					if(t==e->type||e->type==-1)
						lanceup(e, p, len);
					qunlock(e);
				}
			}
			lanceup(p, len);

stage:
			/*

M port/devproc.c => port/devproc.c +1 -2
@@ 111,8 111,7 @@ procclone(Chan *c, Chan *nc)
int
procwalk(Chan *c, char *name)
{
	if(name[0] == '.' && name[1] == '.' &&
	   name[2] == '\0') {
	if(strcmp(name, "..") == 0) {
		c->qid.path = Qdir|CHDIR;
		return 1;
	}

M port/ipdat.h => port/ipdat.h +1 -0
@@ 104,6 104,7 @@ struct Ilcb				/* Control block */
	ulong	sent;
	ulong	recvd;
	ulong	start;
	ulong	rstart;
	ulong	lastack;
	int	timeout;
	int	window;

A port/netXXX.c => port/netXXX.c +108 -0
@@ 0,0 1,108 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

static void nulloput(Queue*, Block*);
static void protooput(Queue*, Block*);
static void protoiput(Queue*, Block*);

static Qinfo XXXprotold =
{
	protoiput,
	protooput,
	0,
	0,
	"proto",
	0
};

static Qinfo XXXmuxld =
{
	0,
	nulloput,
	0,
	0,
	"mux"
};

static void
protooput(Queue *q, Block *bp)
{
	PUTNEXT(q, bp);
}

static void
protoiput(Queue *q, Block *bp)
{
	PUTNEXT(q, bp);
}

static void
nulloput(Queue *q, Block *bp)
{
	freeb(bp);
}

static void XXXaddr(Chan*, char*, int);
static void XXXother(Chan*, char*, int);
static void XXXraddr(Chan*, char*, int);
static void XXXruser(Chan*, char*, int);
static int XXXclone(Chan*);
static void XXXconnect(Chan*, char*);

Network netXXX =
{
	"XXX",
	4,
	32,			/* # conversations */
	&XXXmuxld,
	&XXXprotold,
	0,			/* no listener */
	XXXclone,
	XXXconnect,
	0,			/* no announces */
	4,			/* info files */
	{ { "addr",	XXXaddr, },
	  { "other",	XXXother, },
	  { "raddr",	XXXraddr, },
	  { "ruser",	XXXruser, },
	},
};

static void
XXXaddr(Chan *c, char *buf, int len)
{
	strncpy(buf, "my address", len-1);
}

static void
XXXother(Chan *c, char *buf, int len)
{
	strncpy(buf, "other stuff", len-1);
}

static void
XXXraddr(Chan *c, char *buf, int len)
{
	strncpy(buf, "remote address", len-1);
}

static void
XXXruser(Chan *c, char *buf, int len)
{
	strncpy(buf, "remote user", len-1);
}

static int
XXXclone(Chan *c)
{
	return 5;
}

static void
XXXconnect(Chan *c, char *dest)
{
}

M port/portdat.h => port/portdat.h +28 -0
@@ 10,12 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 Network	Network;
typedef struct Note	Note;
typedef struct Page	Page;
typedef struct Palloc	Palloc;


@@ 611,6 613,32 @@ enum {
	Streambhi= 32,			/* block count high water mark */
};

/*
 *  a multiplexed network
 */
struct Ifile
{
	char	*name;
	void	(*fill)(Chan*, char*, int);
};
struct Network
{
	char	*name;
	int	nif;			/* max # of interfaces */
	int	nconv;			/* max # of conversations */
	Qinfo	*devp;			/* device end line disc */
	Qinfo	*protop;		/* protocol line disc */
	int	(*listen)(Chan*);
	int	(*clone)(Chan*);
	void	(*connect)(Chan*, char*);
	void	(*announce)(Chan*, char*);
	int	ninfo;
	Ifile	info[5];
};
#define MAJOR(q) ((q) >> 8)
#define MINOR(q) ((q) & 0xff)
#define DEVICE(a,i) (((a)<<8) | (i))

#define MAXSYSARG	6		/* for mount(fd, mpt, flag, arg, srv) */
#define	PRINTSIZE	256
#define	NUMSIZE		12		/* size of formatted number */

M port/stil.c => port/stil.c +181 -94
@@ 11,11 11,12 @@
#include	"arp.h"
#include 	"ipdat.h"

#define DPRINT if(pip)print
int 		ilcksum = 1;
static 	int 	initseq = 25000;
static	Rendez	ilackr;
Rendez poor;	/* DEBUG */
char	*ilstate[] = { "Closed", "Syncer", "Syncee", "Established", "Listening", "Closing" };
char	*iltype[] =  { "sync", "data", "dataquerey", "ack", "querey", "state", "close" };

enum
{


@@ 25,7 26,7 @@ enum

void	ilrcvmsg(Ipconv*, Block*);
void	ilackproc(void*);
void	ilsendctl(Ipconv*, Ilhdr*, int, int);
void	ilsendctl(Ipconv*, Ilhdr*, int);
void	ilackq(Ilcb*, Block*);
void	ilprocess(Ipconv*, Ilhdr*, Block*);
void	ilpullup(Ipconv*);


@@ 82,13 83,19 @@ ilclose(Queue *q)
	case Ilsyncer:
	case Ilsyncee:
	case Ilestablished:
		for(bp = ic->unacked; bp; bp = next) {
			next = bp->list;
			freeb(bp);
		}
		for(bp = ic->outoforder; bp; bp = next) {
			next = bp->list;
			freeb(bp);
		}
		ic->unacked = 0;
		ic->outoforder = 0;
		ic->state = Ilclosing;
		ilsendctl(s, 0, Ilclose, 0);
		ic->sent++;
		ilsendctl(s, 0, Ilclose);
		break;
	Illistening:
		ic->state = Ilclosed;


@@ 161,6 168,7 @@ iloput(Queue *q, Block *bp)
		hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, dlen+IL_HDRSIZE));

	ilackq(ic, bp);
	delay(100);
	PUTNEXT(q, bp);
}



@@ 171,7 179,6 @@ ilackq(Ilcb *ic, Block *bp)

	/* Enqueue a copy on the unacked queue in case this one gets lost */
	np = copyb(bp, blen(bp));

	if(ic->unacked)
		ic->unackedtail->list = np;
	else 


@@ 185,11 192,14 @@ ilackto(Ilcb *ic, ulong ackto)
{
	Ilhdr *h;
	Block *bp;
	ulong ack;

	while(ic->unacked) {
		h = (Ilhdr *)ic->unacked->rptr;
		if(ackto < nhgetl(h->ilack))
		ack = nhgetl(h->ilack);
		if(ackto < ack)
			break;
		ic->lastack = ackto;
		bp = ic->unacked;
		ic->unacked = bp->list;
		bp->list = 0;


@@ 207,6 217,7 @@ void
ilrcvmsg(Ipconv *ipc, Block *bp)
{
	Ilhdr *ih;
	Ilcb *ic;
	int plen, illen;
	Ipconv *s, *etab, *new;
	short sp, dp;


@@ 259,10 270,15 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
			new->ipinterface = s->ipinterface;
			new->psrc = sp;
			new->pdst = dp;
			new->ilctl.state = Ilsyncee;
			initseq += TK2MS(MACHP(0)->ticks);
			new->ilctl.sent = initseq;
			new->dst = nhgetl(ih->src);

			ic = &new->ilctl;
			ic->state = Ilsyncee;
			initseq += TK2MS(MACHP(0)->ticks);
			ic->sent = initseq;
			ic->start = ic->sent;
			ic->recvd = 0;
			ic->rstart = nhgetl(ih->ilid);
			ilprocess(new, ih, bp);

			s->ipinterface->ref++;


@@ 272,107 288,190 @@ ilrcvmsg(Ipconv *ipc, Block *bp)
		}
	}
drop:
	print("drop\n");
	freeb(bp);
	return;
reset:
	ilsendctl(0, ih, Ilclose, 0);
	print("reset\n");
	ilsendctl(0, ih, Ilclose);
	freeb(bp);
}

void
ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
_ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
{
	Block *nb;
	Ilcb *ic;
	Block *nb, *next;
	ulong id, ack, dlen;

	id = nhgetl(h->ilid);
	ack = nhgetl(h->ilack);
	ic = &s->ilctl;

	ic->timeout = 0;
	/* Active transition machine - this tracks connection state */
	switch(ic->state) {
	case Ilsyncee:	
	default:
		panic("il unknown state");
	case Ilclosed:
		freeb(bp);
		break;
	case Ilsyncer:
		switch(h->iltype) {
		default:
			break;
		case Ilsync:
			ic->recvd = id;
			ilsendctl(s, 0, Ilsync, 0);
			if(ack != ic->start) {
				ilhangup(s);
				ic->state = Ilclosed;
			}
			else {
				ic->recvd = id;
				ic->rstart = id;
				ilsendctl(s, 0, Ilack);
				ic->state = Ilestablished;
				ilpullup(s);
			}
			break;
		case Ilack:
			ic->state = Ilestablished;
		case Ilclose:
			if(ack == ic->start) {
				ic->state = Ilclosed;
				ilhangup(s);
			}
			break;
		}
		break;
	case Ilsyncer:
		if(h->iltype == Ilsync && ic->start == ack) {
			ic->recvd = id+1;
			ilsendctl(s, 0, Ilack, 1);
			ic->state = Ilestablished;
			ilpullup(s);
		}
		break;
	case Ilclosing:
		ilsendctl(s, 0, Ilclose, 0);
		ic->state = Ilclosed;
		/* No break */
	case Ilclosed:
		ilhangup(s);
		freeb(bp);
		return;
	}

	/* Passive actions based on packet type */
	switch(h->iltype) {
	case Ilstate:
		if(ic->unacked) {
			nb = copyb(ic->unacked, blen(ic->unacked));
			PUTNEXT(Ipoutput, nb);	
		break;
	case Ilsyncee:
		switch(h->iltype) {
		default:
			break;
		case Ilsync:
			if(id != ic->rstart || ack != 0)
				ic->state = Ilclosed;
			else {
				ic->recvd = id;
				ilsendctl(s, 0, Ilsync);
			}
			break;
		case Ilack:
			if(ack == ic->start) {
				ic->state = Ilestablished;
				ilpullup(s);
			}
			break;
		case Ilclose:
			if(ack == ic->start) {
				ic->state = Ilclosed;
				ilhangup(s);
			}
			break;
		}
		else
			ilsendctl(s, 0, Ilack, 1);
		freeb(bp);
		break;
	case Ilack:
		ilackto(ic, ack);
		freeb(bp);
	case Ilestablished:
		switch(h->iltype) {
		case Ilsync:
			if(id != ic->start) {
				ic->state = Ilclosed;
				ilhangup(s);
			}
			else 
				ilsendctl(s, 0, Ilack);
			freeb(bp);	
			break;
		case Ildata:
		case Ildataquery:
			if(id < ic->recvd) {
				freeb(bp);
				break;
			}
			if(ack >= ic->recvd)
				ilackto(ic, ack);
			iloutoforder(s, h, bp);
			ilpullup(s);
			if(h->iltype == Ildataquery)
				ilsendctl(s, 0, Ilstate);
			break;
		case Ilack:
			ilackto(ic, ack);
			freeb(bp);
			break;
		case Ilquerey:
			ilackto(ic, ack);
			ilsendctl(s, 0, Ilstate);
			freeb(bp);
			break;
		case Ilstate:
			ilackto(ic, ack);
			if(ic->unacked) {
				nb = copyb(ic->unacked, blen(ic->unacked));
				h = (Ilhdr*)nb;
				h->iltype = Ildataquery;
				hnputl(h->ilack, ic->recvd);
				PUTNEXT(Ipoutput, nb);
			}
			freeb(bp);
			break;
		case Ilclose:
			freeb(bp);
			if(ic->start >= ack || ack < ic->sent)
				break;
			ic->sent++;
			ic->recvd = ack;
			ilsendctl(s, 0, Ilclose);
			ic->state = Ilclosing;
			for(nb = ic->unacked; nb; nb = next) {
				next = nb->list;
				freeb(nb);
			}
			for(nb = ic->outoforder; nb; nb = next) {
				next = nb->list;
				freeb(nb);
			}
			ic->unacked = 0;
			ic->outoforder = 0;
			break;
		}
		break;
	case Ilquerey:
		ilsendctl(s, 0, Ilack, 1);
	case Illistening:
		freeb(bp);
		break;
	case Ildataquery:
		ilsendctl(s, 0, Ilack, 1);
		/* No break */
	case Ildata:
		ilackto(&s->ilctl, ack);
		switch(s->ilctl.state) {
	case Ilclosing:
		switch(h->iltype) {
		case Ilclose:
			if(ack == ic->sent) {
				ic->state = Ilclosed;
				ilhangup(s);
			}
			ic->recvd = id;
			ilsendctl(s, 0, Ilclose);
			break;
		default:
			iloutoforder(s, h, bp);
			ic->state = Ilclosed;
			ilsendctl(s, 0, Ilclose);
			ilhangup(s);
			break;
		case Ilestablished:
			if(id < s->ilctl.recvd)
				freeb(bp);
			else if(id > s->ilctl.recvd)
				iloutoforder(s, h, bp);
			else if(s->readq) {
				s->ilctl.recvd++;
				bp->rptr += IL_EHSIZE+IL_HDRSIZE;
				PUTNEXT(s->readq, bp);
				ilpullup(s);
			}
		}
		break;
	case Ilclose:
		ic->state = Ilclosing;
		ilhangup(s);
		/* No break */
	default:
		freeb(bp);
		break;
	}
}

/* DEBUG */
void
ilprocess(Ipconv *s, Ilhdr *h, Block *bp)
{
	Ilcb *ic = &s->ilctl;

	print("%s start %d rstart %d recvd %d sent %d\n",
		ilstate[ic->state], ic->start, ic->rstart, ic->recvd, ic->sent);
	print("pkt(%s id %d ack %d)\n", iltype[h->iltype], nhgetl(h->ilid), nhgetl(h->ilack));

	_ilprocess(s, h, bp);

	print("%s start %d rstart %d recvd %d sent %d\n",
		ilstate[ic->state], ic->start, ic->rstart, ic->recvd, ic->sent);
}

void
ilhangup(Ipconv *s)
{


@@ 450,11 549,12 @@ iloutoforder(Ipconv *s, Ilhdr *h, Block *bp)
}

void
ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, int ack)
ilsendctl(Ipconv *ipc, Ilhdr *inih, int type)
{
	Ilhdr *ih;
	Ilcb *ic;
	Block *bp;
	ulong id;

	bp = allocb(IL_EHSIZE+IL_HDRSIZE);
	bp->wptr += IL_EHSIZE+IL_HDRSIZE;


@@ 478,7 578,10 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, int ack)
		hnputl(ih->dst, ipc->dst);
		hnputs(ih->ilsrc, ipc->psrc);
		hnputs(ih->ildst, ipc->pdst);
		hnputl(ih->ilid, ic->sent);
		id = ic->sent;
		if(type == Ilsync)
			id = ic->start;
		hnputl(ih->ilid, id);
		hnputl(ih->ilack, ic->recvd);
	}
	ih->iltype = type;


@@ 489,10 592,6 @@ ilsendctl(Ipconv *ipc, Ilhdr *inih, int type, int ack)
	if(ilcksum)
		hnputs(ih->ilsum, ptcl_csum(bp, IL_EHSIZE, IL_HDRSIZE));

	if(ack == 0 && ipc) {
		ic->sent++;			/* Maybe needs locking */
		ilackq(&ipc->ilctl, bp);
	}
	PUTNEXT(Ipoutput, bp);
}



@@ 507,7 606,7 @@ ilackproc(void *a)
	end = &base[conf.ip];

	for(;;) {
		tsleep(&ilackr, return0, 0, 100);
		tsleep(&ilackr, return0, 0, 250);
		for(s = base; s < end; s++) {
			ic = &s->ilctl;
			switch(ic->state) {


@@ 517,22 616,10 @@ ilackproc(void *a)
			case Ilclosing:
				break;
			case Ilsyncee:
				break;
			case Ilsyncer:
				ilsendctl(s, 0, Ilsync, 1);
				if(++ic->timeout == Slowtime) {
					ilhangup(s);
					ic->state = Ilclosed;
					s->dst = 0;
					s->pdst = 0;
					ic->timeout = 0;
				}
				break;
			case Ilestablished:
				if(++ic->timeout == Fasttime) {
					if(ic->lastack < ic->recvd)
						ilsendctl(s, 0, Ilstate, 1);
					ic->timeout = 0;
				}
				break;
			}
		}


@@ 563,7 650,7 @@ ilstart(Ipconv *ipc, int type, int window)
		break;
	case IL_ACTIVE:
		ic->state = Ilsyncer;
		ilsendctl(ipc, 0, Ilsync, 1);
		ilsendctl(ipc, 0, Ilsync);
		break;
	}
}

M port/stip.c => port/stip.c +1 -2
@@ 322,12 322,11 @@ ipetheriput(Queue *q, Block *bp)
 	 * Look for an ip interface attached to this protocol
	 */
	ep = &ipifc[conf.ipif];
	for(ifp = ipifc; ifp < ep; ifp++) {
	for(ifp = ipifc; ifp < ep; ifp++)
		if(ifp->protocol == h->proto) {
			(*ifp->iprcv)(ifp->connections, bp);
			return;
		}
	}
			
drop:
	freeb(bp);

M port/tcpinput.c => port/tcpinput.c +0 -7
@@ 52,13 52,6 @@ tcp_input(Ipconv *ipc, Block *bp)
	tos = h->tos;
	length = nhgets(h->length);

	if (dest == source) {
		if (!(bp = copyb(bp, blen(bp)))) {
			print("tcpin: allocb failure.");
			return;
		}
	}

	h->Unused = 0;
	hnputs(h->tcplen, length - (TCP_IPLEN+TCP_PHDRSIZE));
	if(ptcl_csum(bp, TCP_EHSIZE+TCP_IPLEN, length - TCP_IPLEN)) {

M ss/fns.h => ss/fns.h +1 -0
@@ 26,6 26,7 @@ KMap*	kmap(Page*);
void	kmapinit(void);
KMap*	kmappa(ulong, ulong);
int	kprint(char*, ...);
void	kproftimer(ulong);
void	kunmap(KMap*);
void	lanceintr(void);
void	lancesetup(Lance*);

M ss/l.s => ss/l.s +7 -7
@@ 119,7 119,7 @@ TEXT	spldone(SB), $0

	RETURN

TEXT	touser(SB), $-4
TEXT	touser(SB), $0
	MOVW	$(SYSPSR&~PSREF), R8
	MOVW	R8, PSR
	OR	R0, R0


@@ 187,10 187,10 @@ trap1:
	MOVD	R28, (4*28)(R1)
	MOVD	R30, (4*30)(R1)
	/* SP and SB and u and m are already set; away we go */
	MOVW	R1, -4(R1)		/* pointer to Ureg */
	MOVW	R1, R7		/* pointer to Ureg */
	SUB	$8, R1
	MOVW	$SYSPSR, R7
	MOVW	R7, PSR
	MOVW	$SYSPSR, R8
	MOVW	R8, PSR
	OR	R0, R0
	OR	R0, R0
	OR	R0, R0


@@ 272,10 272,10 @@ TEXT	syslink(SB), $-4
	/* now our registers R8-R31 are same as before trap */
	MOVW	R15, (4*15)(R1)
	/* SP and SB and u and m are already set; away we go */
	MOVW	R1, -4(R1)		/* pointer to Ureg */
	MOVW	R1, R7			/* pointer to Ureg */
	SUB	$8, R1
	MOVW	$SYSPSR, R7
	MOVW	R7, PSR
	MOVW	$SYSPSR, R8
	MOVW	R8, PSR
	JMPL	syscall(SB)
	/* R7 contains return value from syscall */


M ss/main.c => ss/main.c +0 -2
@@ 279,7 279,6 @@ lancesetup(Lance *lp)
	pa = (ulong)ialloc(BY2PG, 1)&~KZERO;	/* one whole page */
	/* map at LANCESEGM */
	k = kmappa(pa, PTEMAINMEM);
print("init block va %lux\n", k->va);
	lp->lanceram = (ushort*)k->va;
	lp->lm = (Lancemem*)k->va;



@@ 290,7 289,6 @@ print("init block va %lux\n", k->va);
	 */
	i = (lp->nrrb+lp->ntrb)*sizeof(Etherpkt);
	i = (i+(BY2PG-1))/BY2PG;
print("%d lance buffers\n", i);
	pa = (ulong)ialloc(i*BY2PG, 1)&~KZERO;
	va = 0;
	for(j=i-1; j>=0; j--){