~kris/9p

9hist

fb4aaf15cbc6be3c73be37863a2ea62bee43f4b9 — David du Colombier 35 years ago cfaf1a9
Plan 9 from Bell Labs 1991-04-11
M gnot/dat.h => gnot/dat.h +5 -3
@@ 88,7 88,8 @@ struct Alarm
#define	CHEXCL	0x20000000L
struct Chan
{
	QLock;				/* general access */
	QLock	rdl;			/* read access */
	QLock	wrl;			/* write access */
	Ref;
	union{
		Chan	*next;		/* allocation */


@@ 171,8 172,8 @@ struct Dev
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long);
	long	 (*write)(Chan*, void*, long);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong);
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
};


@@ 473,6 474,7 @@ struct Stream {
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)

M gnot/devcons.c => gnot/devcons.c +20 -20
@@ 269,14 269,14 @@ pprint(char *fmt, ...)
		return 0;
	n = sprint(buf, "%s %d: ", u->p->text, u->p->pid);
	n = doprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
	qlock(c);
	qlock(&c->wrl);
	if(waserror()){
		qunlock(c);
		qunlock(&c->wrl);
		return 0;
	}
	(*devtab[c->type].write)(c, buf, n);
	(*devtab[c->type].write)(c, buf, n, c->offset);
	c->offset += n;
	qunlock(c);
	qunlock(&c->wrl);
	poperror();
	return n;
}


@@ 554,7 554,7 @@ consclose(Chan *c)
}

long
consread(Chan *c, void *buf, long n)
consread(Chan *c, void *buf, long n, ulong offset)
{
	int ch, i, j, k;
	ulong l;


@@ 622,13 622,13 @@ consread(Chan *c, void *buf, long n)
		return streamread(c, buf, n);

	case Qrs232ctl:
		if(c->offset)
		if(offset)
			return 0;
		*(char *)buf = duartinputport();
		return 1;

	case Qcputime:
		k = c->offset;
		k = offset;
		if(k >= sizeof tmp)
			return 0;
		if(k+n > sizeof tmp)


@@ 645,21 645,21 @@ consread(Chan *c, void *buf, long n)
		return n;

	case Qpgrpid:
		return readnum(c->offset, buf, n, u->p->pgrp->pgrpid, NUMSIZE);
		return readnum(offset, buf, n, u->p->pgrp->pgrpid, NUMSIZE);

	case Qpid:
		return readnum(c->offset, buf, n, u->p->pid, NUMSIZE);
		return readnum(offset, buf, n, u->p->pid, NUMSIZE);

	case Qppid:
		return readnum(c->offset, buf, n, u->p->parentpid, NUMSIZE);
		return readnum(offset, buf, n, u->p->parentpid, NUMSIZE);

	case Qtime:
		return readnum(c->offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), NUMSIZE);
		return readnum(offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), NUMSIZE);

	case Qmsec:
		return readnum(c->offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
		return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
	case Qclock:
		k = c->offset;
		k = offset;
		if(k >= 2*NUMSIZE)
			return 0;
		if(k+n > 2*NUMSIZE)


@@ 670,7 670,7 @@ consread(Chan *c, void *buf, long n)
		return n;

	case Quser:
		return readstr(c->offset, buf, n, u->p->pgrp->user);
		return readstr(offset, buf, n, u->p->pgrp->user);

	case Qnull:
		return 0;


@@ 699,7 699,7 @@ consread(Chan *c, void *buf, long n)
}

long
conswrite(Chan *c, void *va, long n)
conswrite(Chan *c, void *va, long n, ulong offset)
{
	char cbuf[64];
	char buf[256];


@@ 742,12 742,12 @@ conswrite(Chan *c, void *va, long n)
	case Quser:
		if(u->p->pgrp->user[0])		/* trying to overwrite /dev/user */
			error(Eperm);
		if(c->offset >= NAMELEN-1)
		if(offset >= NAMELEN-1)
			return 0;
		if(c->offset+n >= NAMELEN-1)
			n = NAMELEN-1 - c->offset;
		memmove(u->p->pgrp->user+c->offset, a, n);
		u->p->pgrp->user[c->offset+n] = 0;
		if(offset+n >= NAMELEN-1)
			n = NAMELEN-1 - offset;
		memmove(u->p->pgrp->user+offset, a, n);
		u->p->pgrp->user[offset+n] = 0;
		break;

	case Qcputime:

M gnot/devincon.c => gnot/devincon.c +2 -2
@@ 393,13 393,13 @@ inconclose(Chan *c)
}

long	 
inconread(Chan *c, void *buf, long n)
inconread(Chan *c, void *buf, long n, ulong offset)
{
	return streamread(c, buf, n);
}

long	 
inconwrite(Chan *c, void *buf, long n)
inconwrite(Chan *c, void *buf, long n, ulong offset)
{
	return streamwrite(c, buf, n, 0);
}

M gnot/devport.c => gnot/devport.c +6 -6
@@ 106,7 106,7 @@ portclose(Chan *c)
{}

long
portread(Chan *c, char *a, long n)
portread(Chan *c, char *a, long n, ulong offset)
{
	long s, k;
	if (n == 0)


@@ 115,9 115,9 @@ portread(Chan *c, char *a, long n)
	case Qdir:
		return devdirread(c, a, n, portdir, NPORT, devgen);
	case Qdata:
		if (!conf.portispaged || (s = c->offset >> PORTSHIFT) > 0xff)
		if (!conf.portispaged || (s = offset >> PORTSHIFT) > 0xff)
			s = -1;
		k = c->offset % PORTSIZE;
		k = offset % PORTSIZE;
		P_qlock(s);
		switch ((int)n) {
		case 1:


@@ 139,16 139,16 @@ portread(Chan *c, char *a, long n)
}

long
portwrite(Chan *c, char *a, long n)
portwrite(Chan *c, char *a, long n, ulong offset)
{
	long s, k;
	if (n == 0)
		return 0;
	switch ((int)c->qid.path) {
	case Qdata:
		if (!conf.portispaged || (s = c->offset >> PORTSHIFT) > 0xff)
		if (!conf.portispaged || (s = offset >> PORTSHIFT) > 0xff)
			s = -1;
		k = c->offset % PORTSIZE;
		k = offset % PORTSIZE;
		P_qlock(s);
		switch ((int)n) {
		case 1:

M gnot/fns.h => gnot/fns.h +1 -1
@@ 197,7 197,7 @@ Stream	*streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);
void	streamstat(Chan*, char*, char*);
long	stringread(Chan*, void*, long, char*);
long	stringread(Chan*, void*, long, char*, ulong);
long	syscall(Ureg*);
int	tas(char*);
void	touser(void);

M gnot/main.c => gnot/main.c +3 -3
@@ 118,13 118,13 @@ init0(void)
	u->dot = clone(u->slash, 0);
	if(!waserror()){
		c = namec("#e/bootline", Acreate, OWRITE, 0600);
		(*devtab[c->type].write)(c, bootline, 64);
		(*devtab[c->type].write)(c, bootline, 64, 0);
		close(c);
		c = namec("#e/bootserver", Acreate, OWRITE, 0600);
		(*devtab[c->type].write)(c, bootserver, 64);
		(*devtab[c->type].write)(c, bootserver, 64, 0);
		close(c);
		c = namec("#e/bootdevice", Acreate, OWRITE, 0600);
		(*devtab[c->type].write)(c, bootdevice, 2);
		(*devtab[c->type].write)(c, bootdevice, 2, 0);
		close(c);
	}
	poperror();

M gnot/mem.h => gnot/mem.h +3 -0
@@ 100,3 100,6 @@

#define	NSEG		5
#define	MACHSIZE	4096


#define isphys(p) ((((ulong)(p))&0xF0000000) == KSEG)

M port/dev.c => port/dev.c +6 -0
@@ 107,6 107,12 @@ devwalk(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen)
		}
}

int devclwalk(Chan *c, Chan *nc, char *name, Dirtab *tab, int ntab, Devgen *gen)
{
	c = devclone(c, nc);
	return devwalk(c, name, tab, ntab, gen);
}

void
devstat(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen)
{

M port/devbit.c => port/devbit.c +4 -4
@@ 275,7 275,7 @@ bitclose(Chan *c)
#define	K2U(x)	(x)

long
bitread(Chan *c, void *va, long n)
bitread(Chan *c, void *va, long n, ulong offset)
{
	uchar *p, *q;
	long miny, maxy, t, x, y;


@@ 429,7 429,7 @@ bitread(Chan *c, void *va, long n)
		error(Ebadblt);

	case Qscreen:
		if(c->offset==0){
		if(offset==0){
			if(n < 5*12)
				error(Eio);
			sprint(va, "%11d %11d %11d %11d %11d ",


@@ 441,7 441,7 @@ bitread(Chan *c, void *va, long n)
		}
		ws = 1<<(3-gscreen.ldepth);	/* pixels per byte */
		l = (gscreen.r.max.x+ws-1)/ws - gscreen.r.min.x/ws;
		t = c->offset-5*12;
		t = offset-5*12;
		miny = t/l;
		maxy = (t+n)/l;
		if(miny >= gscreen.r.max.y)


@@ 467,7 467,7 @@ bitread(Chan *c, void *va, long n)


long
bitwrite(Chan *c, void *va, long n)
bitwrite(Chan *c, void *va, long n, ulong offset)
{
	uchar *p, *q;
	long m, v, miny, maxy, minx, maxx, t, x, y, tw, th;

M port/devboot.c => port/devboot.c +7 -7
@@ 74,7 74,7 @@ bootclose(Chan *c)
}

long	 
bootread(Chan *c, void *buf, long n)
bootread(Chan *c, void *buf, long n, ulong offset)
{
	switch(c->qid.path & ~CHDIR){
	case Qdir:


@@ 85,21 85,21 @@ bootread(Chan *c, void *buf, long n)
}

long	 
bootwrite(Chan *c, void *buf, long n)
bootwrite(Chan *c, void *buf, long n, ulong offset)
{
	ulong pc;

	switch(c->qid.path & ~CHDIR){
	case Qmem:
		/* kernel memory.  BUG: shouldn't be so easygoing. BUG: mem mapping? */
		if(c->offset>=KZERO && c->offset<KZERO+conf.npage*BY2PG){
		if(offset>=KZERO && offset<KZERO+conf.npage*BY2PG){
/*			print("%ux, %d\n", c->offset, n);/**/
			if(c->offset+n > KZERO+conf.npage*BY2PG)
				n = KZERO+conf.npage*BY2PG - c->offset;
			memmove((char*)c->offset, buf, n);
			if(offset+n > KZERO+conf.npage*BY2PG)
				n = KZERO+conf.npage*BY2PG - offset;
			memmove((char*)offset, buf, n);
			return n;
		}
		print("bootwrite: bad addr %lux\n", c->offset);
		print("bootwrite: bad addr %lux\n", offset);
		error(Ebadarg);

	case Qboot:

M port/devcons.c => port/devcons.c +18 -18
@@ 197,14 197,14 @@ pprint(char *fmt, ...)
		return 0;
	n = sprint(buf, "%s %d: ", u->p->text, u->p->pid);
	n = doprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
	qlock(c);
	qlock(&c->wrl);
	if(waserror()){
		qunlock(c);
		qunlock(&c->wrl);
		return 0;
	}
	(*devtab[c->type].write)(c, buf, n);
	(*devtab[c->type].write)(c, buf, n, c->offset);
	c->offset += n;
	qunlock(c);
	qunlock(&c->wrl);
	poperror();
	return n;
}


@@ 435,7 435,7 @@ consclose(Chan *c)
}

long
consread(Chan *c, void *buf, long n)
consread(Chan *c, void *buf, long n, ulong offset)
{
	int ch, i, j, k;
	ulong l;


@@ 492,7 492,7 @@ consread(Chan *c, void *buf, long n)
		return i;

	case Qcputime:
		k = c->offset;
		k = offset;
		if(k >= sizeof tmp)
			return 0;
		if(k+n > sizeof tmp)


@@ 509,22 509,22 @@ consread(Chan *c, void *buf, long n)
		return n;

	case Qpgrpid:
		return readnum(c->offset, buf, n, u->p->pgrp->pgrpid, NUMSIZE);
		return readnum(offset, buf, n, u->p->pgrp->pgrpid, NUMSIZE);

	case Qpid:
		return readnum(c->offset, buf, n, u->p->pid, NUMSIZE);
		return readnum(offset, buf, n, u->p->pid, NUMSIZE);

	case Qppid:
		return readnum(c->offset, buf, n, u->p->parentpid, NUMSIZE);
		return readnum(offset, buf, n, u->p->parentpid, NUMSIZE);

	case Qtime:
		return readnum(c->offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), 12);
		return readnum(offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), 12);

	case Quser:
		return readstr(c->offset, buf, n, u->p->pgrp->user);
		return readstr(offset, buf, n, u->p->pgrp->user);

	case Qlog:
		return readlog(c->offset, buf, n);
		return readlog(offset, buf, n);

	case Qnull:
		return 0;


@@ 536,7 536,7 @@ consread(Chan *c, void *buf, long n)
}

long
conswrite(Chan *c, void *va, long n)
conswrite(Chan *c, void *va, long n, ulong offset)
{
	char cbuf[64];
	char buf[256];


@@ 573,12 573,12 @@ conswrite(Chan *c, void *va, long n)
	case Quser:
		if(u->p->pgrp->user[0])		/* trying to overwrite /dev/user */
			error(Eperm);
		if(c->offset >= NAMELEN-1)
		if(offset >= NAMELEN-1)
			return 0;
		if(c->offset+n >= NAMELEN-1)
			n = NAMELEN-1 - c->offset;
		memmove(u->p->pgrp->user+c->offset, a, n);
		u->p->pgrp->user[c->offset+n] = 0;
		if(offset+n >= NAMELEN-1)
			n = NAMELEN-1 - offset;
		memmove(u->p->pgrp->user+offset, a, n);
		u->p->pgrp->user[offset+n] = 0;
		break;

	case Qcputime:

M port/devdk.c => port/devdk.c +5 -5
@@ 863,7 863,7 @@ dkclose(Chan *c)
}

long	 
dkread(Chan *c, void *a, long n)
dkread(Chan *c, void *a, long n, ulong offset)
{
	Line *lp;



@@ 880,17 880,17 @@ dkread(Chan *c, void *a, long n)
	lp = &dk[c->dev].line[STREAMID(c->qid.path)];
	switch(STREAMTYPE(c->qid.path)){
	case Daddrqid:
		return stringread(c, a, n, lp->addr);
		return stringread(c, a, n, lp->addr, offset);
	case Draddrqid:
		return stringread(c, a, n, lp->raddr);
		return stringread(c, a, n, lp->raddr, offset);
	case Duserqid:
		return stringread(c, a, n, lp->ruser);
		return stringread(c, a, n, lp->ruser, offset);
	}
	error(Eperm);
}

long	 
dkwrite(Chan *c, void *a, long n)
dkwrite(Chan *c, void *a, long n, ulong offset)
{
	int t;
	char buf[256];

M port/devdup.c => port/devdup.c +2 -2
@@ 104,7 104,7 @@ dupclose(Chan *c)
}

long
dupread(Chan *c, void *va, long n)
dupread(Chan *c, void *va, long n, ulong offset)
{
	char *a = va;



@@ 114,7 114,7 @@ dupread(Chan *c, void *va, long n)
}

long
dupwrite(Chan *c, void *va, long n)
dupwrite(Chan *c, void *va, long n, ulong offset)
{
	panic("dupwrite");
}

M port/devenv.c => port/devenv.c +9 -9
@@ 435,7 435,7 @@ envpgclose(Env *e)
}

long
envread(Chan *c, void *va, long n)
envread(Chan *c, void *va, long n, ulong offset)
{
	Env *e;
	Envval *ev;


@@ 456,19 456,19 @@ envread(Chan *c, void *va, long n)
	lock(e);
	ev = e->val;
	vn = ev? e->val->len : 0;
	if(c->offset+n > vn)
		n = vn - c->offset;
	if(offset+n > vn)
		n = vn - offset;
	if(n <= 0)
		n = 0;
	else
		memmove(a, ev->dat+c->offset, n);
		memmove(a, ev->dat+offset, n);
	unlock(e);
	unlock(pg);
	return n;
}

long
envwrite(Chan *c, void *va, long n)
envwrite(Chan *c, void *va, long n, ulong offset)
{
	Env *e;
	char *p;


@@ 496,13 496,13 @@ envwrite(Chan *c, void *va, long n)
	}
	if(e->pgref>1)
		panic("envwrite to non-duped env");
	growenval(e, c->offset+n);
	growenval(e, offset+n);
	ev = e->val;
	vn = ev? ev->len : 0;
	if(c->offset > vn)
	if(offset > vn)
		error(Egreg); /* perhaps should zero fill */
	memmove(ev->dat+c->offset, a, n);
	e->val->len = c->offset+n;
	memmove(ev->dat+offset, a, n);
	e->val->len = offset+n;
	poperror();
	unlock(e);
	unlock(&envalloc);

M port/deviproute.c => port/deviproute.c +5 -5
@@ 268,7 268,7 @@ iprouteclose(Chan *c)
#define PAD "                                                                  "

long
iprouteread(Chan *c, void *a, long n)
iprouteread(Chan *c, void *a, long n, ulong offset)
{
	char	buf[IPR_ENTRYLEN*3];
	Iproute	*r;


@@ 280,10 280,10 @@ iprouteread(Chan *c, void *a, long n)
		return devdirread(c, a, n, iproutetab, Niproutetab, devgen);
	case Qdata:
		lock(&iprtab);
		part = c->offset/IPR_ENTRYLEN;
		part = offset/IPR_ENTRYLEN;
		for(r = iprtab.first; part && r; r = r->next)
			part--;
		bytes = c->offset;
		bytes = offset;
		while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){
			part = bytes%IPR_ENTRYLEN;



@@ 309,7 309,7 @@ iprouteread(Chan *c, void *a, long n)
			r = r->next;
		}
		unlock(&iprtab);
		return bytes - c->offset;
		return bytes - offset;
		break;
	default:
		n=0;


@@ 319,7 319,7 @@ iprouteread(Chan *c, void *a, long n)
}

long
iproutewrite(Chan *c, char *a, long n)
iproutewrite(Chan *c, char *a, long n, ulong offset)
{
	char buf[IPR_ENTRYLEN];
	char *field[4];

M port/devkprof.c => port/devkprof.c +6 -6
@@ 118,19 118,19 @@ kproferrstr(Error *e, char *buf)
}

long
kprofread(Chan *c, void *a, long n)
kprofread(Chan *c, void *a, long n, ulong offset)
{
	switch((int)(c->qid&~CHDIR)){
	case Kprofdirqid:
		return devdirread(c, a, n, kproftab, Nkproftab, devgen);
	case Kprofdataqid:
		if(c->offset >= NBUF*sizeof timerbuf[0]){
		if(offset >= NBUF*sizeof timerbuf[0]){
			n = 0;
			break;
		}
		if(c->offset+n > NBUF*sizeof timerbuf[0])
			n = NBUF*sizeof timerbuf[0]-c->offset;
		memmove(a, ((char *)timerbuf)+c->offset, n);
		if(offset+n > NBUF*sizeof timerbuf[0])
			n = NBUF*sizeof timerbuf[0]-offset;
		memmove(a, ((char *)timerbuf)+offset, n);
		break;
	default:
		n=0;


@@ 140,7 140,7 @@ kprofread(Chan *c, void *a, long n)
}

long
kprofwrite(Chan *c, char *a, long n)
kprofwrite(Chan *c, char *a, long n, ulong offset)
{
	switch((int)(c->qid&~CHDIR)){
	case Kprofstartclrqid:

M port/devlance.c => port/devlance.c +11 -11
@@ 623,40 623,40 @@ lanceclose(Chan *c)
}

static long
lancetraceread(Chan *c, void *a, long n)
lancetraceread(Chan *c, void *a, long n, ulong offset)
{
	char buf[1024];
	long rv;
	int i;
	char *ca = a;
	int offset;
	int off;
	Trace *t;
	int plen;

	rv = 0;
	sprintpacket(buf, l.dq.t);
	plen = strlen(buf);
	offset = c->offset % plen;
	for(t = &l.dq.t[c->offset/plen]; n && t < &l.dq.t[Ndpkt]; t++){
	off = offset % plen;
	for(t = &l.dq.t[offset/plen]; n && t < &l.dq.t[Ndpkt]; t++){
		if(t->tag == 0)
			break;
		lock(&l.dq);
		sprintpacket(buf, t);
		unlock(&l.dq);
		i = plen - offset;
		i = plen - off;
		if(i > n)
			i = n;
		memmove(ca, buf + offset, i);
		memmove(ca, buf + off, i);
		n -= i;
		ca += i;
		rv += i;
		offset = 0;
		off = 0;
	}
	return rv;
}

long	 
lanceread(Chan *c, void *a, long n)
lanceread(Chan *c, void *a, long n, ulong offset)
{
	char buf[256];



@@ 668,16 668,16 @@ lanceread(Chan *c, void *a, long 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]);
		return stringread(c, a, n, buf);
		return stringread(c, a, n, buf, offset);
	case Ltraceqid:
		return lancetraceread(c, a, n);
		return lancetraceread(c, a, n, offset);
	default:
		return streamread(c, a, n);
	}
}

long	 
lancewrite(Chan *c, void *a, long n)
lancewrite(Chan *c, void *a, long n, ulong offset)
{
	return streamwrite(c, a, n, 0);
}

M port/devmnt.c => port/devmnt.c +10 -11
@@ 504,16 504,15 @@ mntclose(Chan *c)
}

long
mntreadwrite(Chan *c, void *vbuf, long n, int type)
mntreadwrite(Chan *c, void *vbuf, long n, int type, ulong offset)
{
	Mnt *m;
	Mnthdr *mh;
	long nt, nr, count, offset;
	long nt, nr, count;
	char *buf;

	buf = vbuf;
	count = 0;
	offset = c->offset;
	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){


@@ 543,12 542,12 @@ mntreadwrite(Chan *c, void *vbuf, long n, int type)
}

long	 
mntread(Chan *c, void *buf, long n)
mntread(Chan *c, void *buf, long n, ulong offset)
{
	long i;
	uchar *b;

	n = mntreadwrite(c, buf, n, Tread);
	n = mntreadwrite(c, buf, n, Tread, offset);
	if(c->qid.path & CHDIR){
		b = (uchar*)buf;
		for(i=n-DIRLEN; i>=0; i-=DIRLEN){


@@ 563,9 562,9 @@ mntread(Chan *c, void *buf, long n)
}

long	 
mntwrite(Chan *c, void *buf, long n)
mntwrite(Chan *c, void *buf, long n, ulong offset)
{
	return mntreadwrite(c, buf, n, Twrite);
	return mntreadwrite(c, buf, n, Twrite, offset);
}

void	 


@@ 700,7 699,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
		mqfree(q);
		nexterror();
	}
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n, 0) != n){
		print("short write in mntxmit\n");
		error(Eshortmsg);
	}


@@ 713,7 712,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
		nexterror();
	}
	mh->mbr = mballoc();
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE);
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE, 0);
	poperror();		/* 3 */
	mqfree(q);
	poperror();		/* 2 */


@@ 767,7 766,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
	}
	mh->readreply = 0;
	mh->active = 1;
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n, 0) != n){
		print("short write in mntxmit\n");
		error(Eshortmsg);
	}


@@ 782,7 781,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
			nexterror();
		}
		mh->mbr = mballoc();
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE);
		n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE, 0);
		poperror();		/* 3 */
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){
			mnterrdequeue(m, mh);

M port/devnonet.c => port/devnonet.c +6 -6
@@ 325,7 325,7 @@ nonetclose(Chan *c)
}

long	 
nonetread(Chan *c, void *a, long n)
nonetread(Chan *c, void *a, long n, ulong offset)
{
	int t;
	Noconv *cp;


@@ 346,21 346,21 @@ nonetread(Chan *c, void *a, long n)
	cp = &noifc[c->dev].conv[STREAMID(c->qid.path)];
	switch(t){
	case Nraddrqid:
		return stringread(c, a, n, cp->raddr);
		return stringread(c, a, n, cp->raddr, offset);
	case Naddrqid:
		return stringread(c, a, n, cp->addr);
		return stringread(c, a, n, cp->addr, offset);
	case Nruserqid:
		return stringread(c, a, n, cp->ruser);
		return stringread(c, 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);
		return stringread(c, a, n, stats, offset);
	}
	error(Eperm);
}

long	 
nonetwrite(Chan *c, void *a, long n)
nonetwrite(Chan *c, void *a, long n, ulong offset)
{
	int t;
	int m;

M port/devpipe.c => port/devpipe.c +2 -2
@@ 241,7 241,7 @@ pipeclose(Chan *c)
}

long
piperead(Chan *c, void *va, long n)
piperead(Chan *c, void *va, long n, ulong offset)
{
	if(c->qid.path & CHDIR)
		return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);


@@ 254,7 254,7 @@ piperead(Chan *c, void *va, long n)
 *  the process.
 */
long
pipewrite(Chan *c, void *va, long n)
pipewrite(Chan *c, void *va, long n, ulong offset)
{
	if(waserror()){
		postnote(u->p, 1, "sys: write on closed pipe", NExit);

M port/devproc.c => port/devproc.c +27 -27
@@ 144,9 144,9 @@ procopen(Chan *c, int omode)
			goto Close;
		if(p->pid != PID(c->qid))
			goto Close;
		qlock(tc);
		qlock(&tc->rdl);
		tc->offset = 0;
		qunlock(tc);
		qunlock(&tc->rdl);
		return tc;
	case Qctl:
	case Qnote:


@@ 206,7 206,7 @@ procclose(Chan * c)
}

long
procread(Chan *c, void *va, long n)
procread(Chan *c, void *va, long n, ulong offset)
{
	char *a = va, *b;
	char statbuf[2*NAMELEN+12+6*12];


@@ 236,9 236,9 @@ procread(Chan *c, void *va, long n)
		/*
		 * One page at a time
		 */
		if(((c->offset+n)&~(BY2PG-1)) != (c->offset&~(BY2PG-1)))
			n = BY2PG - (c->offset&(BY2PG-1));
		s = seg(p, c->offset);
		if(((offset+n)&~(BY2PG-1)) != (offset&~(BY2PG-1)))
			n = BY2PG - (offset&(BY2PG-1));
		s = seg(p, offset);
		if(s){
			o = s->o;
			if(o == 0)


@@ 248,11 248,11 @@ procread(Chan *c, void *va, long n)
				unlock(o);
				error(Eprocdied);
			}
			if(seg(p, c->offset) != s){
			if(seg(p, offset) != s){
				unlock(o);
				error(Egreg);
			}
			pte = &o->pte[(c->offset-o->va)>>PGSHIFT];
			pte = &o->pte[(offset-o->va)>>PGSHIFT];
			if(s->mod){
				opte = pte;
				while(pte = pte->nextmod)	/* assign = */


@@ 264,35 264,35 @@ procread(Chan *c, void *va, long n)
			pg = pte->page;
			unlock(o);
			if(pg == 0){
				pprint("nonresident page addr %lux (complain to rob)\n", c->offset);
				pprint("nonresident page addr %lux (complain to rob)\n", offset);
				memset(a, 0, n);
			}else{
				k = kmap(pg);
				b = (char*)VA(k);
				memmove(a, b+(c->offset&(BY2PG-1)), n);
				memmove(a, b+(offset&(BY2PG-1)), n);
				kunmap(k);
			}
			return n;
		}
		/* u area */
		if(c->offset>=USERADDR && c->offset<USERADDR+BY2PG){
			if(c->offset+n > USERADDR+BY2PG)
				n = USERADDR+BY2PG - c->offset;
		if(offset>=USERADDR && offset<USERADDR+BY2PG){
			if(offset+n > USERADDR+BY2PG)
				n = USERADDR+BY2PG - offset;
			pg = p->upage;
			if(pg==0 || p->pid!=PID(c->qid))
				error(Eprocdied);
			k = kmap(pg);
			b = (char*)VA(k);
			memmove(a, b+(c->offset-USERADDR), n);
			memmove(a, b+(offset-USERADDR), n);
			kunmap(k);
			return n;
		}

		/* kernel memory.  BUG: shouldn't be so easygoing. BUG: mem mapping? */
		if(c->offset>=KZERO && c->offset<KZERO+conf.npage0*BY2PG){
			if(c->offset+n > KZERO+conf.npage0*BY2PG)
				n = KZERO+conf.npage0*BY2PG - c->offset;
			memmove(a, (char*)c->offset, n);
		if(offset>=KZERO && offset<KZERO+conf.npage0*BY2PG){
			if(offset+n > KZERO+conf.npage0*BY2PG)
				n = KZERO+conf.npage0*BY2PG - offset;
			memmove(a, (char*)offset, n);
			return n;
		}
		return 0;


@@ 328,18 328,18 @@ procread(Chan *c, void *va, long n)
		return n;

	case Qproc:
		if(c->offset >= sizeof(Proc))
		if(offset >= sizeof(Proc))
			return 0;
		if(c->offset+n > sizeof(Proc))
			n = sizeof(Proc) - c->offset;
		memmove(a, ((char*)p)+c->offset, n);
		if(offset+n > sizeof(Proc))
			n = sizeof(Proc) - offset;
		memmove(a, ((char*)p)+offset, n);
		return n;

	case Qstatus:
		if(c->offset >= sizeof statbuf)
		if(offset >= sizeof statbuf)
			return 0;
		if(c->offset+n > sizeof statbuf)
			n = sizeof statbuf - c->offset;
		if(offset+n > sizeof statbuf)
			n = sizeof statbuf - offset;
		sprint(statbuf, "%-27s %-27s %-11s ", p->text, p->pgrp->user, statename[p->state]);
		for(i=0; i<6; i++){
			l = p->time[i];


@@ 348,7 348,7 @@ procread(Chan *c, void *va, long n)
			l = TK2MS(l);
			readnum(0, statbuf+2*NAMELEN+12+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
		}
		memmove(a, statbuf+c->offset, n);
		memmove(a, statbuf+offset, n);
		return n;
	}
	error(Egreg);


@@ 356,7 356,7 @@ procread(Chan *c, void *va, long n)


long
procwrite(Chan *c, void *va, long n)
procwrite(Chan *c, void *va, long n, ulong offset)
{
	Proc *p;
	Pgrp *pg;

M port/devroot.c => port/devroot.c +10 -10
@@ 90,7 90,7 @@ rootclose(Chan *c)
#include	"boot.h"

long	 
rootread(Chan *c, void *buf, long n)
rootread(Chan *c, void *buf, long n, ulong offset)
{

	switch(c->qid.path & ~CHDIR){


@@ 98,19 98,19 @@ rootread(Chan *c, void *buf, long n)
		return devdirread(c, buf, n, rootdir, nroot, devgen);

	case Qboot:		/* boot */
		if(c->offset >= sizeof bootcode)
		if(offset >= sizeof bootcode)
			return 0;
		if(c->offset+n > sizeof bootcode)
			n = sizeof bootcode - c->offset;
		memmove(buf, ((char*)bootcode)+c->offset, n);
		if(offset+n > sizeof bootcode)
			n = sizeof bootcode - offset;
		memmove(buf, ((char*)bootcode)+offset, n);
		return n;

	case Qcfs:		/* cfs */
		if(c->offset >= cfslen)
		if(offset >= cfslen)
			return 0;
		if(c->offset+n > cfslen)
			n = cfslen - c->offset;
		memmove(buf, ((char*)cfscode)+c->offset, n);
		if(offset+n > cfslen)
			n = cfslen - offset;
		memmove(buf, ((char*)cfscode)+offset, n);
		return n;

	case Qdev:


@@ 121,7 121,7 @@ rootread(Chan *c, void *buf, long n)
}

long	 
rootwrite(Chan *c, void *buf, long n)
rootwrite(Chan *c, void *buf, long n, ulong offset)
{
	error(Egreg);
}

M port/devscsi.c => port/devscsi.c +6 -6
@@ 117,7 117,7 @@ scsiclose(Chan *c)
{}

long
scsiread(Chan *c, char *a, long n)
scsiread(Chan *c, char *a, long n, ulong offset)
{
	Scsi *cmd = &staticcmd;
	if (n == 0)


@@ 125,7 125,7 @@ scsiread(Chan *c, char *a, long n)
	if(c->qid.path & CHDIR)
		return devdirread(c, a, n, 0, 0, scsigen);
	if(c->qid.path==1){
		if(c->offset == 0){
		if(offset == 0){
			*a = ownid;
			n = 1;
		}else


@@ 155,7 155,7 @@ scsiread(Chan *c, char *a, long n)
		memmove(a, cmd->data.base, n);
		break;
	case Qdebug:
		if (c->offset == 0) {
		if (offset == 0) {
			n=1;
			*a="01"[debugs[(c->qid.path>>4)&7]!=0];
		} else


@@ 168,11 168,11 @@ scsiread(Chan *c, char *a, long n)
}

long
scsiwrite(Chan *c, char *a, long n)
scsiwrite(Chan *c, char *a, long n, ulong offset)
{
	Scsi *cmd = &staticcmd;
	if(c->qid.path==1 && n>0){
		if(c->offset == 0){
		if(offset == 0){
			n = 1;
			ownid=*a;
			scsiinit();


@@ 204,7 204,7 @@ scsiwrite(Chan *c, char *a, long n)
		n = cmd->data.ptr - cmd->data.base;
		break;
	case Qdebug:
		if (c->offset == 0) {
		if (offset == 0) {
			debugs[(c->qid.path>>4)&7] = (*a=='1');
			n = 1;
		} else

M port/devsrv.c => port/devsrv.c +2 -4
@@ 231,13 231,11 @@ srvdirentry(Entry *e, char *a, long count){
}

long
srvread(Chan *c, void *va, long n)
srvread(Chan *c, void *va, long n, ulong offset)
{
	Entry *dir, *e;
	int offset;

	dir = c->aux;
	offset = c->offset;
	isdir(c);
	if(n <= 0)
		return 0;


@@ 257,7 255,7 @@ srvread(Chan *c, void *va, long n)
}

long
srvwrite(Chan *c, void *va, long n)
srvwrite(Chan *c, void *va, long n, ulong offset)
{
	Entry *e;
	int i, fd;

M port/devwren.c => port/devwren.c +7 -7
@@ 202,7 202,7 @@ wrenclose(Chan *c)
#define	PSHORT(p, v)		((p)[0]=(v), (p)[1]=((v)>>8))
#define	PLONG(p, v)		(PSHORT(p, (v)), PSHORT(p+2, (v)>>16))
long
wrenread(Chan *c, char *a, long n)
wrenread(Chan *c, char *a, long n, ulong offset)
{
	Scsi *cmd = &staticcmd;
	unsigned long lbn;


@@ 219,9 219,9 @@ wrenread(Chan *c, char *a, long n)
	p = &(d->p[Mask&c->qid.path]);
	switch ((int)(c->qid.path & ~Mask)) {
	case Qdata:
		if (n % d->blocksize || c->offset % d->blocksize)
		if (n % d->blocksize || offset % d->blocksize)
			error(Ebadarg);
		lbn = (c->offset/d->blocksize) + p->firstblock;
		lbn = (offset/d->blocksize) + p->firstblock;
		if (lbn >= p->maxblock)
			error(Ebadarg);
		if (n > sizeof datablk)


@@ 252,7 252,7 @@ wrenread(Chan *c, char *a, long n)
	case Qstruct:
		if (n < 8)
			error(Ebadarg);
		if (c->offset >= 8)
		if (offset >= 8)
			return 0;
		n = 8;
		PLONG((uchar *)&a[0], p->maxblock - p->firstblock);


@@ 265,7 265,7 @@ wrenread(Chan *c, char *a, long n)
}

long
wrenwrite(Chan *c, char *a, long n)
wrenwrite(Chan *c, char *a, long n, ulong offset)
{
	Scsi *cmd = &staticcmd;
	unsigned long lbn;


@@ 279,9 279,9 @@ wrenwrite(Chan *c, char *a, long n)
	p = &(d->p[Mask&c->qid.path]);
	switch ((int)(c->qid.path & ~Mask)) {
	case Qdata:
		if (n % d->blocksize || c->offset % d->blocksize)
		if (n % d->blocksize || offset % d->blocksize)
			error(Ebadarg);
		lbn = c->offset/d->blocksize + p->firstblock;
		lbn = offset/d->blocksize + p->firstblock;
		if (lbn >= p->maxblock)
			error(Ebadarg);
		if (n > sizeof datablk)

M port/fault.c => port/fault.c +4 -5
@@ 79,20 79,19 @@ fault(ulong addr, int read)
				n = BY2PG;
			pg = newpage(1, o, addr);
			k = kmap(pg);
			qlock(o->chan);
			qlock(&o->chan->rdl);
			if(waserror()){
				kunmap(k);
				qunlock(o->chan);
				qunlock(&o->chan->rdl);
				pg->o = 0;
				pg->ref--;
				pexit("load i/o error", 0);
			}
			o->chan->offset = (addr-o->va) + o->minca;
			l = (char*)VA(k);
			if((*devtab[o->chan->type].read)(o->chan, l, n) != n)
			if((*devtab[o->chan->type].read)(o->chan, l, n, (addr-o->va) + o->minca) != n)
				error(Eioload);
			flushpage(pg->pa);
			qunlock(o->chan);
			qunlock(&o->chan->rdl);
			if(n<BY2PG)
				memset(l+n, 0, BY2PG-n);
			lock(o);

M port/stream.c => port/stream.c +24 -8
@@ 790,6 790,7 @@ streamnew(ushort type, ushort dev, ushort id, Qinfo *qi, int noopen)
	s->type = type;
	s->dev = dev;
	s->id = id;
	s->err = 0;

	/*
 	 *  hang a device and process q off the stream


@@ 801,6 802,8 @@ streamnew(ushort type, ushort dev, ushort id, Qinfo *qi, int noopen)
		s->opens = 1;
	s->hread = 0;
	q = allocq(&procinfo);
	WR(q)->ptr = s;
	RD(q)->ptr = s;
	s->procq = WR(q);
	q = allocq(qi);
	s->devq = RD(q);


@@ 895,6 898,8 @@ streamexit(Stream *s, int locked)
			freeq(q);
		}
		s->id = s->dev = s->type = 0;
		if(s->err)
			freeb(s->err);
	}
	s->inuse--;
	rv = s->inuse;


@@ 972,9 977,14 @@ void
stputq(Queue *q, Block *bp)
{
	int delim;
	Stream *s;

	if(bp->type == M_HANGUP){
		freeb(bp);
		s = q->ptr;
		if(bp->rptr<bp->wptr && s->err==0)
			s->err = bp;
		else
			freeb(bp);
		q->flag |= QHUNGUP;
		q->other->flag |= QHUNGUP;
		wakeup(q->other->rp);


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

	i = strlen(str);
	i -= c->offset;
	i -= offset;
	if(i<n)
		n = i;
	if(n<0)
		return 0;
	memmove(buf, str + c->offset, n);
	memmove(buf, str + offset, n);
	return n;
}



@@ 1036,7 1046,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);
		return stringread(c, buf, n, num, c->offset);
	} else {
		if(CHDIR & c->qid.path)
			return devdirread(c, vbuf, n, 0, 0, streamgen);


@@ 1091,7 1101,9 @@ streamread(Chan *c, void *vbuf, long n)
		bp = getq(q);
		if(bp == 0){
			if(q->flag & QHUNGUP){
				if(s->hread++ < 3)
				if(s->err)
					errors((char*)s->err->rptr);
				else if(s->hread++<3)
					break;
				else
					error(Ehungup);


@@ 1246,8 1258,12 @@ streamwrite(Chan *c, void *a, long n, int docopy)
	 *  No writes allowed on hungup channels
	 */
	q = s->procq;
	if(q->other->flag & QHUNGUP)
		error(Ehungup);
	if(q->other->flag & QHUNGUP){
		if(s->err)
			errors((char*)(s->err->rptr));
		else
			error(Ehungup);
	}

	if(!docopy && isphys(a)){
		/*

M port/sysfile.c => port/sysfile.c +15 -12
@@ 191,7 191,7 @@ unionread(Chan *c, void *va, long n)
	}
	nc = (*devtab[nc->type].open)(nc, OREAD);
	nc->offset = c->offset;
	nr = (*devtab[nc->type].read)(nc, va, n);
	nr = (*devtab[nc->type].read)(nc, va, n, nc->offset);
	c->offset = nc->offset;		/* devdirread e.g. changes it */
	close(nc);
	poperror();


@@ 226,9 226,9 @@ sysread(ulong *arg)

	c = fdtochan(arg[0], OREAD);
	validaddr(arg[1], arg[2], 1);
	qlock(c);
	qlock(&c->rdl);
	if(waserror()){
		qunlock(c);
		qunlock(&c->rdl);
		nexterror();
	}
	n = arg[2];


@@ 240,9 240,9 @@ sysread(ulong *arg)
	if((c->qid.path&CHDIR) && (c->flag&CMOUNT))
		n = unionread(c, (void*)arg[1], n);
	else
		n = (*devtab[c->type].read)(c, (void*)arg[1], n);
		n = (*devtab[c->type].read)(c, (void*)arg[1], n, c->offset);
	c->offset += n;
	qunlock(c);
	qunlock(&c->rdl);
	return n;
}



@@ 254,16 254,16 @@ syswrite(ulong *arg)

	c = fdtochan(arg[0], OWRITE);
	validaddr(arg[1], arg[2], 0);
	qlock(c);
	qlock(&c->wrl);
	if(waserror()){
		qunlock(c);
		qunlock(&c->wrl);
		nexterror();
	}
	if(c->qid.path & CHDIR)
		error(Eisdir);
	n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2]);
	n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2], c->offset);
	c->offset += n;
	qunlock(c);
	qunlock(&c->wrl);
	return n;
}



@@ 280,9 280,11 @@ sysseek(ulong *arg)
		error(Eisdir);
	if(devchar[c->type] == '|')
		error(Eisstream);
	qlock(c);
	qlock(&c->rdl);
	qlock(&c->wrl);
	if(waserror()){
		qunlock(c);
		qunlock(&c->rdl);
		qunlock(&c->wrl);
		nexterror();
	}
	switch(arg[2]){


@@ 301,7 303,8 @@ sysseek(ulong *arg)
		break;
	}
	off = c->offset;
	qunlock(c);
	qunlock(&c->rdl);
	qunlock(&c->wrl);
	poperror();
	return off;
}

M port/sysproc.c => port/sysproc.c +1 -1
@@ 170,7 170,7 @@ sysexec(ulong *arg)
	}
	if(!indir)
		strcpy(elem, u->elem);
	n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec));
	n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0);
	if(n < 2)
    Err:
		error(Ebadexec);

M power/dat.h => power/dat.h +5 -3
@@ 106,7 106,8 @@ struct Hotmsg
#define	CHDIR	0x80000000L
struct Chan
{
	QLock;				/* general access */
	QLock	rdl;			/* read access */
	QLock	wrl;			/* write access */
	Ref;
	union{
		Chan	*next;		/* allocation */


@@ 181,8 182,8 @@ struct Dev
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long);
	long	 (*write)(Chan*, void*, long);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong);
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
};


@@ 481,6 482,7 @@ struct Stream {
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)

M power/devbit3.c => power/devbit3.c +2 -2
@@ 130,7 130,7 @@ bit3close(Chan *c)
 */

long	 
bit3read(Chan *c, void *buf, long n)
bit3read(Chan *c, void *buf, long n, ulong offset)
{
	Bit3msg *bp;
	int docpy;


@@ 174,7 174,7 @@ bit3read(Chan *c, void *buf, long n)
}

long	 
bit3write(Chan *c, void *buf, long n)
bit3write(Chan *c, void *buf, long n, ulong offset)
{
	Bit3msg *bp;


M power/devhotrod.c => power/devhotrod.c +2 -2
@@ 272,7 272,7 @@ hotmsgintr(Hotmsg *hm)
 */

long	 
hotrodread(Chan *c, void *buf, long n)
hotrodread(Chan *c, void *buf, long n, ulong offset)
{
	Hotrod *hp;
	Hotmsg *mp, **hmp;


@@ 389,7 389,7 @@ hotrodread(Chan *c, void *buf, long n)
}

long	 
hotrodwrite(Chan *c, void *buf, long n)
hotrodwrite(Chan *c, void *buf, long n, ulong offset)
{
	Hotrod *hp;
	Hotmsg *mp, **hmp;

M power/devhs.c => power/devhs.c +2 -2
@@ 218,13 218,13 @@ hsvmeclose(Chan *c)
}

long	 
hsvmeread(Chan *c, void *buf, long n)
hsvmeread(Chan *c, void *buf, long n, ulong offset)
{
	return streamread(c, buf, n);
}

long	 
hsvmewrite(Chan *c, void *buf, long n)
hsvmewrite(Chan *c, void *buf, long n, ulong offset)
{
	return streamwrite(c, buf, n, 0);
}

M power/devrtc.c => power/devrtc.c +4 -4
@@ 137,7 137,7 @@ rtcclose(Chan *c)
#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4))

long	 
rtcread(Chan *c, void *buf, long n)
rtcread(Chan *c, void *buf, long n, ulong offset)
{
	int i,j;
	uchar ch;


@@ 192,13 192,13 @@ rtcread(Chan *c, void *buf, long n)
	else
		rtc.year += 1900;

	return readnum(c->offset, buf, n, rtc2sec(&rtc), 12);
	return readnum(offset, buf, n, rtc2sec(&rtc), 12);
}

#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4)

long	 
rtcwrite(Chan *c, void *buf, long n)
rtcwrite(Chan *c, void *buf, long n, ulong offset)
{
	Rtc rtc;
	ulong secs;


@@ 208,7 208,7 @@ rtcwrite(Chan *c, void *buf, long n)
	uchar *nv;
	char *cp, *ep;

	if(c->offset!=0)
	if(offset!=0)
		error(Ebadarg);

	/*

M power/fns.h => power/fns.h +1 -1
@@ 186,7 186,7 @@ Stream	*streamnew(ushort, ushort, ushort, Qinfo*, int);
void	streamopen(Chan*, Qinfo*);
int	streamparse(char*, Block*);
void	streamstat(Chan*, char*, char*);
long	stringread(Chan*, void*, long, char*);
long	stringread(Chan*, void*, long, char*, ulong);
long	syscall(Ureg*);
void	sysloginit(void);
void	syslog(char*, int);

M ss/dat.h => ss/dat.h +3 -2
@@ 173,8 173,8 @@ struct Dev
	Chan	*(*open)(Chan*, int);
	void	 (*create)(Chan*, char*, int, ulong);
	void	 (*close)(Chan*);
	long	 (*read)(Chan*, void*, long);
	long	 (*write)(Chan*, void*, long);
	long	 (*read)(Chan*, void*, long, ulong);
	long	 (*write)(Chan*, void*, long, ulong );
	void	 (*remove)(Chan*);
	void	 (*wstat)(Chan*, char*);
};


@@ 478,6 478,7 @@ struct Stream {
	QLock	rdlock;		/* read lock */
	Queue	*procq;		/* write queue at process end */
	Queue	*devq;		/* read queue at device end */
	Block	*err;		/* error message from down stream */
};
#define	RD(q)		((q)->other < (q) ? (q->other) : q)
#define	WR(q)		((q)->other > (q) ? (q->other) : q)

M ss/mem.h => ss/mem.h +1 -1
@@ 132,4 132,4 @@
#define	NSEG		5
#define	MACHSIZE	4096

#define isphys(x) ((((ulong)(x)&0xF0000000) == KZERO)
#define isphys(x) (((ulong)(x)&0xF0000000) == KZERO)