~kris/9p

9hist

a3fea5bbc7fdb6094887af032dda0266effedea2 — David du Colombier 33 years ago ead2873
Plan 9 from Bell Labs 1992-12-17
11 files changed, 200 insertions(+), 112 deletions(-)

M pc/devfloppy.c
M pc/devvga.c
M pc/kbd.c
M port/chan.c
M port/dev.c
M port/devmnt.c
M port/net.c
M port/portdat.h
M power/fns.h
M power/scsi.c
M power/trap.c
M pc/devfloppy.c => pc/devfloppy.c +56 -24
@@ 13,12 13,16 @@ typedef	struct Drive		Drive;
typedef	struct Controller	Controller;
typedef struct Type		Type;

#define DPRINT if(floppydebug)print
#define DPRINT if(floppydebug)kprint
int floppydebug;

/* bits in the registers */
enum
{
	/* status registers a & b */
	Psra=		0x3f0,
	Psrb=		0x3f1,

	/* digital output register */
	Pdor=		0x3f2,
	Fintena=	0x8,	/* enable floppy interrupt */


@@ 212,6 216,13 @@ Dirtab floppydir[]={
};
#define NFDIR	2	/* directory entries/drive */

static void
fldump(void)
{
	DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
		inb(Pdor), inb(Pmsr), inb(Pdir));
}

/*
 *  set floppy drive to its default type
 */


@@ 380,7 391,7 @@ islegal(ulong offset, long n, Drive *dp)
 *
 *  if the read fails, cycle through the possible floppy
 *  density till one works or we've cycled through all
 *  possibilities.
 *  possibilities for this drive.
 */
static void
changed(Chan *c, Drive *dp)


@@ 392,7 403,8 @@ changed(Chan *c, Drive *dp)
	 *  if floppy has changed or first time through
	 */
	if((inb(Pdir)&Fchange) || dp->vers == 0){
DPRINT("changed: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
		DPRINT("changed\n");
		fldump();
		dp->vers++;
		setdef(dp);
		start = dp->t;


@@ 408,9 420,10 @@ DPRINT("changed: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
			}
			floppydir[NFDIR*dp->dev].length = dp->t->cap;
			floppyon(dp);
			DPRINT("changed: trying %s\n", dp->t->name);
			fldump();
			if(dp->t == start)
				nexterror();
			DPRINT("changed: trying %s\n", dp->t->name);
		}
		floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
		poperror();


@@ 594,9 607,14 @@ floppyon(Drive *dp)
	alreadyon = fl.motor & MOTORBIT(dp->dev);
	fl.motor |= MOTORBIT(dp->dev);
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
	if(!alreadyon)
	if(!alreadyon){
		/* wait for drive to spin up */
		tsleep(&dp->r, return0, 0, 750);

		/* clear any pending interrupts */
		floppysense();
	}

	/* set transfer rate */
	if(fl.rate != dp->t->rate){
		fl.rate = dp->t->rate;


@@ 646,10 664,12 @@ floppycmd(void)
	fl.nstat = 0;
	for(i = 0; i < fl.ncmd; i++){
		for(tries = 0; ; tries++){
			if(tries > 10000){
				DPRINT("cmd %ux can't be sent (%d %ux)\n",
					fl.cmd[0], i, inb(Pmsr));
				fl.confused = 1;
			if(tries > 1000){
				DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
				fldump();

				/* empty fifo, might have been a bad command */
				floppyresult();
				return -1;
			}
			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)


@@ 673,24 693,28 @@ floppyresult(void)
	int i, s;
	int tries;

	/* get the result of the operation */
	for(i = 0; i < sizeof(fl.stat); i++){
		/* wait for status byte */
		for(tries = 0; ; tries++){
			if(tries > 1000){
				DPRINT("floppyresult: %d stats\n", i);
				fldump();
				fl.confused = 1;
				return -1;
			}
			s = inb(Pmsr)&(Ffrom|Fready);
			if(s == Fready){
				fl.nstat = i;
				return i;
				return fl.nstat;
			}
			if(s == (Ffrom|Fready))
				break;
		}
		fl.stat[i] = inb(Pdata);
	}
	fl.nstat = i;
	return i;
	fl.nstat = sizeof(fl.stat);
	return fl.nstat;
}

/*


@@ 732,6 756,7 @@ floppysense(void)
		return -1;
	if(floppyresult() < 2){
		DPRINT("can't read sense response\n");
		fldump();
		fl.confused = 1;
		return -1;
	}


@@ 746,12 771,15 @@ cmddone(void *a)
}

/*
 *  wait for a floppy interrupt
 *  Wait for a floppy interrupt.  If none occurs in 5 seconds, we
 *  may have missed one.  This only happens on some portables which
 *  do power management behind our backs.  Call the interrupt
 *  routine to try to clear any conditions.
 */
static void
floppywait(void)
{
	tsleep(&fl.r, cmddone, 0, 2000);
	tsleep(&fl.r, cmddone, 0, 5000);
	if(!cmddone(0))
		floppyintr(0);
}


@@ 765,7 793,6 @@ floppyrecal(Drive *dp)
	dp->ccyl = -1;
	dp->cyl = -1;

DPRINT("floppyrecal: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Frecal;
	fl.cmd[fl.ncmd++] = dp->dev;


@@ 807,22 834,31 @@ floppyrevive(void)
	 *  reset the controller if it's confused
	 */
	if(fl.confused){
DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
		DPRINT("floppyrevive in\n");
		fldump();

		/* reset controller and turn all motors off */
		splhi();
		fl.ncmd = 1;
		fl.cmd[0] = 0;
		outb(Pdor, 0);
		delay(1);
		outb(Pdor, Fintena|Fena);
		spllo();
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
			dp->confused = 1;
		fl.motor = 0;
		floppywait();
		fl.confused = 0;
		floppywait();

		/* mark all drives in an unknown state */
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
			dp->confused = 1;

		/* set rate to a known value */
		outb(Pdsr, 0);
		fl.rate = 0;
DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));

		DPRINT("floppyrevive out\n");
		fldump();
	}
}



@@ 839,7 875,6 @@ floppyseek(Drive *dp, long off)
		return dp->tcyl;
	dp->cyl = -1;

	DPRINT("seek: tcyl %d, thead %d\n", dp->tcyl, dp->thead);
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fseek;
	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;


@@ 891,9 926,6 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
		error(Eio);
	}

	DPRINT("floppyxfer: tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);

	/*
	 *  set up the dma (dp->len may be trimmed)
	 */

M pc/devvga.c => pc/devvga.c +2 -0
@@ 297,8 297,10 @@ vgawrite(Chan *c, void *buf, long n, ulong offset)
		return n;
	case Qvgaport:
		cp = buf;
		/*
		if (offset + n >= 0x8000 || offset < 0x300)
			error(Ebadarg);
		*/
		for (port=offset; port<offset+n; port++) {
			outb(port, *cp++);
		}

M pc/kbd.c => pc/kbd.c +1 -1
@@ 188,7 188,7 @@ mousecmd(int cmd)
		c = inb(Data);
	} while(c == 0xFE || c == 0);
	if(c != 0xFA){
		print("mouse returns %2.2ux to the %2.2ux command\n", c, cmd);
		kprint("mouse returns %2.2ux to the %2.2ux command\n", c, cmd);
		return -1;
	}
	return 0;

M port/chan.c => port/chan.c +7 -5
@@ 42,7 42,7 @@ chandevreset(void)
{
	int i;

	for(i=0; i<strlen(devchar); i++)
	for(i=0; i<devchar[i]; i++)
		(*devtab[i].reset)();
}



@@ 51,7 51,7 @@ chandevinit(void)
{
	int i;

	for(i=0; i<strlen(devchar); i++)
	for(i=0; i<devchar[i]; i++)
		(*devtab[i].init)();
}



@@ 429,6 429,7 @@ namec(char *name, int amode, int omode, ulong perm)
{
	Chan *c, *nc, *cc;
	int t;
	Rune r;
	int mntok, isdot;
	char *p;
	char *elem;


@@ 463,12 464,13 @@ namec(char *name, int amode, int omode, ulong perm)
	else
	if(name[0] == '#') {
		mntok = 0;
		if(name[1]=='M')
		name++;
		name += chartorune(&r, name);
		if(r == 'M')
			error(Enonexist);
		t = devno(name[1], 1);
		t = devno(r, 1);
		if(t == -1)
			error(Ebadsharp);
		name += 2;
		if(*name == '/'){
			name = skipslash(name);
			elem[0]=0;

M port/dev.c => port/dev.c +16 -9
@@ 12,15 12,22 @@ extern ulong	kerndate;
int
devno(int c, int user)
{
	char *s;
	Rune *s;
	int i;

	s = strchr(devchar, c);
	if(s==0 || c==0){
		if(user)
			return -1;
		panic("devno %c 0x%ux", c, c);
	s = devchar;
	i = 0;
	while(*s){
		if(c == *s)
			return i;
		i++;
		s++;
	}
	return s - devchar;

	if(user)
		return -1;
	panic("devno %C 0x%ux", c, c);
	return 0;
}

void


@@ 68,7 75,7 @@ Chan *
devclone(Chan *c, Chan *nc)
{
	if(c->flag & COPEN)
		panic("clone of open file type %c\n", devchar[c->type]);
		panic("clone of open file type %C\n", devchar[c->type]);
	if(nc == 0)
		nc = newchan();
	nc->type = c->type;


@@ 130,7 137,7 @@ devstat(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen)
				convD2M(&dir, db);
				return;
			}
			print("%s %s: devstat %c %lux\n", u->p->text, u->p->user,
			print("%s %s: devstat %C %lux\n", u->p->text, u->p->user,
							devchar[c->type], c->qid.path);
			error(Enonexist);
		case 0:

M port/devmnt.c => port/devmnt.c +1 -2
@@ 773,8 773,7 @@ mntchk(Chan *c)
void
mntdirfix(uchar *dirbuf, Chan *c)
{
	dirbuf[DIRLEN-4] = devchar[c->type];
	dirbuf[DIRLEN-3] = 0;
	*(ushort*)&dirbuf[DIRLEN-4] = devchar[c->type];
	dirbuf[DIRLEN-2] = c->dev;
	dirbuf[DIRLEN-1] = c->dev>>8;
}

M port/net.c => port/net.c +1 -1
@@ 151,7 151,7 @@ netstat(Chan *c, char *db, Network *np)
				convD2M(&dir, db);
				return;
			}
			print("netstat %c %lux\n", devchar[c->type], c->qid.path);
			print("netstat %C %lux\n", devchar[c->type], c->qid.path);
			error(Enonexist);
		case 0:
			break;

M port/portdat.h => port/portdat.h +1 -1
@@ 733,7 733,7 @@ enum
extern	Conf	conf;
extern	char*	conffile;
extern	int	cpuserver;
extern	char*	devchar;
extern	Rune*	devchar;
extern	Dev	devtab[];
extern  char	eve[];
extern	uchar	initcode[];

M power/fns.h => power/fns.h +1 -0
@@ 58,6 58,7 @@ void	puttlbx(int, ulong, ulong);
int	readlog(ulong, char*, ulong);
void	restfpregs(FPsave*, ulong);
#define	screenputs syslog
void	scsiintr(int);
void	setvmevec(int, void (*)(int));
void	sinit(void);
uchar*	smap(int, uchar*);

M power/scsi.c => power/scsi.c +113 -66
@@ 34,6 34,7 @@ enum
	Rdata		= 0x19,		/* data register */
	Raux		= 0x1F,		/* auxiliary status register */
	  Dbr		=   0x01,	/* data buffer ready */
	  Cip		=   0x10,	/* command in progress */
	  Intrpend	=   0x80,	/* interrupt pending */

	Creset		= 0x00,		/* reset */


@@ 60,6 61,7 @@ typedef struct Target Target;
struct Target
{
	QLock;
	Lock	regs;
	Rendez;
	ulong	flags;
	uchar	sync;


@@ 115,6 117,15 @@ static Target target[NCtlr][NTarget];

static	void	dmamap(Target*);

static void
issue(Target *ctlr, uchar cmd)
{
	while(*ctlr->addr & Cip)
		;
	*ctlr->addr = Rcmd;
	*ctlr->data = cmd;
}

/*
 * Set up and start a data transfer. This maybe
 * a continuation.


@@ 165,8 176,7 @@ start(Target *tp)
	/*
	 * Select and transfer.
	 */
	*dev->addr = Rcmd;
	*dev->data = tp->transfer;
	issue(dev, tp->transfer);
}

/*


@@ 200,8 210,7 @@ arbitrate(Target *dev)
	*dev->data = 0x00;				/* cmdphase */
	*dev->addr = Rdestid;
	*dev->data = tp->target;
	*dev->addr = Rcmd;
	*dev->data = CselectATN;
	issue(dev, CselectATN);
}

static int


@@ 241,12 250,13 @@ scsiio(int nbus, Scsi *p, int rw)
	tp->dmalen = p->data.lim - p->data.base;
	tp->dmatx = 0;
	tp->status = 0x6002;
	tp->lun = p->lun;

	tp->clen = p->cmd.lim - p->cmd.base;
	memmove(tp->cdb, p->cmd.base, tp->clen);

	s = splhi();
	qlock(ctlr);
	lock(&ctlr->regs);

	/*
	 * Link the target onto the end of the


@@ 264,7 274,7 @@ scsiio(int nbus, Scsi *p, int rw)
		arbitrate(ctlr);
	}

	qunlock(ctlr);
	unlock(&ctlr->regs);
	splx(s);

	/*


@@ 335,7 345,7 @@ complete(Target *ctlr)
	 * one up.
	 */
	tp->flags &= Fidentified;
	*tp->dmafls = 1;
	*tp->dmafls = 0;

	wakeup(tp);



@@ 362,11 372,10 @@ disconnect(Target *ctlr)
	tp->flags |= Fdisconnected;
	ctlr->active = tp->active;

	if(ctlr->active){
	if(ctlr->active)
		arbitrate(ctlr);
		return;
	}
	ctlr->flags &= ~Fbusy;
	else
		ctlr->flags &= ~Fbusy;
}

/*


@@ 404,9 413,11 @@ identify(Target *tp, uchar status)
	switch(status){

	case 0x11:				/* select complete */
		delay(7);
		*dev->addr = Rcmd;
		*dev->data = Catn;
		/*
		 * This is what WD calls an 'extended interrupt',
		 * the next interrupt (0x8E) is already in the
		 * pipe, we don't have to do anything.
		 */
		break;

	case 0x8E:				/* service required - MSGOUT */


@@ 421,8 432,7 @@ identify(Target *tp, uchar status)
		*dev->data = 0x00;
		*dev->data = 0x00;
		*dev->data = sizeof(msgout);
		*dev->addr = Rcmd;
		*dev->data = Ctinfo;
		issue(dev, Ctinfo);
		msgout[0] = Midentify|tp->lun;
		*dev->addr = Rdata;
		n = 0;


@@ 463,8 473,7 @@ identify(Target *tp, uchar status)
		*dev->data = 0x00;
		*dev->data = 0x00;
		*dev->data = 5;
		*dev->addr = Rcmd;
		*dev->data = Ctinfo;
		issue(dev, Ctinfo);
		*dev->addr = Rdata;
		for(i = sizeof(msgin)-1, n = 0; n < i; n++){
			while((*dev->addr & Dbr) == 0){


@@ 489,8 498,24 @@ identify(Target *tp, uchar status)
		break;

	case 0x4E:
		*dev->addr = Rcmd;
		*dev->data = Csbt|Ctinfo;
		/*
		 * The target went to message-out phase, so send
		 * it a NOP to keep it happy.
		 * There seems to be no reason for this delay, other than
		 * that we just end up busy without an interrupt if it
		 * isn't there.
		 * I wish I understood this.
		 */
		delay(10);
		*dev->addr = Rstatus;
		n = *dev->data;
		USED(n);

		*dev->addr = Rtchi;
		*dev->data = 0x00;
		*dev->data = 0x00;
		*dev->data = 1;
		issue(dev, Ctinfo);
		*dev->addr = Rdata;
		while((*dev->addr & Dbr) == 0){
			if(*dev->addr & Intrpend)


@@ 499,10 524,8 @@ identify(Target *tp, uchar status)
		*dev->data = Mnop;
		break;

	case 0x20:				/* transfer info paused */
		delay(7);
		*dev->addr = Rcmd;
		*dev->data = Cnack;
	case 0x20:					/* transfer info paused */
		issue(dev, Cnack);
		break;

	case 0x1A:


@@ 527,7 550,7 @@ saveptr(Target *tp)
	Target *dev;
	ulong count, tx;

	*tp->dmafls = 1;
	*tp->dmafls = 0;

	dev = tp->ctlr;
	/*


@@ 539,6 562,11 @@ saveptr(Target *tp)
	count += (*dev->data & 0xFF)<<8;
	count += (*dev->data & 0xFF);

	*dev->addr = Rtchi;
	*dev->data = 0;
	*dev->data = 0;
	*dev->data = 0;

	tx = tp->dmalen - count;
	tp->dmaaddr += tx;
	tp->dmalen = count;


@@ 557,28 585,38 @@ scsistatus(Target *ctlr)
	return status;
}

void
scsiintr(int ctlrno)
static void
scsiprocessint(int ctlrno, Target *ctlr)
{
	uchar status, x, phase;
	Target *ctlr, *tp;
	Target *tp;
	uchar aux, status, sid, phase, x;

	ctlr = &target[ctlrno][CtlrID];
	tp = ctlr->active;

	if(*ctlr->addr & 0x20)
		print("busy\n");
	while(*ctlr->addr & 0x20)		/* Wait for busy to clear */
		;

	aux = *ctlr->addr;
	if((aux&0x80) == 0) {
		print("scsi%d: bogus int #%2.2lux\n", ctlrno, *ctlr->addr);
		return;
	}
	if(aux & 0x02)
		print("scsi%d: parity error (ignored)\n", ctlrno);
	if(aux & 0x10)
		print("scsi%d: cip #%2.2lux\n", ctlrno, aux);

	*ctlr->addr = Rcmdphase;
	phase = *ctlr->data;

	*ctlr->addr = Rsrcid;
	sid = *ctlr->data;
	*ctlr->addr = Rstatus;
	status = *ctlr->data;

	switch(status){
	case 0x00:				/* reset interrupt */
		return;
	if((aux&0x40) && status != 0x81)
		print("lci but not reconnect #%2.2lux\n", status);

	switch(status) {
	case 0x42:				/* timeout */
		tp->flags &= ~Fretry;
		scsistatus(ctlr);		/* Must read lun register */


@@ 586,12 624,6 @@ scsiintr(int ctlrno)
		return;

	case 0x16:				/* select-and-transfer complete */
		/*
		 * The target status comes back in the Rlun
		 * register. Returned status is combined
		 * with the final command phase, which
		 * should be 0x60.
		 */
		saveptr(tp);
		tp->status = scsistatus(ctlr);	/* target status */
		complete(ctlr);


@@ 599,8 631,7 @@ scsiintr(int ctlrno)

	case 0x21:				/* save data pointers */
		saveptr(tp);
		*ctlr->addr = Rcmd;
		*ctlr->data = tp->transfer;
		issue(ctlr, tp->transfer);
		return;

	case 0x4B:				/* unexpected status phase */


@@ 610,17 641,12 @@ scsiintr(int ctlrno)
			*ctlr->data = 0x41;	/* resume no data */
		else
			*ctlr->data = 0x46;	/* collect status */
		*ctlr->addr = Rtchi;
		*ctlr->data = 0;
		*ctlr->data = 0;
		*ctlr->data = 0;
		*ctlr->addr = Rcmd;
		*ctlr->data = tp->transfer;
		issue(ctlr, tp->transfer);
		return;

	case 0x85:					/* disconnect */
	case 0x85:				/* disconnect */
		if(tp->flags & Fidentifying){
			tp->cmdphase = 0x00;		/* complete retry */
			tp->cmdphase = 0x00;	/* complete retry */
			complete(ctlr);
			return;
		}


@@ 628,31 654,52 @@ scsiintr(int ctlrno)
		return;

	case 0x81:
		*ctlr->addr = Rsrcid;
		x = *ctlr->data;
		if(x & Siv){				/* source ID valid */
			reselect(ctlr, x & 0x07);
			ctlr->active->cmdphase = 0x44;	/* reselected by target */
			start(ctlr->active);
			return;
		*ctlr->addr = Rdata;
		x = *ctlr->data;		/* the identify message */
		USED(x);
		if((sid & Siv) == 0) {		/* source ID valid */
			print("scsi%d: invalid src id\n", ctlrno);
			break;
		}
		break;
		reselect(ctlr, sid & 0x07);
		ctlr->active->cmdphase = 0x45;	/* reselected by target */
		start(ctlr->active);
		return;

	default:
		if(tp == 0) {
			print("scsi%d: bogus sr #%2.2lux phase #%2.2lux\n",
					ctlrno, status, phase);
			return;
		}
		if((tp->flags & Fidentifying) && identify(tp, status) == 0)
			return;
		break;
	}
	delay(1000);
	print("scsi intr status #%.2ux\n", status);
	print("scsi aux status #%.2ux\n", *ctlr->addr & 0xFF);
	print("scsi%d:\n", ctlrno);
	if(tp) print("unit %d cmd #%2.2lux flags #%4.4lux phase #%2.2lux\n",
			tp->target, tp->cdb[0], tp->flags, tp->cmdphase);
	print("scsi status #%.2ux phase #%2.2lux\n", status, phase);
	print("aux  status #%2.2ux was #%2.2lux\n", *ctlr->addr, aux);
	for(*ctlr->addr = 0x00, x = 0x00; x < 0x19; x++){
		if((x & 0x07) == 0x07)
			print("#%.2ux: #%.2ux\n", x, *ctlr->data & 0xFF);
			print("#%.2ux: #%2.2ux\n", x, *ctlr->data);
		else
			print("#%.2ux: #%.2ux ", x, *ctlr->data & 0xFF);
			print("#%.2ux: #%2.2ux ", x, *ctlr->data);
	}
	panic("scsiintr\n");
	panic("\nscsiintr");
}

void
scsiintr(int ctlrno)
{
	Target *ctlr;

	ctlr = &target[ctlrno][CtlrID];

	lock(&ctlr->regs);
	scsiprocessint(ctlrno, ctlr);
	unlock(&ctlr->regs);
}

void

M power/trap.c => power/trap.c +1 -3
@@ 172,7 172,7 @@ intr(Ureg *ur)
	int i, any;
	ulong cause;
	static int bogies;
	uchar pend, npend, xxx;
	uchar pend, xxx;

	m->intr++;
	cause = ur->cause&(INTR5|INTR4|INTR3|INTR2|INTR1);


@@ 209,7 209,6 @@ intr(Ureg *ur)
		 *  3. read pending interrupts
		 */
		pend = SBCCREG->fintpending;
		npend = pend;

		/*
		 *  4. clear pending register


@@ 227,7 226,6 @@ intr(Ureg *ur)
		xxx = SBCCREG->fintpending;
		if(xxx){
			print("new pend %ux\n", xxx);
			npend = pend |= xxx;
			i = SBCCREG->flevel;
			USED(i);
		}