~kris/9p

9hist

dc9f8fe42b544576b468f5013cbcc476e74a002f — David du Colombier 28 years ago b3e9884
Plan 9 from Bell Labs 1998-03-27
M ip/devip.c => ip/devip.c +1 -1
@@ 1080,7 1080,7 @@ Fsconnected(Conv* c, char* msg)
Proto*
Fsrcvpcol(Fs* f, uchar proto)
{
	if(f->t2m[proto] && f->ipmux)
	if(f->ipmux)
		return f->ipmux;
	else
		return f->t2p[proto];

M ip/ip.h => ip/ip.h +1 -2
@@ 241,8 241,7 @@ struct Fs

	int	np;
	Proto*	p[Maxproto+1];		/* list of supported protocols */
	Proto*	t2p[256];		/* vector of all ip protocol handlers */
	Ipmux*	t2m[256];		/* vector of all ip multiplexors */
	Proto*	t2p[256];		/* vector of all protocols */
	Proto*	ipifc;			/* kludge for ipifcremroute & ipifcaddroute */
	Proto*	ipmux;			/* kludge for finding an ip multiplexor */


M ip/ipmux.c => ip/ipmux.c +117 -55
@@ 32,6 32,7 @@ struct Iphdr
	uchar	dst[4];		/* IP destination */
	uchar	data[1];	/* start of data */
};
Iphdr *ipoff = 0;

enum
{


@@ 66,6 67,7 @@ struct Ipmux
	uchar	*mask;

	int	ref;		/* so we can garbage collect */
	Conv	*conv;
};

/*


@@ 74,7 76,6 @@ struct Ipmux
struct Ipmuxrock
{
	Ipmux	*chain;
	int	proto;
};

static char*


@@ 107,25 108,28 @@ parseop(char **pp)
	int type, off, end, len;
	Ipmux *f;

	off = 0;
	p = skipwhite(p);
	if(strncmp(p, "dst", 3) == 0){
		type = Tdst;
		len = IPaddrlen;
		off = ((ulong)(ipoff->dst)) - IPHDR;
		len = IPv4addrlen;
		p += 3;
	}
	else if(strncmp(p, "src", 3) == 0){
		type = Tsrc;
		len = IPaddrlen;
		off = ((ulong)(ipoff->src)) - IPHDR;
		len = IPv4addrlen;
		p += 3;
	}
	else if(strncmp(p, "ifc", 3) == 0){
		type = Tifc;
		len = IPaddrlen;
		off = -IPv4addrlen - IPHDR;
		len = IPv4addrlen;
		p += 3;
	}
	else if(strncmp(p, "proto", 5) == 0){
		type = Tproto;
		off = ((ulong)&(ipoff->proto)) - IPHDR;
		len = 1;
		p += 5;
	}


@@ 137,6 141,8 @@ parseop(char **pp)
			return nil;
		p++;
		off = strtoul(p, &p, 0);
		if(off < 0 || off > (64-IPHDR))
			return nil;
		p = skipwhite(p);
		if(*p != ':')
			end = off;


@@ 150,8 156,9 @@ parseop(char **pp)
		}
		if(*p != ']')
			return nil;
		len = end - off + 1;
		p++;
		len = end - off + 1;
		off += ((ulong)(ipoff->data)) - IPHDR;
	}
	else 
		return nil;


@@ 198,7 205,7 @@ parseval(uchar *v, char *p, int len)
}

static Ipmux*
parsedemux(char *p)
parsemux(char *p)
{
	int n;
	Ipmux *f;


@@ 234,11 241,13 @@ parsedemux(char *p)
		default:
			goto parseerror;
		}
	} else
		f->mask = nil;
	} else {
		f->mask = smalloc(f->len);
		memset(f->mask, 0xff, f->len);
	}

	/* parse vals */
	f->n = tokenize(val, vals, sizeof(vals)/sizeof(char*));
	f->n = parsefields(val, vals, sizeof(vals)/sizeof(char*), "|");
	if(f->n == 0)
		goto parseerror;
	f->val = smalloc(f->n*f->len);


@@ 374,6 383,8 @@ ipmuxfree(Ipmux *f)
static void
ipmuxtreefree(Ipmux *f)
{
	if(f == nil)
		return;
	if(f->no != nil)
		ipmuxfree(f->no);
	if(f->yes != nil)


@@ 481,7 492,7 @@ ipmuxremove(Ipmux **l, Ipmux *f)
static char*
ipmuxconnect(Conv *c, char **argv, int argc)
{
	int n, proto;
	int i, n;
	char *field[10];
	Ipmux *mux, *chain;
	Ipmuxrock *r;


@@ 496,36 507,28 @@ ipmuxconnect(Conv *c, char **argv, int argc)
	if(n <= 0)
		return Ebadarg;

	chain = nil; 
	chain = nil;
	mux = nil;
	for(i = 0; i < n; i++){
		mux = ipmuxparse(field[i]);
		mux = parsemux(field[i]);
		if(mux == nil){
			ipmuxtreefree(chain);
			return Ebadarg;
		}
		ipmuxchain(&chain, mux);
	}

	/* optimize the protocol into an array lookup */
	if(chain->type != Tproto){
		ipmuxtreefree(chain);
		return "need proto rule";
	}
	mux = chain;
	proto = mux->val;
	chain = chain->yes;
	ipmuxfree(mux);
	if(chain == nil)
		return Ebadarg;
	mux->conv = c;

	/* save a copy of the chain so we can later remove it */
	mux->conv = c;
	mux = ipmuxcopy(chain);
	r = (Ipmuxrock*)(c->ptcl);
	r->chain = chain;
	r->proto = proto;

	/* add the chain to the protocol demultiplexor tree */
	wlock(f);
	f->t2m[proto] = ipmuxmerge(f->t2m[proto], mux);
	f->ipmux->priv = ipmuxmerge(f->ipmux->priv, mux);
	wunlock(f);

	Fsconnected(c, nil);


@@ 542,9 545,12 @@ ipmuxstate(Conv *c, char *state, int n)
static void
ipmuxcreate(Conv *c)
{
	Ipmuxrock *r;

	c->rq = qopen(64*1024, 0, 0, c);
	c->wq = qopen(64*1024, 0, 0, 0);
	*(IPmux**)(c->ptcl) = nil;
	r = (Ipmuxrock*)(c->ptcl);
	r->chain = nil;
}

static char*


@@ 557,10 563,9 @@ static void
ipmuxclose(Conv *c)
{
	Ipmuxrock *r;
	Fs *f = c->p->f;

	r = (Ipmuxrock*)(c->ptcl);
	r->chain = chain;
	r->proto = proto;

	qclose(c->rq);
	qclose(c->wq);


@@ 571,9 576,9 @@ ipmuxclose(Conv *c)
	c->rport = 0;

	wlock(f);
	ipmuxremove(&(f->t2m[r->proto]), r->chain);
	ipmuxremove(&(c->p->priv), r->chain);
	wunlock(f);
	ipmuxtreefree(f->chain);
	ipmuxtreefree(r->chain);

	unlock(c);
}


@@ 583,8 588,14 @@ ipmuxclose(Conv *c)
 *  the stack
 */
static void
ipmuxkick(Conv *c, int l)
ipmuxkick(Conv *c, int)
{
	Block *bp;

	bp = qget(c->wq);
	if(bp == nil)
		return;
	ipoput(c->p->f, bp, 0, 0);
}

static void


@@ 594,24 605,31 @@ ipmuxiput(Proto *p, uchar *ia, Block *bp)
	Fs *f = p->f;
	uchar *m, *h, *v, *e, *ve, *hp;
	Conv *c;
	Ipmux *mux;
	Iphdr *ip;

	rlock(f);
	mux = f->t2m[ip->proto];
	if(mux == nil)
		goto out;
	if(p->priv == nil)
		goto nomatch;

	/* make interface address part of packet */
	h = bp->rptr - IPHDR - IPv4addrlen;
	h = bp->rp - IPHDR - IPv4addrlen;
	if(h < bp->base){
		bp = padblock(bp, IPHDR + IPv4addrlen);
		h = bp->rptr;
		bp->rptr += IPHDR + IPv4addrlen;
		h = bp->rp;
		bp->rp += IPHDR + IPv4addrlen;
	}
	memmove(h, ia+IPv4off, ia);
	memmove(h, ia+IPv4off, IPv4addrlen);
	len = BLEN(bp);

	/* run the v4 filter */
	/* run the v4 filter (needs optimizing) */
	rlock(f);
	c = nil;
	mux = f->ipmux->priv;
	while(mux != nil){
		if(mux->len + mux->off > len){
			mux = mux->no;
			continue;
		}
		v = mux->val;
		for(e = v + mux->n*mux->len; v < e; v = ve){
			m = mux->mask;


@@ 621,35 639,77 @@ ipmuxiput(Proto *p, uchar *ia, Block *bp)
					break;
			}
			if(v == ve){
				if(mux->c != nil)
					c = mux->c;
				if(mux->conv != nil)
					c = mux->conv;
				mux = mux->yes;
				if(
				
				break;
			}
		}
			
		mux = mux->no;
		continue;
		if(v == e)
			mux = mux->no;
	}
out:
	/* doesn't match any filter, hand it to the specific protocol handler */
	runlock(f);

	if(c != nil){
		bp->rp -= IPHDR;
		if(bp->next){
			bp = concatblock(bp);
			if(bp == 0)
				panic("ilpullup");
		}
		qpass(c->rq, bp);
	}

nomatch:
	/* doesn't match any filter, hand it to the specific protocol handler */
	ip = (Iphdr*)bp->rp;
	p = f->t2p[ip->proto];
	if(p)
		(*p->rcv)(p, ia, bp);
	else
		freeblist(bp);
	return;	
	return;
}

int
static int
ipmuxsprint(Ipmux *mux, int level, char *buf, int len)
{
	int i, j, n;

	n = 0;
	if(mux == nil)
		return n;
	for(i = 0; i < level; i++)
		n += snprint(buf+n, len-n, " ");
	n += snprint(buf+n, len-n, "h[%d:%d] & ", mux->off, mux->off+mux->len-1);
	for(i = 0; i < mux->len; i++)
		n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
	for(j = 0; j < mux->n; j++){
		for(i = 0; i < mux->len; i++)
			n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
		n += snprint(buf+n, len-n, "|");
	}
	level++;
	n += ipmuxsprint(mux->no, level, buf+n, len-n);
	n += ipmuxsprint(mux->yes, level, buf+n, len-n);
	return n;
}

static int
ipmuxstats(Proto *p, char *buf, int len)
{
	return 0;
	int n;
	Fs *f = p->f;

	rlock(f);
	n = ipmuxsprint(p->priv, 0, buf, len);
	runlock(f);

	return n;
}

void
ipmuxinit(Fs *fs)
ipmuxinit(Fs *f)
{
	Proto *ipmux;



@@ 670,5 730,7 @@ ipmuxinit(Fs *fs)
	ipmux->nc = 64;
	ipmux->ptclsize = sizeof(Ipmuxrock);

	Fsproto(fs, ipmux);
	f->ipmux = ipmux;			/* hack for Fsrcvpcol */

	Fsproto(f, ipmux);
}

M pc/devata.c => pc/devata.c +46 -41
@@ 130,7 130,7 @@ struct Drive
	int	state;
	char	vol[NAMELEN];

	ulong	cap;		/* total bytes */
	vlong	cap;		/* total bytes */
	int	bytes;		/* bytes/sector */
	int	sectors;	/* sectors/track */
	int	heads;		/* heads/cyl */


@@ 190,7 190,7 @@ static int defirq[NCtlr] = {
};

static void	ataintr(Ureg*, void*);
static long	ataxfer(Drive*, Partition*, int, ulong, long, uchar*);
static long	ataxfer(Drive*, Partition*, int, vlong, long, uchar*);
static void	ataident(Drive*);
static void	atafeature(Drive*, uchar);
static void	ataparams(Drive*);


@@ 200,7 200,7 @@ static void	atasleep(Controller*, int);
static void	ataclock(void);

static int	isatapi(Drive*);
static long	atapirwio(Chan*, uchar*, ulong, ulong, int);
static long	atapirwio(Chan*, uchar*, ulong, vlong, int);
static void	atapipart(Drive*);
static void	atapiintr(Controller*);



@@ 212,7 212,7 @@ atagen(Chan* c, Dirtab*, int, int s, Dir* dirp)
	char name[NAMELEN+4];
	Drive *dp;
	Partition *pp;
	ulong l;
	vlong l;

	qid.vers = 0;
	drive = s/Npart;


@@ 231,7 231,7 @@ atagen(Chan* c, Dirtab*, int, int s, Dir* dirp)
	sprint(name, "%s%s", dp->vol, pp->name);
	name[NAMELEN] = 0;
	qid.path = MKQID(drive, s);
	l = (pp->end - pp->start) * dp->bytes;
	l = (pp->end - pp->start) * (vlong)dp->bytes;
	devdir(c, qid, name, l, eve, 0660, dirp);
	return 1;
}


@@ 642,7 642,6 @@ ataread(Chan* c, void* a, long n, vlong off)
	uchar *aa = a;
	Partition *pp;
	uchar *buf;
	ulong offset = off;

	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, 0, 0, atagen);


@@ 660,7 659,7 @@ ataread(Chan* c, void* a, long n, vlong off)
			atapipart(dp);
		qunlock(dp);
		poperror();
		return atapirwio(c, a, n, offset, Cread2);
		return atapirwio(c, a, n, off, Cread2);
	}
	pp = &dp->p[PART(c->qid.path)];



@@ 670,9 669,9 @@ ataread(Chan* c, void* a, long n, vlong off)
		nexterror();
	}

	skip = offset % dp->bytes;
	skip = off % dp->bytes;
	for(rv = 0; rv < n; rv += i){
		i = ataxfer(dp, pp, Cread, offset+rv-skip, n-rv+skip, buf);
		i = ataxfer(dp, pp, Cread, off+rv-skip, n-rv+skip, buf);
		if(i == 0)
			break;
		i -= skip;


@@ 696,7 695,6 @@ atawrite(Chan *c, void *a, long n, vlong off)
	uchar *aa = a;
	Partition *pp;
	uchar *buf;
	ulong offset = off;

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


@@ 728,21 726,21 @@ atawrite(Chan *c, void *a, long n, vlong off)
	 *  read in the first sector before writing
	 *  it out.
	 */
	partial = offset % dp->bytes;
	partial = off % dp->bytes;
	if(partial){
		if(dp->atapi)
			atapirwio(c, buf, dp->bytes, offset-partial, Cread2);
			atapirwio(c, buf, dp->bytes, off-partial, Cread2);
		else
			ataxfer(dp, pp, Cread, offset-partial, dp->bytes, buf);
			ataxfer(dp, pp, Cread, off-partial, dp->bytes, buf);
		if(partial+n > dp->bytes)
			rv = dp->bytes - partial;
		else
			rv = n;
		memmove(buf+partial, aa, rv);
		if(dp->atapi)
			atapirwio(c, buf, dp->bytes, offset-partial, Cwrite2);
			atapirwio(c, buf, dp->bytes, off-partial, Cwrite2);
		else
			ataxfer(dp, pp, Cwrite, offset-partial, dp->bytes, buf);
			ataxfer(dp, pp, Cwrite, off-partial, dp->bytes, buf);
	} else
		rv = 0;



@@ 757,9 755,9 @@ atawrite(Chan *c, void *a, long n, vlong off)
			i = Maxxfer;
		memmove(buf, aa+rv, i);
		if(dp->atapi)
			i = atapirwio(c, buf, i, offset+rv, Cwrite2);
			i = atapirwio(c, buf, i, off+rv, Cwrite2);
		else
			i = ataxfer(dp, pp, Cwrite, offset+rv, i, buf);
			i = ataxfer(dp, pp, Cwrite, off+rv, i, buf);
		if(i == 0)
			break;
	}


@@ 771,14 769,14 @@ atawrite(Chan *c, void *a, long n, vlong off)
	 */
	if(partial){
		if(dp->atapi)
			atapirwio(c, buf, dp->bytes, offset+rv, Cread2);
			atapirwio(c, buf, dp->bytes, off+rv, Cread2);
		else
			ataxfer(dp, pp, Cread, offset+rv, dp->bytes, buf);
			ataxfer(dp, pp, Cread, off+rv, dp->bytes, buf);
		memmove(buf, aa+rv, partial);
		if(dp->atapi)
			atapirwio(c, buf, dp->bytes, offset+rv, Cwrite2);
			atapirwio(c, buf, dp->bytes, off+rv, Cwrite2);
		else
			ataxfer(dp, pp, Cwrite, offset+rv, dp->bytes, buf);
			ataxfer(dp, pp, Cwrite, off+rv, dp->bytes, buf);
		rv += partial;
	}



@@ 832,7 830,8 @@ atarepl(Drive *dp, long bblk)
		return;
	for(i = 0; i < dp->repl.nrepl; i++){
		if(dp->repl.blk[i] == bblk)
			DPRINT("%s: found bblk %ld at offset %ld\n", dp->vol, bblk, i);
			DPRINT("%s: found bblk %ld at offset %ld\n",
			dp->vol, bblk, i);
	}
}



@@ 852,12 851,13 @@ atasleep(Controller *cp, int ms)
 *  parts.
 */
static long
ataxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len, uchar *buf)
ataxfer(Drive *dp, Partition *pp, int cmd, vlong off, long len, uchar *buf)
{
	Controller *cp;
	long lblk;
	int cyl, sec, head;
	int loop, stat;
	ulong start;

	if(dp->online == 0)
		error(Eio);


@@ 865,7 865,7 @@ ataxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len, uchar *buf)
	/*
	 *  cut transfer size down to disk buffer size
	 */
	start = start / dp->bytes;
	start = off / dp->bytes;
	if(len > Maxxfer)
		len = Maxxfer;
	len = (len + dp->bytes - 1) / dp->bytes;


@@ 890,7 890,8 @@ ataxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len, uchar *buf)
		head = ((lblk/dp->sectors) % dp->heads);
	}

	XPRINT("%s: ataxfer cyl %d sec %d head %d len %d\n", dp->vol, cyl, sec, head, len);
	XPRINT("%s: ataxfer cyl %d sec %d head %d len %d\n",
		dp->vol, cyl, sec, head, len);

	cp = dp->cp;
	qlock(cp->ctlrlock);


@@ 1140,8 1141,9 @@ retryatapi:
	dp->cyl = ip->cyls;
	dp->heads = ip->heads;
	dp->sectors = ip->s2t;
	XPRINT("%s: %s %d/%d/%d CHS %d bytes\n",
		dp->vol, id, dp->cyl, dp->heads, dp->sectors, dp->cap);
	XPRINT("%s: %s %d/%d/%d CHS %lld bytes\n",
		dp->vol, id, dp->cyl, dp->heads, dp->sectors,
		dp->cap);

	if(ip->cvalid&(1<<0)){
		/* use current settings */


@@ 1156,13 1158,14 @@ retryatapi:
	if((ip->capabilities & (1<<9)) && (lbasecs & 0xf0000000) == 0){
		dp->lba = 1;
		dp->lbasecs = lbasecs;
		dp->cap = dp->bytes * dp->lbasecs;
		XPRINT("%s: LBA: %s %d sectors %d bytes\n",
			dp->vol, id, dp->lbasecs, dp->cap);
		dp->cap = (vlong)dp->bytes * dp->lbasecs;
		XPRINT("%s: LBA: %s %d sectors %lld bytes\n",
			dp->vol, id, dp->lbasecs,
			dp->cap);
	} else {
		dp->lba = 0;
		dp->lbasecs = 0;
		dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
		dp->cap = (vlong)dp->bytes * dp->cyl * dp->heads * dp->sectors;
	}

	if(cp->cmd){


@@ 1285,9 1288,10 @@ ataparams(Drive *dp)
			lo = i;
	}
	dp->cyl = lo + 1;
	dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
	DPRINT("%s: probed: %d/%d/%d CHS %d bytes\n",
		dp->vol, dp->cyl, dp->heads, dp->sectors, dp->cap);
	dp->cap = (vlong)dp->bytes * dp->cyl * dp->heads * dp->sectors;
	DPRINT("%s: probed: %d/%d/%d CHS %lld bytes\n",
		dp->vol, dp->cyl, dp->heads, dp->sectors,
		dp->cap);
	if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0)
		error(Eio);
}


@@ 1703,7 1707,7 @@ atapiexec(Drive *dp)
}

static long
atapiio(Drive *dp, uchar *a, ulong len, ulong offset, int cmd)
atapiio(Drive *dp, uchar *a, ulong len, vlong off, int cmd)
{
	ulong bn, n, o, m;
	Controller *cp;


@@ 1718,6 1722,7 @@ atapiio(Drive *dp, uchar *a, ulong len, ulong offset, int cmd)
		buf = 0;
	qlock(cp->ctlrlock);
	retrycount = 2;

retry:
	if(waserror()){
		dp->partok = 0;


@@ 1744,10 1749,10 @@ retry:

	n = len;
	while(n > 0){
		bn = offset / dp->bytes;
		if(offset > dp->cap-dp->bytes)
		bn = off / dp->bytes;
		if(off > dp->cap-dp->bytes)
			break;
		o = offset % dp->bytes;
		o = off % dp->bytes;
		m = dp->bytes - o;
		if(m > n)
			m = n;


@@ 1766,7 1771,7 @@ retry:
		}
		memmove(a, cp->buf + o, m);
		n -= m;
		offset += m;
		off += m;
		a += m;
	}
	poperror();


@@ 1778,7 1783,7 @@ retry:
}

static long
atapirwio(Chan *c, uchar *a, ulong len, ulong offset, int cmd)
atapirwio(Chan *c, uchar *a, ulong len, vlong off, int cmd)
{
	Drive *dp;
	ulong vers;


@@ 1796,7 1801,7 @@ atapirwio(Chan *c, uchar *a, ulong len, ulong offset, int cmd)
	c->qid.vers = dp->vers;
	if(vers && vers != dp->vers)
		error(Eio);
	rv = atapiio(dp, a, len, offset, cmd);
	rv = atapiio(dp, a, len, off, cmd);

	poperror();
	qunlock(dp);

M pc/devi82365.c => pc/devi82365.c +8 -7
@@ 187,8 187,8 @@ static void	cisread(Slot*);
static void	i82365intr(Ureg*, void*);
static void	i82365reset(void);
static int	pcmio(int, ISAConf*);
static long	pcmread(int, int, void*, long, ulong);
static long	pcmwrite(int, int, void*, long, ulong);
static long	pcmread(int, int, void*, long, vlong);
static long	pcmwrite(int, int, void*, long, vlong);

static void i82365dump(Slot*);



@@ 713,12 713,13 @@ memmoves(uchar *to, uchar *from, int n)
}

static long
pcmread(int slotno, int attr, void *a, long n, ulong offset)
pcmread(int slotno, int attr, void *a, long n, vlong off)
{
	int i, len;
	PCMmap *m;
	uchar *ac;
	Slot *pp;
	ulong offset = off;

	pp = slot + slotno;
	if(pp->memlen < offset)


@@ 765,7 766,7 @@ i82365read(Chan *c, void *a, long n, vlong off)
		return devdirread(c, a, n, 0, 0, pcmgen);
	case Qmem:
	case Qattr:
		return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, offset);
		return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off);
	case Qctl:
		p = malloc(READSTR);
		len = 0;


@@ 795,12 796,13 @@ i82365read(Chan *c, void *a, long n, vlong off)
}

static long
pcmwrite(int dev, int attr, void *a, long n, ulong offset)
pcmwrite(int dev, int attr, void *a, long n, vlong off)
{
	int i, len;
	PCMmap *m;
	uchar *ac;
	Slot *pp;
	ulong offset = off;

	pp = slot + dev;
	if(pp->memlen < offset)


@@ 839,7 841,6 @@ i82365write(Chan *c, void *a, long n, vlong off)
{
	Slot *pp;
	char buf[32];
	ulong offset = off;

	switch(TYPE(c)){
	case Qctl:


@@ 860,7 861,7 @@ i82365write(Chan *c, void *a, long n, vlong off)
		pp = slot + SLOTNO(c);
		if(pp->occupied == 0 || pp->enabled == 0)
			error(Eio);
		n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, offset);
		n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off);
		if(n < 0)
			error(Eio);
		return n;

M pc/etherelnk3.c => pc/etherelnk3.c +1 -1
@@ 1509,7 1509,7 @@ miir(Ether* ether, int phyad, int regad)

	if(data & 0x10000)
		return -1;
print("%d/%d: data=%uX\n", phyad, regad, data);
	XCVRDEBUG("phy%d/%d: data=%uX\n", phyad, regad, data);

	return data & 0xFFFF;
}

M pc/u.h => pc/u.h +1 -0
@@ 5,6 5,7 @@ typedef	signed char	schar;
typedef unsigned int	uint;
typedef unsigned long	ulong;
typedef	 long long	vlong;
typedef unsigned long long uvlong;
typedef union Length	Length;
typedef ushort		Rune;


M port/cache.c => port/cache.c +14 -5
@@ 231,13 231,17 @@ cdev(Mntcache *m, Chan *c)
}

int
cread(Chan *c, uchar *buf, int len, ulong offset)
cread(Chan *c, uchar *buf, int len, vlong off)
{
	KMap *k;
	Page *p;
	Mntcache *m;
	Extent *e, **t;
	int o, l, total;
	ulong offset;

	if(off+len > MAXCACHE)
		return 0;

	m = c->mcp;
	if(m == 0)


@@ 249,6 253,7 @@ cread(Chan *c, uchar *buf, int len, ulong offset)
		return 0;
	}

	offset = off;
	t = &m->list;
	for(e = *t; e; e = e->next) {
		if(offset >= e->start && offset < e->start+e->len)


@@ 390,14 395,15 @@ cpgmove(Extent *e, uchar *buf, int boff, int len)
}

void
cupdate(Chan *c, uchar *buf, int len, ulong offset)
cupdate(Chan *c, uchar *buf, int len, vlong off)
{
	Mntcache *m;
	Extent *tail;
	Extent *e, *f, *p;
	int o, ee, eblock;
	ulong offset;

	if(offset > MAXCACHE || len == 0)
	if(off > MAXCACHE || len == 0)
		return;

	m = c->mcp;


@@ 412,6 418,7 @@ cupdate(Chan *c, uchar *buf, int len, ulong offset)
	/*
	 * Find the insertion point
	 */
	offset = off;
	p = 0;
	for(f = m->list; f; f = f->next) {
		if(f->start >= offset)


@@ 498,14 505,15 @@ cupdate(Chan *c, uchar *buf, int len, ulong offset)
}

void
cwrite(Chan* c, uchar *buf, int len, ulong offset)
cwrite(Chan* c, uchar *buf, int len, vlong off)
{
	int o, n;
	Mntcache *m;
	ulong eblock, ee;
	Extent *p, *f, *e, *tail;
	ulong offset;

	if(offset > MAXCACHE || len == 0)
	if(off > MAXCACHE || len == 0)
		return;

	m = c->mcp;


@@ 518,6 526,7 @@ cwrite(Chan* c, uchar *buf, int len, ulong offset)
		return;
	}

	offset = off;
	m->vers++;
	c->qid.vers++;


M port/devaudio.c => port/devaudio.c +12 -6
@@ 964,20 964,26 @@ audioread(Chan *c, char *a, long n, vlong off)
					j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
				else{
					if(volumes[m].flag & Fin)
						j += snprint(buf+j, sizeof(buf)-j, " in %d", liv);
						j += snprint(buf+j, sizeof(buf)-j,
						" in %d", liv);
					if(volumes[m].flag & Fout)
						j += snprint(buf+j, sizeof(buf)-j, " out %d", lov);
						j += snprint(buf+j, sizeof(buf)-j,
						" out %d", lov);
				}
			}else{
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov && riv==rov)
					j += snprint(buf+j, sizeof(buf)-j, " left %d right %d",
				if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
				    liv==lov && riv==rov)
					j += snprint(buf+j, sizeof(buf)-j,
						" left %d right %d",
						liv, riv);
				else{
					if(volumes[m].flag & Fin)
						j += snprint(buf+j, sizeof(buf)-j, " in left %d right %d",
						j += snprint(buf+j, sizeof(buf)-j,
							" in left %d right %d",
							liv, riv);
					if(volumes[m].flag & Fout)
						j += snprint(buf+j, sizeof(buf)-j, " out left %d right %d",
						j += snprint(buf+j, sizeof(buf)-j,
							" out left %d right %d",
							lov, rov);
				}
			}

M port/devmnt.c => port/devmnt.c +18 -21
@@ 43,8 43,8 @@ void	mntgate(Mnt*);
void	mntpntfree(Mnt*);
void	mntqrm(Mnt*, Mntrpc*);
Mntrpc*	mntralloc(Chan*);
long	mntrdwr(int, Chan*, void*, long, ulong);
long	mnt9prdwr(int, Chan*, void*, long, ulong);
long	mntrdwr(int, Chan*, void*, long, vlong);
long	mnt9prdwr(int, Chan*, void*, long, vlong);
void	mntrpcread(Mnt*, Mntrpc*);
void	mountio(Mnt*, Mntrpc*);
void	mountmux(Mnt*, Mntrpc*);


@@ 475,9 475,9 @@ mntwstat(Chan *c, char *dp)
}

long	 
mntread9p(Chan *c, void *buf, long n, ulong offset)
mntread9p(Chan *c, void *buf, long n, vlong off)
{
	return mnt9prdwr(Tread, c, buf, n, offset);
	return mnt9prdwr(Tread, c, buf, n, off);
}

static long	 


@@ 485,7 485,6 @@ mntread(Chan *c, void *buf, long n, vlong off)
{
	uchar *p, *e;
	int nc, cache, isdir;
	ulong offset = off;

	isdir = 0;
	cache = c->flag & CCACHE;


@@ 496,20 495,20 @@ mntread(Chan *c, void *buf, long n, vlong off)

	p = buf;
	if(cache) {
		nc = cread(c, buf, n, offset);
		nc = cread(c, buf, n, off);
		if(nc > 0) {
			n -= nc;
			if(n == 0)
				return nc;
			p += nc;
			offset += nc;
			off += nc;
		}
		n = mntrdwr(Tread, c, p, n, offset);
		cupdate(c, p, n, offset);
		n = mntrdwr(Tread, c, p, n, off);
		cupdate(c, p, n, off);
		return n + nc;
	}

	n = mntrdwr(Tread, c, buf, n, offset);
	n = mntrdwr(Tread, c, buf, n, off);
	if(isdir) {
		for(e = &p[n]; p < e; p += DIRLEN)
			mntdirfix(p, c);


@@ 519,21 518,19 @@ mntread(Chan *c, void *buf, long n, vlong off)
}

long	 
mntwrite9p(Chan *c, void *buf, long n, ulong offset)
mntwrite9p(Chan *c, void *buf, long n, vlong off)
{
	return mnt9prdwr(Twrite, c, buf, n, offset);
	return mnt9prdwr(Twrite, c, buf, n, off);
}

static long	 
mntwrite(Chan *c, void *buf, long n, vlong off)
{
	ulong offset = off;

	return mntrdwr(Twrite, c, buf, n, offset);
	return mntrdwr(Twrite, c, buf, n, off);
}

long
mnt9prdwr(int type, Chan *c, void *buf, long n, ulong offset)
mnt9prdwr(int type, Chan *c, void *buf, long n, vlong off)
{
	Mnt *m;
 	ulong nr;


@@ 553,7 550,7 @@ mnt9prdwr(int type, Chan *c, void *buf, long n, ulong offset)
	}
	r->request.type = type;
	r->request.fid = c->fid;
	r->request.offset = offset;
	r->request.offset = off;
	r->request.data = buf;
	r->request.count = n;
	mountrpc(m, r);


@@ 570,7 567,7 @@ mnt9prdwr(int type, Chan *c, void *buf, long n, ulong offset)
}

long
mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
{
	Mnt *m;
 	Mntrpc *r;


@@ 592,7 589,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
		}
		r->request.type = type;
		r->request.fid = c->fid;
		r->request.offset = offset;
		r->request.offset = off;
		r->request.data = uba;
		r->request.count = limit(n, m->blocksize);
		mountrpc(m, r);


@@ 603,11 600,11 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
		if(type == Tread)
			memmove(uba, r->reply.data, nr);
		else if(cache)
			cwrite(c, (uchar*)uba, nr, offset);
			cwrite(c, (uchar*)uba, nr, off);

		poperror();
		mntfree(r);
		offset += nr;
		off += nr;
		uba += nr;
		cnt += nr;
		n -= nr;

M port/devsd.c => port/devsd.c +8 -8
@@ 231,17 231,17 @@ sdclose(Chan *c)
}

static long
sdread(Chan *c, void *a, long n, vlong offset)
sdread(Chan *c, void *a, long n, vlong off)
{

	if(c->qid.path & CHDIR)
		return devdirread(c, a, n, 0, 0, sdgen);

	return sdio(c, 0, a, n, offset);
	return sdio(c, 0, a, n, off);
}

static long
sdwrite(Chan *c, char *a, long n, vlong offset)
sdwrite(Chan *c, char *a, long n, vlong off)
{
	Disk *d;



@@ 249,7 249,7 @@ sdwrite(Chan *c, char *a, long n, vlong offset)

	if((d->inquire[0] & 0x1F) == TypeCD)
		error(Eperm);
	return sdio(c, 1, a, n, offset);
	return sdio(c, 1, a, n, off);
}

Dev sddevtab = {


@@ 354,13 354,13 @@ sdio(Chan *c, int write, char *a, ulong len, vlong off)
	Part *p;
	uchar *b;
	ulong block, n, max, x;
	ulong offset = off;
	ulong offset;

	d = &disk[DRIVE(c->qid)];
	p = &d->table[PART(c->qid)];

	block = (offset / d->bsize) + p->beg;
	n = (offset + len + d->bsize - 1) / d->bsize + p->beg - block;
	block = (off / d->bsize) + p->beg;
	n = (off + len + d->bsize - 1) / d->bsize + p->beg - block;
	max = SCSImaxxfer / d->bsize;
	if(n > max)
		n = max;


@@ 373,7 373,7 @@ sdio(Chan *c, int write, char *a, ulong len, vlong off)
	if(b == 0)
		return scsierrstr(STnomem);

	offset %= d->bsize;
	offset = off % d->bsize;
	if(write) {
		if(offset || len % d->bsize) {
			x = scsibio(d->t, d->lun, SCSIread, b, n, d->bsize, block);

M port/devssl.c => port/devssl.c +1 -3
@@ 427,15 427,13 @@ qremove(Block **l, int n, int discard)
}

static Block*
sslbread(Chan *c, long n, ulong offset)
sslbread(Chan *c, long n, ulong)
{
	volatile struct { Dstate *s; } s;
	Block *b;
	uchar count[2];
	int len, pad;

	USED(offset);

	s.s = dstate[CONV(c->qid)];
	if(s.s == 0)
		panic("sslbread");

M port/portfns.h => port/portfns.h +5 -5
@@ 48,10 48,10 @@ void		copen(Chan*);
Block*		concatblock(Block*);
Block*		copyblock(Block*, int);
void		copypage(Page*, Page*);
int		cread(Chan*, uchar*, int, ulong);
int		cread(Chan*, uchar*, int, vlong);
void		cunmount(Chan*, Chan*);
void		cupdate(Chan*, uchar*, int, ulong);
void		cwrite(Chan*, uchar*, int, ulong);
void		cupdate(Chan*, uchar*, int, vlong);
void		cwrite(Chan*, uchar*, int, vlong);
ulong		dbgpc(Proc*);
int		decref(Ref*);
int		decrypt(void*, void*, int);


@@ 148,9 148,9 @@ void		microdelay(int);
void		mmurelease(Proc*);
void		mmuswitch(Proc*);
void		mntdump(void);
long		mntread9p(Chan*, void*, long, ulong);
long		mntread9p(Chan*, void*, long, vlong);
void		mntrepl(char*);
long		mntwrite9p(Chan*, void*, long, ulong);
long		mntwrite9p(Chan*, void*, long, vlong);
void		mountfree(Mount*);
int		msize(void*);
Chan*		namec(char*, int, int, ulong);

M port/print.c => port/print.c +36 -6
@@ 219,6 219,10 @@ numbconv(va_list *arg, Fconv *fp)
	int i, f, n, b, ucase;
	short h;
	long v;
	vlong vl;

	SET(v);
	SET(vl);

	ucase = 0;
	b = fp->chr;


@@ 241,7 245,15 @@ numbconv(va_list *arg, Fconv *fp)
	}

	f = 0;
	switch(fp->f3 & (FLONG|FSHORT|FUNSIGN)) {
	switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) {
	case FVLONG|FLONG:
		vl = va_arg(*arg, vlong);
		break;

	case FUNSIGN|FVLONG|FLONG:
		vl = va_arg(*arg, uvlong);
		break;

	case FLONG:
		v = va_arg(*arg, long);
		break;


@@ 268,13 280,23 @@ numbconv(va_list *arg, Fconv *fp)
		v = va_arg(*arg, unsigned);
		break;
	}
	if(!(fp->f3 & FUNSIGN) && v < 0) {
		v = -v;
		f = 1;
	if(fp->f3 & FVLONG) {
		if(!(fp->f3 & FUNSIGN) && vl < 0) {
			vl = -vl;
			f = 1;
		}
	} else {
		if(!(fp->f3 & FUNSIGN) && v < 0) {
			v = -v;
			f = 1;
		}
	}
	s[IDIGIT-1] = 0;
	for(i = IDIGIT-2;; i--) {
		n = (ulong)v % b;
		if(fp->f3 & FVLONG)
			n = (uvlong)vl % b;
		else
			n = (ulong)v % b;
		n += '0';
		if(n > '9') {
			n += 'a' - ('9'+1);


@@ 284,9 306,17 @@ numbconv(va_list *arg, Fconv *fp)
		s[i] = n;
		if(i < 2)
			break;
		v = (ulong)v / b;
		if(fp->f3 & FVLONG)
			vl = (uvlong)vl / b;
		else
			v = (ulong)v / b;
		if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
			continue;
		if(fp->f3 & FVLONG) {
			if(vl <= 0)
				break;
			continue;
		}
		if(v <= 0)
			break;
	}