~kris/9p

9hist

06450e3278aa79b6ab74586f212a64b3efedea89 — David du Colombier 35 years ago 5d85856
Plan 9 from Bell Labs 1991-04-23
M gnot/dat.h => gnot/dat.h +2 -1
@@ 628,8 628,9 @@ struct Scsidata
struct Scsi
{
	QLock;
	ulong	pid;
	ushort	target, lun;
	ushort	state;
	ushort	rflag;
	ushort	status;
	Scsidata cmd;
	Scsidata data;

M gnot/devcons.c => gnot/devcons.c +35 -11
@@ 69,9 69,10 @@ struct Rs232{
	int	kstarted;	/* true if kproc started */
	Queue	*wq;
	Alarm	*a;		/* alarm for waking the rs232 kernel process */
	int	started;
	int	started;	/* true if output interrupt pending */
	int	delay;		/* time between character input and waking kproc */
	Rendez	r;
	Rendez	rempty;
};

Rs232 rs232;


@@ 108,6 109,7 @@ printinit(void)
	lineq.out = lineq.buf;
	rs232.in.in = rs232.in.buf;
	rs232.in.out = rs232.in.buf;
	rs232.delay = 64;	/* msec */
	qlock(&kbdq);		/* allocate qlock */
	qunlock(&kbdq);
	lock(&lineq);		/* allocate lock */


@@ 293,6 295,7 @@ echo(int c)
{
	char ch;
	static int ctrlt;
	extern void DEBUG(void), dumpqueues(void), mntdump(void);

	/*
	 * ^t hack BUG


@@ 337,6 340,7 @@ echo(int c)
 * Put character into read queue at interrupt time.
 * Always called splhi from proc 0.
 */

void
kbdchar(int c)
{


@@ 699,7 703,7 @@ consread(Chan *c, void *buf, long n, ulong offset)
		return i;

	default:
		panic("consread %lux\n", c->qid);
		panic("consread %lux\n", c->qid.path);
		return 0;
	}
}


@@ 820,6 824,12 @@ rs232output(Rs232 *r)
	}
	r->out.f = next;

	if(q==0){
		kprint("rs232output: null q\n");
		qunlock(&r->outlock);
		return;
	}

	/*
	 *  stage new blocks
	 *


@@ 831,8 841,13 @@ rs232output(Rs232 *r)
		if(bp == 0)
			break;
		if(bp->type == M_CTL){
			if(waserror()){
				freeb(bp);
				qunlock(&r->outlock);
				nexterror();
			}
			while(!rs232empty(r))
				sleep(&r->r, rs232empty, r);
				sleep(&r->rempty, rs232empty, r);
			l = strtoul((char *)(bp->rptr+1), 0, 0);
			switch(*bp->rptr){
			case 'B':


@@ 853,6 868,7 @@ rs232output(Rs232 *r)
					r->delay = l;
				break;
			}
			poperror();
			freeb(bp);
			break;
		}


@@ 864,12 880,8 @@ rs232output(Rs232 *r)
	 *  start output, the spl's sync with interrupt level
	 *  this wouldn't work on a multi-processor
	 */
	splhi();
	if(r->started == 0){
		r->started = 1;
	if(r->started == 0)
		duartstartrs232o();
	}
	spllo();
	qunlock(&r->outlock);
}



@@ 942,11 954,14 @@ rs232open(Queue *q, Stream *c)
	WR(q)->ptr = r;
	r->wq = WR(q);

	kprint("rs232open: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n",
		q, c->inuse, c->type, c->dev, c->id);
	if(r->kstarted == 0){
		r->in.in = r->in.out = r->in.buf;
		kproc("rs232", rs232kproc, r);
		r->kstarted = 1;
	}
	}else
		wakeup(&r->r);	/* pick up any input characters */
}

static void


@@ 954,7 969,14 @@ rs232close(Queue *q)
{
	Rs232 *r;

	kprint("rs232close: q=0x%ux\n", q);
	r = q->ptr;
	qlock(&r->outlock);
	while(!rs232empty(r))
		sleep(&r->rempty, rs232empty, r);
	qunlock(&r->outlock);
	kprint("rs232close: emptied\n");
	rs232output(r);	/* reclaim blocks written */
	qlock(r);
	r->wq = 0;
	qunlock(r);


@@ 994,7 1016,7 @@ rs232ichar(int c)
		screenputc('^');

	/*
	 *  pass upstream within 1/16 second
	 *  pass upstream within r->delay milliseconds
	 */
	if(r->a==0){
		if(r->delay == 0)


@@ 1005,7 1027,7 @@ rs232ichar(int c)
}

/*
 *  called by output interrupt.  runs splhi
 *  called by output interrupt.  runs spl5
 */
int
getrs232o(void)


@@ 1016,6 1038,7 @@ getrs232o(void)

	r = &rs232;
	if(r->out.r == r->out.w){
		wakeup(&r->rempty);
		r->started = 0;
		return -1;
	}


@@ 1026,5 1049,6 @@ getrs232o(void)
		if(r->out.r==r->out.w || NEXT(r->out.r)==r->out.w)
			wakeup(&r->r);
	}
	r->started = 1;
	return c;
}

M gnot/fns.h => gnot/fns.h +2 -3
@@ 21,7 21,6 @@ long	clrfpintr(void);
int	compactpte(Orig*, ulong);
void	confinit(void);
Env	*copyenv(Env*, int);
Chan	*createdir(Chan*);
int	decref(Ref*);
void	delay(int);
void	delete(List**, List*, List*);


@@ 162,7 161,7 @@ void	schedinit(void);
void	screeninit(void);
void	screenputc(int);
int	scsicap(int, uchar *);
void	scsicmd(Scsi *, int, int, uchar *, long);
Scsi	*scsicmd(int, int, long);
void	scsictrlintr(void);
void	scsidmaintr(void);
int	scsiexec(Scsi *, int);


@@ 182,6 181,7 @@ int	setlabel(Label*);
char	*skipslash(char*);
void	sleep(Rendez*, int(*)(void*), void*);
int	spl1(void);
int	splduart(void);
int	splhi(void);
int	spllo(void);
void	splx(int);


@@ 214,7 214,6 @@ void	validaddr(ulong, ulong, int);
void	*vmemchr(void*, int, int);
void	wakeme(Alarm*);
void	wakeup(Rendez*);
Chan	*walk(Chan*, char*, int);

#define	waserror()	(u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define	poperror()	u->nerrlab--

M gnot/l.s => gnot/l.s +30 -19
@@ 54,6 54,13 @@ TEXT	splhi(SB), $0
	MOVW	$(SUPER|SPL(7)), SR
	RTS

TEXT	splduart(SB), $0

	MOVL	$0, R0
	MOVW	SR, R0
	MOVW	$(SUPER|SPL(5)), SR
	RTS

TEXT	spllo(SB), $0

	MOVL	$0, R0


@@ 230,14 237,9 @@ TEXT	portintr(SB), $0		/* level 2 */
	MOVL	A0, ((8+8)*BY2WD)(A7)
	MOVL	A7, -(A7)
	BSR	devportintr(SB)
	ADDL	$4, A7
	MOVL	((8+8)*BY2WD)(A7), A0
	MOVL	A0, USP
	MOVEM	(A7), $0x7FFF
	ADDL	$((8+8+1)*BY2WD+BY2WD), A7
	RTE
	BRA	retintr

TEXT	dkintr(SB), $0			/* level 2 */
TEXT	dkintr(SB), $0			/* level 3 */

	MOVL	$DBMAGIC, -(A7)
	SUBL	$((8+8+1)*BY2WD), A7


@@ 247,12 249,7 @@ TEXT	dkintr(SB), $0			/* level 2 */
	MOVL	A0, ((8+8)*BY2WD)(A7)
	MOVL	A7, -(A7)
	BSR	inconintr(SB)
	ADDL	$4, A7
	MOVL	((8+8)*BY2WD)(A7), A0
	MOVL	A0, USP
	MOVEM	(A7), $0x77FFF
	ADDL	$((8+8+1)*BY2WD+BY2WD), A7
	RTE
	BRA	retintr

TEXT	mouseintr(SB), $0		/* level 4 */



@@ 280,12 277,7 @@ TEXT	uartintr(SB), $0		/* level 5 */
	MOVL	A0, ((8+8)*BY2WD)(A7)
	MOVL	A7, -(A7)
	BSR	duartintr(SB)
	ADDL	$4, A7
	MOVL	((8+8)*BY2WD)(A7), A0
	MOVL	A0, USP
	MOVEM	(A7), $0x7FFF
	ADDL	$((8+8+1)*BY2WD+BY2WD), A7
	RTE
	BRA	retintr

TEXT	syncintr(SB), $0		/* level 6 */



@@ 297,6 289,9 @@ TEXT	syncintr(SB), $0		/* level 6 */
	MOVL	A0, ((8+8)*BY2WD)(A7)
	MOVL	A7, -(A7)
	BSR	clock(SB)
	/* fall through */
retintr:
	BSR	mousetry(SB)
	ADDL	$4, A7
	MOVL	((8+8)*BY2WD)(A7), A0
	MOVL	A0, USP


@@ 304,6 299,22 @@ TEXT	syncintr(SB), $0		/* level 6 */
	ADDL	$((8+8+1)*BY2WD+BY2WD), A7
	RTE

GLOBL	duarttimer+0(SB),$4

TEXT	duartreadtimer+0(SB), $0
	MOVW	SR, R1		/* spl7() */
	MOVW	$0x2700, SR
	MOVL	$0x40100000, A0
	CLRL	R0
	TSTB	15(A0)		/* stop timer */
	MOVW	6(A0), R0	/* read hi,lo */
	TSTB	14(A0)		/* restart timer */
	NOTW	R0		/* timer counts down from 0xffff */
	ADDL	duarttimer(SB), R0
	MOVL	R0, duarttimer(SB)
	MOVW	R1, SR
	RTS

GLOBL	mousetab(SB), $128
DATA	mousetab+  0(SB)/4, -1		/* x down,        */
DATA	mousetab+  4(SB)/4,  1		/*         y up   */

M gnot/screen.c => gnot/screen.c +12 -5
@@ 227,10 227,9 @@ duartinputport(void)
void
duartbaud(int b)
{
	int x;
	int x = 0;
	Duart *duart = DUARTREG;

	x = 0;		/* set */
	switch(b){
	case 38400:
		x = BD38400;


@@ 333,8 332,15 @@ duartrs232intr(void)
void
duartstartrs232o(void)
{
	DUARTREG[1].cmnd = ENB_TX;
	duartrs232intr();
	int s;
	Duart *duart;

	duart = DUARTREG;
	s = splduart();
	duart[1].cmnd = ENB_TX;
	if(duart[1].sr_csr & (XMT_RDY|XMT_EMT))
		duartrs232intr();
	splx(s);
}

struct latin


@@ 542,13 548,14 @@ duartintr(Ureg *ur)
	/*
	 * Is it 2?
	 */
	if(cause & IM_RRDYB){		/* rs232 input */
	while(cause & IM_RRDYB){	/* rs232 input */
		status = duart[1].sr_csr;
		c = duart[1].data;
		if(status & (FRM_ERR|OVR_ERR|PAR_ERR))
			duart[1].cmnd = RESET_ERR;
		else
			rs232ichar(c);
		cause = duart->is_imr;
	}
	/*
	 * Is it 3?

M port/chan.c => port/chan.c +140 -124
@@ 11,6 11,18 @@ struct{
	Chan	*free;
}chanalloc;

/*
 *  used by namec, domount, and walk to point
 *  to the current mount entry during name resolution
 */
typedef struct Finger	Finger;
struct Finger {
	Chan	*c;		/* channel we're walking */
	int	needcl;		/* true if we need to clone c before using it */
	Mount	*mnt;		/* last mount point we ran traversed */
	ulong	mountid;	/* id of that mount point */
};

int
incref(Ref *r)
{


@@ 83,9 95,7 @@ loop:
		c->dev = 0;
		c->offset = 0;
		c->mnt = 0;
		c->stream = 0;
		c->aux = 0;
		c->mntindex = 0;
		c->mchan = 0;
		c->mqid = (Qid){0, 0};
		return c;


@@ 294,15 304,13 @@ clone(Chan *c, Chan *nc)
	return (*devtab[c->type].clone)(c, nc);
}

Chan*
domount(Chan *c)
void
domount(Finger *f)
{
	int i;
	ulong mntid;
	Mtab *mt;
	Mount *mnt;
	Pgrp *pg;
	Chan *nc, *mc;
	Chan *mc;

	pg = u->p->pgrp;
	/*


@@ 310,110 318,101 @@ domount(Chan *c)
	 */
	mt = pg->mtab;
	for(i=0; i<pg->nmtab; i++,mt++)
		if(mt->c && eqchan(mt->c, c, 1))
		if(mt->c && eqchan(mt->c, f->c, 1))
			goto Found;
	/*
	 * No; c is unaffected
	 */
	return c;
	return;

	/*
	 * Yes; move c through table
	 */
    Found:
	lock(pg);
	if(!eqchan(mt->c, c, 1)){	/* table changed underfoot */
	if(!eqchan(mt->c, f->c, 1)){	/* table changed underfoot */
		pprint("domount: changed underfoot?\n");
		unlock(pg);
		return c;
		return;
	}
	mnt = mt->mnt;
	mntid = mnt->mountid;
	mc = mnt->c;
	f->mnt = mt->mnt;
	f->mountid = f->mnt->mountid;
	mc = mt->mnt->c;
	incref(mc);
	unlock(pg);
	if(waserror()){
		close(mc);
		nexterror();
	}
	nc = clone(mc, 0);
	close(mc);
	poperror();
	close(c);
	nc->mnt = mnt;
	nc->mountid = mntid;
	return nc;
	close(f->c);
	f->c = mc;
	f->needcl = 1;
}

Chan*
walk(Chan *ac, char *name, int domnt)
int
walk(Finger *f, char *name, int domnt)
{
	Mount *mnt;
	int first = 1;
	Chan *c = ac;
	Chan *nc, *mc;
	Mount *mnt = f->mnt;
	ulong mountid = f->mountid;
	Chan *c = f->c;
	Chan *mc;
	Pgrp *pg = u->p->pgrp;

	/*
	 * name may be empty if the file name is "/", "#c" etc.
	 */
    Again:
	if(name[0] && (*devtab[c->type].walk)(c, name)==0){
		if(!(c->flag&CMOUNT))
			goto Notfound;
		mnt = c->mnt;
		if(mnt == 0)
			panic("walk");
		lock(pg);
		if(mnt->term){
			unlock(pg);
			goto Notfound;
		}
		if(c->mountid != mnt->mountid){
			pprint("walk: changed underfoot? '%s'\n", name);
	if(name[0]){
		for(;;){
			if(!first || f->needcl){
				mc = (*devtab[c->type].clwalk)(c, name);
				if(mc){
					close(c);
					c = mc;
					break;
				}
			} else {
				if((*devtab[c->type].walk)(c, name) != 0){
					break;
				}
			}
			if(!(c->flag&CMOUNT))
				goto Notfound;
			if(mnt == 0)
				panic("walk");	/* ??? is this safe ??? */
			lock(pg);
			if(mnt->term){
				unlock(pg);
				goto Notfound;
			}
			if(mountid != mnt->mountid){
				pprint("walk: changed underfoot? '%s'\n", name);
				unlock(pg);
				goto Notfound;
			}
			mnt = mnt->next;
			mountid = mnt->mountid;
			mc = mnt->c;
			incref(mc);
			unlock(pg);
			goto Notfound;
		}
		mnt = mnt->next;
		mc = mnt->c;
		incref(mc);
		unlock(pg);
		if(waserror()){
			close(mc);
			nexterror();
		}
		if(mnt == 0)
			panic("walk 1");
		nc = clone(mc, 0);
		close(mc);
		poperror();
		if(!first)
			close(c);
		nc->mnt = mnt;
		nc->mountid = mnt->mountid;
		c = nc;
		first = 0;
		goto Again;
	}

	if(name[0])			/* walk succeeded */
		c->flag &= ~CMOUNT;

	if(domnt){
		if(waserror()){
			if(!first)
				close(c);
			return 0;
			c = mc;
			first = 0;
		}
		c = domount(c);
		poperror();
	}

	if(!first)
		close(ac);
		/*
		 *  we get here only if we have a cloned and walked
		 *  channel
		 */
		if(!first)
			close(f->c);
		f->c = c;
		f->needcl = 0;
		f->mnt = 0;
		c->flag &= ~CMOUNT;
	}

	if(domnt)
		domount(f);

	return c;
	return 1;

    Notfound:
	if(!first)


@@ 422,22 421,22 @@ walk(Chan *ac, char *name, int domnt)
}

/*
 * c is a mounted non-creatable directory.  find a creatable one.
 * f->c is a mounted non-creatable directory.  find a creatable one.
 */
Chan*
createdir(Chan *c)
void
createdir(Finger *f)
{
	Mount *mnt;
	Pgrp *pg = u->p->pgrp;
	Chan *mc, *nc;
	Chan *mc;

	lock(pg);
	if(waserror()){
		unlock(pg);
		nexterror();
	}
	mnt = c->mnt;
	if(c->mountid != mnt->mountid){
	mnt = f->mnt;
	if(f->mountid != mnt->mountid){
		pprint("createdir: changed underfoot?\n");
		error(Enocreate);
	}


@@ 449,16 448,10 @@ createdir(Chan *c)
	mc = mnt->c;
	incref(mc);
	unlock(pg);
	if(waserror()){
		close(mc);
		nexterror();
	}
	nc = clone(mc, 0);
	poperror();
	close(c);
	close(mc);
	nc->mnt = mnt;
	return nc;
	close(f->c);
	f->needcl = 1;
	f->c = mc;
}

void


@@ 466,6 459,19 @@ saveregisters(void)
{
}

void
doclone(Finger *f)
{
	Chan *nc;

	if(f->needcl == 0)
		return;
	nc = clone(f->c, 0);
	close(f->c);
	f->c = nc;
	f->needcl = 0;
}

/*
 * Turn a name into a channel.
 * &name[0] is known to be a valid address.  It may be a kernel address.


@@ 473,11 479,11 @@ saveregisters(void)
Chan*
namec(char *name, int amode, int omode, ulong perm)
{
	Chan *c, *nc;
	int t;
	int mntok, isdot;
	char *p;
	char *elem;
	Finger f;

	if(name[0] == 0)
		error(Enonexist);


@@ 498,8 504,11 @@ namec(char *name, int amode, int omode, ulong perm)
	elem = u->elem;
	mntok = 1;
	isdot = 0;
	f.mnt = 0;
	if(name[0] == '/'){
		c = clone(u->slash, 0);
		f.c = u->slash;
		incref(f.c);
		f.needcl = 1;
		/*
		 * Skip leading slashes.
		 */


@@ 517,16 526,19 @@ namec(char *name, int amode, int omode, ulong perm)
			elem[0]=0;
		}else
			name = nextelem(name, elem);
		c = (*devtab[t].attach)(elem);
		f.c = (*devtab[t].attach)(elem);
		f.needcl = 0;
	}else{
		c = clone(u->dot, 0);
		f.c = u->dot;
		incref(f.c);
		f.needcl = 1;
		name = skipslash(name);	/* eat leading ./ */
		if(*name == 0)
			isdot = 1;
	}

	if(waserror()){
		close(c);
		close(f.c);
		nexterror();
	}



@@ 537,16 549,15 @@ namec(char *name, int amode, int omode, ulong perm)
	 *  current directory.
	 */
	if(mntok && !isdot && !(amode==Amount && elem[0]==0))
		c = domount(c);			/* see case Atodir below */
		domount(&f);		/* see case Atodir below */

	/*
	 * How to treat the last element of the name depends on the operation.
	 * Therefore do all but the last element by the easy algorithm.
	 */
	while(*name){
		if((nc=walk(c, elem, mntok)) == 0)
		if(walk(&f, elem, mntok) == 0)
			error(Enonexist);
		c = nc;
		name = nextelem(name, elem);
	}



@@ 556,11 567,10 @@ namec(char *name, int amode, int omode, ulong perm)
	switch(amode){
	case Aaccess:
		if(isdot)
			c = domount(c);
			domount(&f);
		else{
			if((nc=walk(c, elem, mntok)) == 0)
			if(walk(&f, elem, mntok) == 0)
				error(Enonexist);
			c = nc;
		}
		break;



@@ 569,26 579,26 @@ namec(char *name, int amode, int omode, ulong perm)
		 * Directories (e.g. for cd) are left before the mount point,
		 * so one may mount on / or . and see the effect.
		 */
		if((nc=walk(c, elem, 0)) == 0)
		if(walk(&f, elem, 0) == 0)
			error(Enonexist);
		c = nc;
		if(!(c->qid.path & CHDIR))
		if(!(f.c->qid.path & CHDIR))
			error(Enotdir);
		break;

	case Aopen:
		if(isdot)
			c = domount(c);
			domount(&f);
		else{
			if((nc=walk(c, elem, mntok)) == 0)
			if(walk(&f, elem, mntok) == 0)
				error(Enonexist);
			c = nc;
		}
	Open:
		saveregisters();	/* else error() in open has wrong value of c saved */
		c = (*devtab[c->type].open)(c, omode);
		saveregisters(); /* else error() in open has wrong value of c saved */
		if(f.needcl)
			doclone(&f);
		f.c = (*devtab[f.c->type].open)(f.c, omode);
		if(omode & OCEXEC)
			c->flag |= CCEXEC;
			f.c->flag |= CCEXEC;
		break;

	case Amount:


@@ 597,31 607,37 @@ namec(char *name, int amode, int omode, ulong perm)
		 * the second mount to be attached to the original directory, not
		 * the replacement.
		 */
		if((nc=walk(c, elem, 0)) == 0)
		if(walk(&f, elem, 0) == 0)
			error(Enonexist);
		c = nc;
		break;

	case Acreate:
		if(isdot)
			error(Eisdir);
		if((nc=walk(c, elem, 1)) != 0){
			c = nc;
		if(walk(&f, elem, 1) != 0){
			omode |= OTRUNC;
			goto Open;
		}
		if((c->flag&(CMOUNT|CCREATE)) == CMOUNT)
			c = createdir(c);
		(*devtab[c->type].create)(c, elem, omode, perm);
		if((f.c->flag&(CMOUNT|CCREATE)) == CMOUNT)
			createdir(&f);
		if(f.needcl)
			doclone(&f);
		(*devtab[f.c->type].create)(f.c, elem, omode, perm);
		if(omode & OCEXEC)
			c->flag |= CCEXEC;
			f.c->flag |= CCEXEC;
		break;

	default:
		panic("unknown namec access %d\n", amode);
	}
	if(f.needcl)
		doclone(&f);
	poperror();
	return c;
	if(f.c->flag & CMOUNT){
		f.c->mnt = f.mnt;
		f.c->mountid = f.mountid;
	}
	return f.c;
}

/*

M port/devbit.c => port/devbit.c +50 -19
@@ 6,6 6,7 @@
#include	"errno.h"

#include	"devtab.h"
#include	"ureg.h"

#include	<libg.h>
#include	<gnot.h>


@@ 45,6 46,7 @@ struct
#define	FREE	0x80000000
void	bitcompact(void);
void	bitfree(GBitmap*);
void	mouseupdate(int);
extern	GBitmap	gscreen;

struct{


@@ 54,6 56,7 @@ struct{
	int	dx;		/* interrupt-time delta */
	int	dy;
	int	track;		/* update cursor on screen */
	int	clock;		/* check mouse.track on RTE */
	Mouse;
	int	changed;	/* mouse structure changed since last read */
	int	newbuttons;	/* interrupt time access only */


@@ 526,6 529,8 @@ bitwrite(Chan *c, void *va, long n, ulong offset)
			rect.min.y = GLONG(p+6);
			rect.max.x = GLONG(p+10);
			rect.max.y = GLONG(p+14);
			if(Dx(rect) < 0 || Dy(rect) < 0)
				error(Ebadblt);
			if(rect.min.x >= 0)
				l = (rect.max.x+ws-1)/ws - rect.min.x/ws;
			else{	/* make positive before divide */


@@ 1129,26 1134,52 @@ mousebuttons(int b)	/* called spl5 */
void
mouseclock(void)	/* called spl6 */
{
	++mouse.clock;
}

void
mousetry(Ureg *ur)
{
	int s;

	if(mouse.clock && mouse.track && (ur->sr&SPL(7)) == 0 && canlock(&cursor)){
		s = spl1();
		mouseupdate(0);
		splx(s);
		unlock(&cursor);
		wakeup(&mouse.r);
	}
}

void
mouseupdate(int dolock)
{
	int x, y;
	if(mouse.track && canlock(&cursor)){
		x = mouse.xy.x + mouse.dx;
		if(x < gscreen.r.min.x)
			x = gscreen.r.min.x;
		if(x >= gscreen.r.max.x)
			x = gscreen.r.max.x;
		y = mouse.xy.y + mouse.dy;
		if(y < gscreen.r.min.y)
			y = gscreen.r.min.y;
		if(y >= gscreen.r.max.y)
			y = gscreen.r.max.y;
		cursoroff(0);
		mouse.xy = Pt(x, y);
		cursoron(0);
		mouse.dx = 0;
		mouse.dy = 0;
		mouse.track = 0;
		mouse.buttons = mouse.newbuttons;
		mouse.changed = 1;

	if(dolock && !canlock(&cursor))
		return;

	x = mouse.xy.x + mouse.dx;
	if(x < gscreen.r.min.x)
		x = gscreen.r.min.x;
	if(x >= gscreen.r.max.x)
		x = gscreen.r.max.x;
	y = mouse.xy.y + mouse.dy;
	if(y < gscreen.r.min.y)
		y = gscreen.r.min.y;
	if(y >= gscreen.r.max.y)
		y = gscreen.r.max.y;
	cursoroff(0);
	mouse.xy = Pt(x, y);
	cursoron(0);
	mouse.dx = 0;
	mouse.dy = 0;
	mouse.clock = 0;
	mouse.track = 0;
	mouse.buttons = mouse.newbuttons;
	mouse.changed = 1;

	if(dolock){
		unlock(&cursor);
		wakeup(&mouse.r);
	}

M port/devlance.c => port/devlance.c +7 -6
@@ 208,19 208,21 @@ void lancekproc(void *);
/*
 *  print a packet preceded by a message
 */
int
sprintpacket(char *buf, Trace *t)
{
	Dpkt *p = &t->p;
	int i;
	int i, n;

	sprint(buf, "%c: %.8ud %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)d(",
	n = sprint(buf, "%c: %.8ud %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)d(",
		t->tag, t->ticks, t->len,
		p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5],
		p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5],
		p->type[0], p->type[1]);
	for(i=0; i<sizeof(p->data); i++)
		sprint(buf+strlen(buf), "%.2ux", p->data[i]);
	sprint(buf+strlen(buf), ")\n");
		n += sprint(buf+n, "%.2ux", p->data[i]);
	n += sprint(buf+n, ")\n");
	return n;
}

/*


@@ 642,8 644,7 @@ lancetraceread(Chan *c, void *a, long n, ulong offset)
	int plen;

	rv = 0;
	sprintpacket(buf, l.dq.t);
	plen = strlen(buf);
	plen = sprintpacket(buf, l.dq.t);
	off = offset % plen;
	for(t = &l.dq.t[offset/plen]; n && t < &l.dq.t[Ndpkt]; t++){
		if(t->tag == 0)

M port/devmnt.c => port/devmnt.c +21 -9
@@ 199,6 199,8 @@ mntdev(Chan *c, int noerr)
		return m;
	if(noerr)
		return 0;
	print("mntdev shutdown %d %d %d %lux\n", c->dev, c->mntindex,
			m->mntid, m->q);
	error(Eshutdown);
}



@@ 395,24 397,34 @@ mntclwalk(Chan *c, char *name)
	Mnthdr *mh;
	Chan *nc;

	if(waserror()){	/* BUG: can check type of error? */
		freechan(nc);
		nc = 0;
		goto Out;
	}
	nc = newchan();
	nc->type = c->type;
	nc->dev = c->dev;
	nc->qid = c->qid;
	nc->mode = c->mode;
	nc->flag = c->flag;
	nc->offset = c->offset;
	nc->mnt = c->mnt;
	nc->aux = c->aux;
	nc->mchan = c->mchan;
	nc->mqid = c->qid;
	m = mntdev(c, 0);
	mh = mhalloc();
	mh->thdr.type = Tclwalk;
	mh->thdr.fid = c->fid;
	mh->thdr.newfid = nc->fid;
	strcpy(mh->thdr.name, name);
	if(waserror()){	/* BUG: can check type of error? */
		print("mntclwalk(%d %lux) failed\n", c->type, c->qid.path);
		freechan(nc);
		nc = 0;
		goto Out;
	}
	mntxmit(m, mh);
	nc->qid = mh->rhdr.qid;
	print("mntclwalk(%d %lux)->%d %lux\n", c->type, c->qid.path,
		nc->type, nc->qid.path);
	if(mh->rhdr.fid == mh->thdr.fid)
		errors("directory entry not found");
	poperror();
	nc->qid = mh->rhdr.qid;
	incref(m);
    Out:
	mhfree(mh);
	return nc;

M port/devscsi.c => port/devscsi.c +66 -34
@@ 24,7 24,8 @@ static Dirtab scsidir[]={
#define	NSCSI	(sizeof scsidir/sizeof(Dirtab))

static Scsi	staticcmd;	/* BUG */
static uchar	datablk[8192];	/* BUG */
#define	DATASIZE	(8*1024)
static uchar	datablk[DATASIZE];	/* BUG */

static int	debugs[8];
static int	isscsi;


@@ 120,7 121,18 @@ scsicreate(Chan *c, char *name, int omode, ulong perm)

void
scsiclose(Chan *c)
{}
{
	Scsi *cmd = &staticcmd;
	
	if((c->qid.path & CHDIR) || c->qid.path==1)
		return;
	if((c->qid.path & 0xf) == Qcmd){
		if(canqlock(cmd) || cmd->pid == u->p->pid){
			cmd->pid = 0;
			qunlock(cmd);
		}
	}
}

long
scsiread(Chan *c, char *a, long n, ulong offset)


@@ 132,6 144,7 @@ scsiread(Chan *c, char *a, long n, ulong offset)
		return devdirread(c, a, n, 0, 0, scsigen);
	if(c->qid.path==1){
		if(offset == 0){
			/*void scsidump(void); scsidump();*/
			*a = ownid;
			n = 1;
		}else


@@ 140,17 153,26 @@ scsiread(Chan *c, char *a, long n, ulong offset)
	case Qcmd:
		if (n < 4)
			error(Ebadarg);
		/*if(canqlock(cmd)){
		if(canqlock(cmd)){
			qunlock(cmd);
			error(Egreg);
		}*/
		}
		if(cmd->pid != u->p->pid)
			error(Egreg);
		n = 4;
		*a++ = cmd->state>>8; *a++ = cmd->state;
		*a++ = 0; *a++ = 0;
		*a++ = cmd->status>>8; *a = cmd->status;
		/*qunlock(cmd);*/
		cmd->pid = 0;
		qunlock(cmd);
		break;
	case Qdata:
		if (n > sizeof datablk)
		if(canqlock(cmd)){
			qunlock(cmd);
			error(Egreg);
		}
		if(cmd->pid != u->p->pid)
			error(Egreg);
		if (n > DATASIZE)
			error(Ebadarg);
		cmd->data.base = datablk;
		cmd->data.lim = cmd->data.base + n;


@@ 181,25 203,31 @@ scsiwrite(Chan *c, char *a, long n, ulong offset)
		if(offset == 0){
			n = 1;
			ownid=*a;
			scsiinit();
			scsireset();
		}else
			n = 0;
	}else switch ((int)c->qid.path & 0xf){
	case Qcmd:
		if (n < 6 || n > sizeof cmd->cmdblk)
			error(Ebadarg);
		/*qlock(cmd);*/
		qlock(cmd);
		cmd->pid = u->p->pid;
		cmd->cmd.base = cmd->cmdblk;
		memmove(cmd->cmd.base, a, n);
		cmd->cmd.lim = cmd->cmd.base + n;
		cmd->cmd.ptr = cmd->cmd.base;
		cmd->target = (c->qid.path>>4)&7;
		cmd->lun = (a[1]>>5)&7;
		cmd->state = 0;
		cmd->status = 0xFFFF;
		break;
	case Qdata:
		if (n > sizeof datablk)
		if(canqlock(cmd)){
			qunlock(cmd);
			error(Egreg);
		}
		if(cmd->pid != u->p->pid)
			error(Egreg);
		if (n > DATASIZE)
			error(Ebadarg);
		cmd->data.base = datablk;
		cmd->data.lim = cmd->data.base + n;


@@ 234,18 262,21 @@ scsiwstat(Chan *c, char *dp)
	error(Eperm);
}

void
scsicmd(Scsi *cmd, int dev, int cmdbyte, uchar *buf, long size)
Scsi *
scsicmd(int dev, int cmdbyte, long size)
{
	Scsi *cmd = &staticcmd;

	if(size > DATASIZE)
		panic("scsicmd %d", size);
	qlock(cmd);
	cmd->target = dev>>3;
	cmd->lun = dev&7;
	cmd->cmd.base = cmd->cmdblk;
	cmd->data.base = buf;
	cmd->cmd.ptr = cmd->cmd.base;
	memset(cmd->cmdblk, 0, sizeof cmd->cmdblk);
	cmd->cmdblk[0] = cmdbyte;
	switch (cmdbyte>>5) {
	switch(cmdbyte>>5){
	case 0:
		cmd->cmd.lim = &cmd->cmdblk[6]; break;
	case 1:


@@ 253,7 284,7 @@ scsicmd(Scsi *cmd, int dev, int cmdbyte, uchar *buf, long size)
	default:
		cmd->cmd.lim = &cmd->cmdblk[12]; break;
	}
	switch (cmdbyte) {
	switch(cmdbyte){
	case 0x00:	/* test unit ready */
		break;
	case 0x03:	/* read sense data */


@@ 262,49 293,49 @@ scsicmd(Scsi *cmd, int dev, int cmdbyte, uchar *buf, long size)
	case 0x25:	/* read capacity */
		break;
	}
	cmd->data.base = datablk;
	cmd->data.lim = cmd->data.base + size;
	cmd->data.ptr = cmd->data.base;
	cmd->save = cmd->data.base;
	return cmd;
}

int
scsiready(int dev)
{
	static Scsi cmd;
	Scsi *cmd = scsicmd(dev, 0x00, 0);
	int status;
	scsicmd(&cmd, dev, 0x00, 0, 0);
	status = scsiexec(&cmd, 0);
	qunlock(&cmd);

	status = scsiexec(cmd, 0);
	qunlock(cmd);
	if ((status&0xff00) != 0x6000)
		error(Eio);
	return status&0xff;
}

int
scsisense(int dev, uchar *p)
scsisense(int dev, void *p)
{
	static Scsi cmd;
	static uchar buf[18];
	Scsi *cmd = scsicmd(dev, 0x03, 18);
	int status;
	scsicmd(&cmd, dev, 0x03, buf, sizeof buf);
	status = scsiexec(&cmd, 1);
	memmove(p, buf, sizeof buf);
	qunlock(&cmd);

	status = scsiexec(cmd, 1);
	memmove(p, cmd->data.base, 18);
	qunlock(cmd);
	if ((status&0xff00) != 0x6000)
		error(Eio);
	return status&0xff;
}

int
scsicap(int dev, uchar *p)
scsicap(int dev, void *p)
{
	static Scsi cmd;
	static uchar buf[8];
	Scsi *cmd = scsicmd(dev, 0x25, 8);
	int status;
	scsicmd(&cmd, dev, 0x25, buf, sizeof buf);
	status = scsiexec(&cmd, 1);
	memmove(p, buf, sizeof buf);
	qunlock(&cmd);

	status = scsiexec(cmd, 1);
	memmove(p, cmd->data.base, 8);
	qunlock(cmd);
	if ((status&0xff00) != 0x6000)
		error(Eio);
	return status&0xff;


@@ 381,6 412,7 @@ scsiexec(Scsi *p, int rflag)
		nexterror();
	}
	scsirflag = rflag;
	p->rflag = rflag;
	datap = p->data.base;
	if ((ownid & 0x08) && rflag)
		PUT(Dest_id, 0x40|p->target);

M port/devwren.c => port/devwren.c +12 -35
@@ 37,8 37,7 @@ struct Disk

static Disk	wren[Ndisk];

static Scsi	staticcmd;		/* BUG */
static uchar	datablk[BY2PG];		/* BUG */
#define	DATASIZE	(8*1024)	/* BUG */

#define	BGLONG(p)	(((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3])



@@ 125,11 124,7 @@ wrenreset(void)

void
wreninit(void)
{
	Scsi *cmd = &staticcmd;
	cmd->cmd.base = cmd->cmdblk;
	cmd->data.base = datablk;
}
{}

/*
 *  param is #r<target>.<lun>


@@ 210,8 205,8 @@ wrenclose(Chan *c)
long
wrenread(Chan *c, char *a, long n, ulong offset)
{
	Scsi *cmd = &staticcmd;
	unsigned long lbn;
	Scsi *cmd;
	ulong lbn;
	Part *p;
	Disk *d;



@@ 230,26 225,17 @@ wrenread(Chan *c, char *a, long n, ulong offset)
		lbn = (offset/d->blocksize) + p->firstblock;
		if (lbn >= p->maxblock)
			error(Ebadarg);
		if (n > sizeof datablk)
			n = sizeof datablk;
		qlock(cmd);
		if (n > DATASIZE)
			n = DATASIZE;
		cmd = scsicmd(c->dev, 0x08, n);
		if (waserror()) {
			qunlock(cmd);
			nexterror();
		}
		cmd->target = c->dev>>3;
		cmd->lun = c->dev&7;
		cmd->cmd.ptr = cmd->cmd.base;
		cmd->cmdblk[0] = 0x08;
		cmd->cmdblk[1] = lbn>>16;
		cmd->cmdblk[2] = lbn>>8;
		cmd->cmdblk[3] = lbn;
		cmd->cmdblk[4] = n/d->blocksize;
		cmd->cmdblk[5] = 0x00;
		cmd->cmd.lim = &cmd->cmdblk[6];
		cmd->data.lim = cmd->data.base + n;
		cmd->data.ptr = cmd->data.base;
		cmd->save = cmd->data.base;
		scsiexec(cmd, 1);
		n = cmd->data.ptr - cmd->data.base;
		memmove(a, cmd->data.base, n);


@@ 273,8 259,8 @@ wrenread(Chan *c, char *a, long n, ulong offset)
long
wrenwrite(Chan *c, char *a, long n, ulong offset)
{
	Scsi *cmd = &staticcmd;
	unsigned long lbn;
	Scsi *cmd;
	ulong lbn;
	Part *p;
	Disk *d;



@@ 290,26 276,17 @@ wrenwrite(Chan *c, char *a, long n, ulong offset)
		lbn = offset/d->blocksize + p->firstblock;
		if (lbn >= p->maxblock)
			error(Ebadarg);
		if (n > sizeof datablk)
			n = sizeof datablk;
		qlock(cmd);
		if (n > DATASIZE)
			n = DATASIZE;
		cmd = scsicmd(c->dev, 0x0a, n);
		if (waserror()) {
			qunlock(cmd);
			nexterror();
		}
		cmd->target = c->dev>>3;
		cmd->lun = c->dev&7;
		cmd->cmd.ptr = cmd->cmd.base;
		cmd->cmdblk[0] = 0x0a;
		cmd->cmdblk[1] = lbn>>16;
		cmd->cmdblk[2] = lbn>>8;
		cmd->cmdblk[3] = lbn;
		cmd->cmdblk[4] = n/d->blocksize;
		cmd->cmdblk[5] = 0x00;
		cmd->cmd.lim = &cmd->cmdblk[6];
		cmd->data.lim = cmd->data.base + n;
		cmd->data.ptr = cmd->data.base;
		cmd->save = cmd->data.base;
		memmove(cmd->data.base, a, n);
		scsiexec(cmd, 0);
		n = cmd->data.ptr - cmd->data.base;

M port/stasync.c => port/stasync.c +11 -0
@@ 69,6 69,7 @@ Qinfo asyncinfo =
	asyncreset
};

static int	debugcount = 6;
int asyncdebug = 3;
int asyncerror;



@@ 280,6 281,10 @@ asyncoput(Queue *q, Block *bp)
		asputf(ap);
	ap->chan = chan;

	if(asyncdebug > 1)
		kprint("a%d->(%d)%3.3uo %d\n",
			ap-async, chan, ctl, bp->wptr-bp->rptr);

	/*
	 *  send the 8 bit data
	 */


@@ 321,6 326,8 @@ asyncoput(Queue *q, Block *bp)
			asputf(ap);
		}
	}
	if(debugcount > 0 && --debugcount == 0)
		asyncdebug = 1;

	qunlock(&ap->xmit);
	return;


@@ 432,9 439,13 @@ asynciput(Queue *q, Block *bp)
					showframe("in", ap, ap->buf, ap->icount);
				if(ap->icount < 5) {
					DPRINT("a%d pkt too short\n", ap-async);
					if(asyncdebug && asyncdebug<=2)
						showframe("shortin", ap, ap->buf, ap->icount);
					ap->tooshort++;
				} else if(ap->icrc != 0) {
					DPRINT("a%d bad crc\n", ap-async);
					if(asyncdebug && asyncdebug<=2)
						showframe("badin", ap, ap->buf, ap->icount);
					ap->badcrc++;
				} else {
					asdeliver(q, ap);