~kris/9p

9hist

39e8ef7beacede06996f1eda95880e82e8a1764a — David du Colombier 34 years ago 7beaef9
Plan 9 from Bell Labs 1992-08-25
M boot/local.c => boot/local.c +1 -1
@@ 7,7 7,7 @@ static char *disk;
void
configlocal(Method *mp)
{
	disk = mp->arg;
	disk = *sys ? sys : mp->arg;
	USED(mp);
}


A pc/devconfig.c => pc/devconfig.c +215 -0
@@ 0,0 1,215 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

#include	<libg.h>
#include	<gnot.h>
#include	"devtab.h"
#include	"vga.h"

/*
 *  Driver for various VGA cards
 */

char	monitor[NAMELEN];	/* monitor name and type */
char	vgacard[NAMELEN];	/* vga card type */
struct screeninfo {
	int	maxx, maxy;	/* current bits per screen */
	int	packed;		/* 0=planar, 1=packed */
	int	interlaced;	/* != 0 if interlaced */
} screeninfo;

enum {
	Qdir=		0,
	Qvgamonitor=	1,
	Qvgasize=	2,
	Qvgatype=	3,
	Qvgaport=	4,
	Qvgamem=	5,
	Qmouse=		6,
	Nvga=		6,
};

Dirtab vgadir[]={
	"mouseconf",	{Qmouse},	0,		0666,
	"vgamonitor",	{Qvgamonitor},	0,		0666,
	"vgatype",	{Qvgatype},	0,		0666,
	"vgasize",	{Qvgasize},	0,		0666,
	"vgaport",	{Qvgaport},	0,		0666,
	"vgamem",	{Qvgamem},	0,		0666,
};

/* a routine from ../port/devcons.c */
extern	int readstr(ulong, char *, ulong, char *);

void
configsetup(void) {
}

void
configreset(void) {
	strcpy(monitor, "generic");
	strcpy(vgacard, "generic");
	screeninfo.maxx = 640;
	screeninfo.maxy = 480;
	screeninfo.packed = 0;
	screeninfo.interlaced = 0;
}

void
configinit(void)
{
}

Chan*
configattach(char *upec)
{
	return devattach('v', upec);
}

Chan*
configclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
configwalk(Chan *c, char *name)
{
	return devwalk(c, name, vgadir, Nvga, devgen);
}

void
configstat(Chan *c, char *dp)
{
	devstat(c, dp, vgadir, Nvga, devgen);
}

Chan*
configopen(Chan *c, int omode)
{
	return devopen(c, omode, vgadir, Nvga, devgen);
}

void
configcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

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

long
configread(Chan *c, void *buf, long n, ulong offset)
{
	char obuf[60];
	int port;
	uchar *cp = buf;

	switch(c->qid.path&~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, vgadir, Nvga, devgen);
	case Qvgamonitor:
		return readstr(offset, buf, n, monitor);
	case Qvgatype:
		return readstr(offset, buf, n, vgacard);
	case Qvgasize:
		sprint(obuf, "%d %d",
			gscreen.r.max.x, gscreen.r.max.y);
		return readstr(offset, buf, n, obuf);
	case Qvgaport:
		if (offset + n >= 0x8000)
			error(Ebadarg);
		for (port=offset; port<offset+n; port++)
			*cp++ = inb(port);
		return n;
	case Qvgamem:
		if (offset > 0x10000)
			return 0;
		if (offset + n > 0x10000)
			n = 0x10000 - offset;
		memmove(cp, (void *)(SCREENMEM+offset), n);
		return n;
	}
	error(Eperm);
	return 0;
}

long
configwrite(Chan *c, void *buf, long n, ulong offset)
{
	char cbuf[20], *cp;
	int port, maxx, maxy;

	switch(c->qid.path&~CHDIR){
	case Qdir:
		error(Eperm);
	case Qvgamonitor:
		error(Eperm);
	case Qvgatype:
		error(Eperm);
	case Qvgasize:
		if(offset != 0)
			error(Ebadarg);
		if(n >= sizeof(cbuf))
			n = sizeof(cbuf) - 1;
		memmove(cbuf, buf, n);
		cbuf[n] = 0;
		cp = cbuf;
		maxx = strtoul(cp, &cp, 0);
		maxy = strtoul(cp, &cp, 0);
		if (maxx == 0 || maxy == 0 ||
		    maxx > 1280 || maxy > 1024)
			error(Ebadarg);
		setscreen(maxx, maxy, 1);
		return n;
	case Qvgaport:
		cp = buf;
		if (offset + n >= 0x8000)
			error(Ebadarg);
		for (port=offset; port<offset+n; port++) {
			outb(port, *cp++);
		}
		return n;
	case Qvgamem:
		if (offset + n > 0x10000)
			error(Ebadarg);
		memmove((void *)(SCREENMEM+offset), buf, n);
		return n;
	case Qmouse:
		if(n >= sizeof(cbuf))
			n = sizeof(cbuf) - 1;
		memmove(cbuf, buf, n);
		cbuf[n] = 0;
		if(strncmp("accelerated", cbuf, 11) == 0)
			mouseaccelerate(1);
		else if(strncmp("linear", cbuf, 6) == 0)
			mouseaccelerate(0);
		return n;
	}
	error(Eperm);
	return 0;
}

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

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

M pc/fns.h => pc/fns.h +1 -0
@@ 37,6 37,7 @@ void	ksetpcinfo(void);
void	mathinit(void);
void	mmuinit(void);
int	modem(int);
void	mouseaccelerate(int);
void	outb(int, int);
void	outss(int, void*, int);
void	pmubuzz(int, int);

M pc/kbd.c => pc/kbd.c +18 -1
@@ 214,7 214,7 @@ kbdinit(void)
			print("can't initialize mouse\n");

		/* turn on mouse acceleration */
		mousecmd(0xE7);
		mouseaccelerate(0);
		break;
	case At:
		/* enable kbd xfers and interrupts */


@@ 230,6 230,23 @@ kbdinit(void)
}

/*
 *  turn mouse acceleration on/off
 */
void
mouseaccelerate(int on)
{

	switch(machtype){
	case Attnsx:
		if(on)
			mousecmd(0xE7);
		else
			mousecmd(0xE6);
		break;
	}
}

/*
 *  mouse message is three bytes
 *
 *	byte 0 -	0 0 SDY SDX 1 M R L

M port/chan.c => port/chan.c +8 -4
@@ 306,12 306,13 @@ undomount(Chan *c)
	he = &pg->mnthash[MNTHASH];
	for(h = pg->mnthash; h < he; h++) {
		for(f = *h; f; f = f->hash) {
			for(t = f->mount; t; t = t->next)
			for(t = f->mount; t; t = t->next) {
				if(eqchan(c, t->to, 1)) {
					close(c);
					c = clone(t->head->from, 0);
					break;
				}
			}
		}
	}
	poperror();


@@ 452,13 453,15 @@ namec(char *name, int amode, int omode, ulong perm)
	elem = u->elem;
	mntok = 1;
	isdot = 0;
	if(name[0] == '/'){
	if(name[0] == '/') {
		c = clone(u->slash, 0);
		/*
		 * Skip leading slashes.
		 */
		name = skipslash(name);
	}else if(name[0] == '#'){
	}
	else
	if(name[0] == '#') {
		mntok = 0;
		if(name[1]=='M')
			error(Enonexist);


@@ 472,7 475,8 @@ namec(char *name, int amode, int omode, ulong perm)
		}else
			name = nextelem(name, elem);
		c = (*devtab[t].attach)(elem);
	}else{
	}
	else {
		c = clone(u->dot, 0);
		name = skipslash(name);	/* eat leading ./ */
		if(*name == 0)

M port/devcons.c => port/devcons.c +8 -13
@@ 188,15 188,13 @@ 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->wrl);
	if(waserror()){
		qunlock(&c->wrl);
		return 0;
	}

	(*devtab[c->type].write)(c, buf, n, c->offset);

	lock(c);
	c->offset += n;
	qunlock(&c->wrl);
	poperror();
	unlock(c);

	return n;
}



@@ 887,8 885,9 @@ conswrite(Chan *c, void *va, long n, ulong offset)
			error(Egreg);
		memmove(buf, va, n);	/* so we can NUL-terminate */
		buf[n] = 0;
		/* start a pager if not already started */
		if(strncmp(buf, "start", 5) == 0){
			kickpager();		/* start a pager if not already started */
			kickpager();
			break;
		}
		if(cpuserver && strcmp(u->p->user, eve) != 0)


@@ 896,7 895,7 @@ conswrite(Chan *c, void *va, long n, ulong offset)
		if(buf[0]<'0' || '9'<buf[0])
			error(Ebadarg);
		fd = strtoul(buf, 0, 0);
		swc = fdtochan(fd, -1, 1);
		swc = fdtochan(fd, -1, 1, 0);
		setswapchan(swc);
		break;



@@ 932,10 931,6 @@ conswstat(Chan *c, char *dp)
	error(Eperm);
}

/*
 *  Rand is huge and not worth it here.  Be small.
 *  Borrowed from the white book.
 */
int
nrand(int n)
{

M port/devdup.c => port/devdup.c +1 -1
@@ 74,7 74,7 @@ dupopen(Chan *c, int omode)
		c->offset = 0;
		return c;
	}
	fdtochan(c->qid.path, openmode(omode), 0);	/* error check only */
	fdtochan(c->qid.path, openmode(omode), 0, 0);	/* error check only */
	f = u->p->fgrp->fd[c->qid.path];
	close(c);
	incref(f);

M port/devmnt.c => port/devmnt.c +22 -49
@@ 48,23 48,23 @@ struct Mntalloc
#define MAXRPC		(MAXFDATA+MAXMSG)
#define limit(n, max)	(n > max ? max : n)

Chan 	*mattach(Mnt*, char*, char*);
Mntrpc	*mntralloc(void);
void	mntfree(Mntrpc*);
int	rpcattn(Mntrpc*);
void	mountrpc(Mnt*, Mntrpc*);
void	mountio(Mnt*, Mntrpc*);
Mnt	*mntchk(Chan*);
void	mountmux(Mnt*, Mntrpc*);
long	mntrdwr(int , Chan*, void*,long , ulong);
int	mntflush(Mnt*, Mntrpc*);
void	mntqrm(Mnt*, Mntrpc*);
Chan*	mattach(Mnt*, char*, char*);
void	mntauth(Mnt *, Mntrpc *, char *, ushort);
Mnt*	mntchk(Chan*);
void	mntdirfix(uchar*, Chan*);
void	mntgate(Mnt*);
void	mntrpcread(Mnt*, Mntrpc*);
void	mntdoclunk(Mnt *, Mntrpc *);
void	mntauth(Mnt *, Mntrpc *, char *, ushort);
int	mntflush(Mnt*, Mntrpc*);
void	mntfree(Mntrpc*);
void	mntgate(Mnt*);
void	mntpntfree(Mnt*);
void	mntqrm(Mnt*, Mntrpc*);
Mntrpc*	mntralloc(void);
long	mntrdwr(int , Chan*, void*,long , ulong);
void	mntrpcread(Mnt*, Mntrpc*);
void	mountio(Mnt*, Mntrpc*);
void	mountmux(Mnt*, Mntrpc*);
void	mountrpc(Mnt*, Mntrpc*);
int	rpcattn(Mntrpc*);

enum
{


@@ 203,9 203,9 @@ mattach(Mnt *m, char *spec, char *serv)
void
mntauth(Mnt *m, Mntrpc *f, char *serv, ushort fid)
{
	int i;
	Mntrpc *r;
	uchar chal[AUTHLEN];
	int i;

	r = mntralloc();
	if(waserror()) {


@@ 493,8 493,8 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
{
	Mnt *m;
	Mntrpc *r;
	ulong cnt, nr;
	char *uba;
	ulong cnt, nr;

	m = mntchk(c);
	uba = buf;


@@ 561,23 561,12 @@ mountio(Mnt *m, Mntrpc *r)
	/* Transmit a file system rpc */
	n = convS2M(&r->request, r->rpc);
	if(waserror()) {
		if(!m->mux)
			qunlock(&m->c->wrl);
		if(mntflush(m, r) == 0)
			nexterror();
	}
	else {

		if(m->mux) {
			if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n)
				error(Emountrpc);
		}
		else {
			qlock(&m->c->wrl);
			if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n)
				error(Emountrpc);
			qunlock(&m->c->wrl);
		}
		if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n)
			error(Emountrpc);
		poperror();
	}
	if(m->mux) {


@@ 618,8 607,6 @@ mntrpcread(Mnt *m, Mntrpc *r)

	for(;;) {
		if(waserror()) {
			if(!m->mux)
				qunlock(&m->c->rdl);
			if(mntflush(m, r) == 0) {
				if(m->mux == 0)
					mntgate(m);


@@ 629,13 616,7 @@ mntrpcread(Mnt *m, Mntrpc *r)
		}
		r->reply.type = 0;
		r->reply.tag = 0;
		if(m->mux) 
			n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0);
		else {
			qlock(&m->c->rdl);
			n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0);
			qunlock(&m->c->rdl);
		}
		n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0);
		poperror();
		if(n == 0)
			continue;


@@ 669,8 650,8 @@ mntgate(Mnt *m)
void
mountmux(Mnt *m, Mntrpc *r)
{
	Mntrpc **l, *q;
	char *dp;
	Mntrpc **l, *q;

	lock(m);
	l = &m->queue;


@@ 698,8 679,8 @@ mountmux(Mnt *m, Mntrpc *r)
int
mntflush(Mnt *m, Mntrpc *r)
{
	Fcall flush;
	int n;
	Fcall flush;

	lock(m);
	r->flushtag = m->flushtag++;


@@ 714,20 695,12 @@ mntflush(Mnt *m, Mntrpc *r)
	n = convS2M(&flush, r->flush);

	if(waserror()) {
		if(!m->mux)
			qunlock(&m->c->wrl);
		if(strcmp(u->error, Eintr) == 0)
			return 1;
		mntqrm(m, r);
		return 0;
	}
	if(m->mux)
		(*devtab[m->c->type].write)(m->c, r->flush, n, 0);
	else {
		qlock(&m->c->wrl);
		(*devtab[m->c->type].write)(m->c, r->flush, n, 0);
		qunlock(&m->c->wrl);
	}
	(*devtab[m->c->type].write)(m->c, r->flush, n, 0);
	poperror();
	return 1;
}

M port/devmux.c => port/devmux.c +1 -1
@@ 465,7 465,7 @@ muxwrite(Chan *c, void *va, long n, ulong offset)
		memmove(buf, va, n);		/* so we can NUL-terminate */
		buf[n] = 0;
		fd = strtoul(buf, 0, 0);
		fdtochan(fd, -1, 0);		/* error check */
		fdtochan(fd, -1, 0, 0);		/* error check */
		m->c = u->p->fgrp->fd[fd];
		incref(m->c);
		return n;

M port/devscsi.c => port/devscsi.c +48 -0
@@ 326,6 326,7 @@ scsicmd(int dev, int cmdbyte, Scsibuf *b, long size)
		cmd->cmdblk[2] = 1;
		/* fall through */
	case ScsiExtsens:
	case ScsiInquiry:
		cmd->cmdblk[4] = size;
		break;
	case ScsiGetcap:


@@ 407,6 408,30 @@ scsicap(int dev, void *p)
}

int
scsiinquiry(int dev, void *p, int size)
{
	Scsi *cmd;
	int status;

	cmd = scsicmd(dev, ScsiInquiry, scsibuf(), size);
	if(waserror()){
		scsifree(cmd->b);
		qunlock(cmd);
		nexterror();
	}
	status = scsiexec(cmd, ScsiIn);
	memmove(p, cmd->data.base, size);
	poperror();
	scsifree(cmd->b);
	qunlock(cmd);
	if((status&0xff00) != 0x6000)
		error(Eio);
	if(status & 0xFF)
		scsisense(dev, p);
	return status&0xff;
}

int
scsiwp(int dev)
{
	Scsi *cmd;


@@ 429,6 454,29 @@ scsiwp(int dev)
}

int
scsimodesense(int dev, int page, void *p, int size)
{
	Scsi *cmd;
	int status;

	cmd = scsicmd(dev, ScsiModesense, scsibuf(), size);
	cmd->cmdblk[2] = page;
	if(waserror()){
		scsifree(cmd->b);
		qunlock(cmd);
		nexterror();
	}
	status = scsiexec(cmd, ScsiIn);
	memmove(p, cmd->data.base, size);
	poperror();
	scsifree(cmd->b);
	qunlock(cmd);
	if ((status&0xffff) != 0x6000)
		error(Eio);
	return status&0xff;
}

int
scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno)
{
	Scsi *cmd;

M port/devsrv.c => port/devsrv.c +1 -12
@@ 207,7 207,6 @@ long
srvwrite(Chan *c, void *va, long n, ulong offset)
{
	Srv *sp;
	Fgrp *f;
	Chan *c1;
	int fd;
	char buf[32];


@@ 219,17 218,7 @@ srvwrite(Chan *c, void *va, long n, ulong offset)
	buf[n] = 0;
	fd = strtoul(buf, 0, 0);

	f = u->p->fgrp;
	lock(f);
	if(waserror()){
		unlock(f);
		nexterror();
	}
	fdtochan(fd, -1, 0);	/* error check only */
	c1 = f->fd[fd];
	incref(c1);
	unlock(f);
	poperror();
	c1 = fdtochan(fd, -1, 0, 1);	/* error check only */

	qlock(&srvlk);
	if(waserror()) {

M port/devwren.c => port/devwren.c +4 -1
@@ 261,7 261,7 @@ wrenpart(int dev)
{
	Drive *dp;
	Partition *pp;
	uchar buf[32];
	uchar buf[128];
	Scsibuf *b;
	char *rawpart, *line[Npart+1], *field[3];
	ulong n;


@@ 294,6 294,9 @@ wrenpart(int dev)
	pp->start = dp->p[0].end - 1;
	pp->end = dp->p[0].end;

	scsiinquiry(dev, buf, sizeof buf);
	if(memcmp(&buf[8], "INSITE  I325VM        *F", 24) == 0)
		scsimodesense(dev, 0x2e, buf, 0x2a);
	/*
	 *  read partition table from disk, null terminate
	 */

M port/fault.c => port/fault.c +0 -6
@@ 185,11 185,9 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
	
	if(loadrec == 0) {			/* This is demand load */
		c = s->image->c;
		qlock(&c->rdl);
		while(waserror()) {
			if(strcmp(u->error, Eintr) == 0)
				continue;
			qunlock(&c->rdl);
			kunmap(k);
			putpage(new);
			faulterror("sys: demand load I/O error");


@@ 207,7 205,6 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)

		poperror();
		kunmap(k);
		qunlock(&c->rdl);
		qlock(&s->lk);
		if(*p == 0) { 			/* Someone may have got there first */
			new->daddr = daddr;


@@ 219,10 216,8 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
	}
	else {					/* This is paged out */
		c = swapimage.c;
		qlock(&c->rdl);

		if(waserror()) {
			qunlock(&c->rdl);
			kunmap(k);
			putpage(new);
			qlock(&s->lk);


@@ 236,7 231,6 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)

		poperror();
		kunmap(k);
		qunlock(&c->rdl);
		qlock(&s->lk);

		if(pagedout(*p)) {

M port/portdat.h => port/portdat.h +1 -3
@@ 149,9 149,6 @@ enum

struct Chan
{
	QLock	rdl;			/* read access */
	QLock	wrl;			/* write access */
	Lock	offl;			/* offset access */
	Ref;
	union{
		Chan	*next;		/* allocation */


@@ 231,6 228,7 @@ enum
{
	ScsiTestunit	= 0x00,
	ScsiExtsens	= 0x03,
	ScsiInquiry	= 0x12,
	ScsiModesense	= 0x1a,
	ScsiGetcap	= 0x25,
	ScsiRead	= 0x08,

M port/portfns.h => port/portfns.h +3 -1
@@ 60,7 60,7 @@ void		exit(int);
Block*		expandb(Block*, int);
int		fault(ulong, int);
void		fdclose(int, int);
Chan*		fdtochan(int, int, int);
Chan*		fdtochan(int, int, int, int);
int		fixfault(Segment*, ulong, int, int);
void		flowctl(Queue*, Block*);
void		flushmmu(void);


@@ 205,6 205,8 @@ int		scsicap(int, void*);
Scsi*		scsicmd(int, int, Scsibuf*, long);
int		scsiexec(Scsi*, int);
void		scsifree(Scsibuf*);
int		scsiinquiry(int, void*, int);
int		scsimodesense(int, int, void*, int);
int		scsiready(int);
int		scsisense(int, void*);
int		scsiwp(int);

M port/stsplice.c => port/stsplice.c +1 -1
@@ 61,7 61,7 @@ spliceoput(Queue *q, Block *bp)
	freeb(bp);
	if(RD(q)->ptr)
		error("stream already spliced");
	c = fdtochan(fd, ORDWR, 0);
	c = fdtochan(fd, ORDWR, 0, 0);
	s = c->stream;
	if(s == 0)
		error("splice attempt on non-stream");

M port/swap.c => port/swap.c +0 -3
@@ 292,7 292,6 @@ executeio(void)

		k = kmap(out);
		kaddr = (char*)VA(k);
		qlock(&c->wrl);

		if(waserror())
			panic("executeio: page out I/O error");


@@ 301,7 300,6 @@ executeio(void)
		if(n != BY2PG)
			nexterror();

		qunlock(&c->wrl);
		kunmap(k);
		poperror();



@@ 332,4 330,3 @@ setswapchan(Chan *c)
	incref(c);
	swapimage.c = c;
}


M port/sysfile.c => port/sysfile.c +98 -40
@@ 30,21 30,44 @@ newfd(Chan *c)
}

Chan*
fdtochan(int fd, int mode, int chkmnt)
fdtochan(int fd, int mode, int chkmnt, int iref)
{
	Chan *c;
	Fgrp *f;

	c = 0;
	if(fd<0 || NFD<=fd || (c = u->p->fgrp->fd[fd])==0)
	f = u->p->fgrp;

	lock(f);
	if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) {
		unlock(f);
		error(Ebadfd);
	if(chkmnt && (c->flag&CMSG))
	}
	if(iref)
		incref(c);
	unlock(f);

	if(chkmnt && (c->flag&CMSG)) {
		if(iref)
			close(c);
		error(Ebadusefd);
	}

	if(mode<0 || c->mode==ORDWR)
		return c;
	if((mode&OTRUNC) && c->mode==OREAD)

	if((mode&OTRUNC) && c->mode==OREAD) {
		if(iref)
			close(c);
		error(Ebadusefd);
	if((mode&~OTRUNC) != c->mode)
	}

	if((mode&~OTRUNC) != c->mode) {
		if(iref)
			close(c);
		error(Ebadusefd);
	}

	return c;
}



@@ 109,16 132,17 @@ sysdup(ulong *arg)
	/*
	 * Close after dup'ing, so date > #d/1 works
	 */
	c = fdtochan(arg[0], -1, 0);
	c = fdtochan(arg[0], -1, 0, 1);
	fd = arg[1];
	if(fd != -1){
		if(fd<0 || NFD<=fd)
		if(fd<0 || NFD<=fd) {
			close(c);
			error(Ebadfd);

		}
		lock(f);
		if(fd > f->maxfd)
			f->maxfd = fd;
		incref(c);

		oc = f->fd[fd];
		f->fd[fd] = c;
		unlock(f);


@@ 129,7 153,6 @@ sysdup(ulong *arg)
			close(c);
			nexterror();
		}
		incref(c);
		fd = newfd(c);
		poperror();
	}


@@ 188,7 211,7 @@ fdclose(int fd, int flag)
long
sysclose(ulong *arg)
{
	fdtochan(arg[0], -1, 0);
	fdtochan(arg[0], -1, 0, 0);
	fdclose(arg[0], 0);

	return 0;


@@ 252,32 275,38 @@ unionread(Chan *c, void *va, long n)
long
sysread(ulong *arg)
{
	Chan *c;
	int dir;
	long n;
	Chan *c;

	c = fdtochan(arg[0], OREAD, 1);
	validaddr(arg[1], arg[2], 1);
	qlock(&c->rdl);

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

	n = arg[2];
	if(c->qid.path & CHDIR){
	dir = c->qid.path&CHDIR;

	if(dir) {
		n -= n%DIRLEN;
		if(c->offset%DIRLEN || n==0)
			error(Etoosmall);
	}
	if((c->qid.path&CHDIR) && c->mnt)

	if(dir && c->mnt)
		n = unionread(c, (void*)arg[1], n);
	else
		n = (*devtab[c->type].read)(c, (void*)arg[1], n, c->offset);
	qunlock(&c->rdl);
	poperror();
	lock(&c->offl);

	lock(c);
	c->offset += n;
	unlock(&c->offl);
	unlock(c);

	poperror();
	close(c);

	return n;
}



@@ 287,22 316,25 @@ syswrite(ulong *arg)
	Chan *c;
	long n;

	c = fdtochan(arg[0], OWRITE, 1);
	validaddr(arg[1], arg[2], 0);
	qlock(&c->wrl);

	if(waserror()){
		qunlock(&c->wrl);
	c = fdtochan(arg[0], OWRITE, 1, 1);
	if(waserror()) {
		close(c);
		nexterror();
	}

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

	n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2], c->offset);
	qunlock(&c->wrl);
	poperror();
	lock(&c->offl);

	lock(c);
	c->offset += n;
	unlock(&c->offl);
	unlock(c);

	poperror();
	close(c);

	return n;
}



@@ 314,11 346,13 @@ sysseek(ulong *arg)
	Dir dir;
	long off;

	c = fdtochan(arg[0], -1, 1);
	c = fdtochan(arg[0], -1, 1, 0);
	if(c->qid.path & CHDIR)
		error(Eisdir);

	if(devchar[c->type] == '|')
		error(Eisstream);

	off = 0;
	switch(arg[2]){
	case 0:


@@ 326,10 360,10 @@ sysseek(ulong *arg)
		break;

	case 1:
		lock(&c->offl);	/* lock for read/write update */
		lock(c);	/* lock for read/write update */
		c->offset += (long)arg[1];
		off = c->offset;
		unlock(&c->offl);
		unlock(c);
		break;

	case 2:


@@ 349,8 383,14 @@ sysfstat(ulong *arg)

	validaddr(arg[1], DIRLEN, 1);
	evenaddr(arg[1]);
	c = fdtochan(arg[0], -1, 0);
	c = fdtochan(arg[0], -1, 0, 1);
	if(waserror()) {
		close(c);
		nexterror();
	}
	(*devtab[c->type].stat)(c, (char*)arg[1]);
	poperror();
	close(c);
	return 0;
}



@@ 388,7 428,7 @@ syschdir(ulong *arg)
long
bindmount(ulong *arg, int ismount)
{
	Chan *c0, *c1;
	Chan *c0, *c1, *bc;
	ulong flag;
	long ret;
	int fd;


@@ 403,18 443,30 @@ bindmount(ulong *arg, int ismount)
	if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER))
		error(Ebadarg);
	if(ismount){
		bogus.chan = fdtochan(fd, 2, 0);
		bc = fdtochan(fd, 2, 0, 1);
		if(waserror()) {
			close(bc);
			nexterror();
		}
		bogus.chan = bc;

		validaddr(arg[3], 1, 0);
		if(vmemchr((char*)arg[3], '\0', NAMELEN) == 0)
			error(Ebadarg);

		bogus.spec = (char*)arg[3];
		validaddr(arg[4], 1, 0);
		if(vmemchr((char*)arg[4], '\0', NAMELEN) == 0)
			error(Ebadarg);

		bogus.serv = (char*)arg[4];
		ret = devno('M', 0);
		c0 = (*devtab[ret].attach)((char*)&bogus);
	}else{

		poperror();
		close(bc);
	}
	else {
		validaddr(arg[0], 1, 0);
		c0 = namec((char*)arg[0], Aaccess, 0, 0);
	}


@@ 556,7 608,13 @@ sysfwstat(ulong *arg)

	validaddr(arg[1], DIRLEN, 0);
	nameok((char*)arg[1]);
	c = fdtochan(arg[0], -1, 1);
	c = fdtochan(arg[0], -1, 1, 1);
	if(waserror()) {
		close(c);
		nexterror();
	}
	(*devtab[c->type].wstat)(c, (char*)arg[1]);
	poperror();
	close(c);
	return 0;
}

D ss/div.c => ss/div.c +0 -134
@@ 1,134 0,0 @@
#include <u.h>

#define	W	32

ulong
_udiv(ulong dividend, ulong divisor)
{
	long R;		/* partial remainder */
	ulong Q;	/* partial quotient */
	int iter;
	ulong logQ, m;

	m = (1<<(W-1))+1;
	if(dividend < m)
		m = dividend;
	for(logQ=0; logQ<W; logQ++)
		if((divisor<<logQ) >= m)
			break;

	R = dividend;
	Q = 0;
	for(iter=logQ; iter>=0; iter--){
		if(R >= 0){
			R -= divisor<<iter;
			Q += 1<<iter;
		}else{
			R += divisor<<iter;
			Q -= 1<<iter;
		}
	}
	if(R < 0)
		Q--;
	return Q;
}

ulong
_urem(ulong dividend, ulong divisor)
{
	long R;		/* partial remainder */
	int iter;
	ulong logQ, m;

	m = (1<<(W-1))+1;
	if(dividend < m)
		m = dividend;
	for(logQ=0; logQ<W; logQ++)
		if((divisor<<logQ) >= m)
			break;

	R = dividend;
	for(iter=logQ; iter>=0; iter--){
		if(R >= 0)
			R -= divisor<<iter;
		else
			R += divisor<<iter;
	}
	if(R < 0)
		R += divisor;
	return R;
}

ulong
_div(long dividend, long divisor)
{
	if(dividend>=0 && divisor>=0)
		return _udiv(dividend, divisor);
	if(dividend<0 && divisor<0)
		return _udiv(-dividend, -divisor);
	if(dividend < 0)
		return -_udiv(-dividend, divisor);
	return -_udiv(dividend, -divisor);
}

ulong
_rem(long dividend, long divisor)
{
	if(dividend>=0 && divisor>=0)
		return _urem(dividend, divisor);
	if(dividend<0 && divisor<0)
		return _urem(-dividend, -divisor);
	if(dividend < 0)
		return -_urem(-dividend, divisor);
	return -_urem(dividend, -divisor);
}

long
_asmul(long *a, long b)
{
	long c;

	c = *a * b;
	*a = c;
	return c;
}

long
_asdiv(long *a, long b)
{
	long c;

	c = *a / b;
	*a = c;
	return c;
}

long
_asrem(long *a, long b)
{
	long c;

	c = *a % b;
	*a = c;
	return c;
}

ulong
_asudiv(ulong *a, ulong b)
{
	ulong c;

	c = *a / b;
	*a = c;
	return c;
}

ulong
_asurem(ulong *a, ulong b)
{
	ulong c;

	c = *a % b;
	*a = c;
	return c;
}