~kris/9p

9hist

fb6fc6c2654be6262d6627acd63f5d6e327ae042 — David du Colombier 35 years ago 0148026
Plan 9 from Bell Labs 1991-02-12
10 files changed, 141 insertions(+), 94 deletions(-)

M gnot/dat.h
M port/devmnt.c
M port/devproc.c
M port/pgrp.c
M power/dat.h
M power/devhotrod.c
M power/io.h
M power/main.c
M power/trap.c
M ss/dat.h
M gnot/dat.h => gnot/dat.h +1 -1
@@ 288,7 288,7 @@ struct Pgrp
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	Lock	debug;			/* single access via devproc.c */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};

M port/devmnt.c => port/devmnt.c +2 -2
@@ 688,10 688,10 @@ mntxmit(Mnt *m, Mnthdr *mh)
		error(Eshutdown);
#ifdef	BIT3
	/*
	 * Bit3 does its own multiplexing.  (Well, the file server does.)
	 * Bit3 and Hotrod do their own multiplexing.  (Well, the file server does.)
	 * The code is different enough that it's broken out separately here.
	 */
	if(devchar[q->msg->type] != '3')
	if(devchar[q->msg->type]!='3' && devchar[q->msg->type]!='H')
		goto Normal;

	incref(q);

M port/devproc.c => port/devproc.c +4 -4
@@ 374,17 374,17 @@ procwrite(Chan *c, void *va, long n)
	 */
	if(QID(c->qid) == Qnotepg){
		pg = pgrptab(c->pgrpid.path-1);
		lock(&pg->debug);
		qlock(&pg->debug);
		if(waserror()){
			unlock(&pg->debug);
			qunlock(&pg->debug);
			nexterror();
		}
		if(pg->pgrpid != c->pgrpid.vers){
			unlock(&pg->debug);
			qunlock(&pg->debug);
  	  		goto Died;
		}
		pgrpnote(pg, va, n, NUser);
		unlock(&pg->debug);
		qunlock(&pg->debug);
		return n;
	}


M port/pgrp.c => port/pgrp.c +2 -2
@@ 115,7 115,7 @@ closepgrp(Pgrp *p)
	Envp *ep;

	if(decref(p) == 0){
		lock(&p->debug);
		qlock(&p->debug);
		p->pgrpid = -1;
		m = p->mtab;
		for(i=0; i<p->nmtab; i++,m++)


@@ 130,7 130,7 @@ closepgrp(Pgrp *p)
		lock(&pgrpalloc);
		p->next = pgrpalloc.free;
		pgrpalloc.free = p;
		unlock(&p->debug);
		qunlock(&p->debug);
		unlock(&pgrpalloc);
	}
}

M power/dat.h => power/dat.h +1 -1
@@ 285,7 285,7 @@ struct Pgrp
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	Lock	debug;			/* single access via devproc.c */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};

M power/devhotrod.c => power/devhotrod.c +92 -64
@@ 5,6 5,7 @@
#include	"fns.h"
#include	"errno.h"
#include	"devtab.h"
#include	"fcall.h"

#include	"io.h"



@@ 42,6 43,7 @@ struct HotQ{

struct Hotrod{
	QLock;
	QLock		buflock;
	Lock		busy;
	Device		*addr;		/* address of the device */
	int		vec;		/* vme interrupt vector */


@@ 50,6 52,7 @@ struct Hotrod{
	HotQ		rq;		/* read this queue to receive replies */
	int		ri;		/* where to read next response */
	Rendez		r;
	uchar		buf[MAXFDATA+100];
};

Hotrod hotrod[Nhotrod];


@@ 62,13 65,15 @@ void	hotrodintr(int);
enum{
	RESET=	0,	/* params: Q address, length of queue */
	REBOOT=	1,	/* params: none */
	READ=	2,	/* params: buffer, count, returned count */
	WRITE=	3,	/* params: buffer, count */
};

void
hotsend(Hotrod *h, Hotmsg *m)
{
print("hotsend send %d %lux %lux\n", m->cmd, m, m->param[0]);
	h->wq->msg[h->wi] = m;
	h->wq->msg[h->wi] = (Hotmsg*)MP2VME(m);
	while(h->wq->msg[h->wi])
		;
print("hotsend done\n");


@@ 155,6 160,7 @@ hotrodopen(Chan *c, int omode)
{
	Device *dp;
	Hotrod *hp;
	Hotmsg *mp;

	if(c->qid.path == CHDIR){
		if(omode != OREAD)


@@ 174,9 180,10 @@ hotrodopen(Chan *c, int omode)
		 */
		hp->wi = 0;
		hp->ri = 0;
		u->khot.cmd = RESET;
		u->khot.param[0] = (ulong)&hp->rq;
		u->khot.param[1] = NhotQ;
		mp = &u->khot;
		mp->cmd = RESET;
		mp->param[0] = MP2VME(&hp->rq);
		mp->param[1] = NhotQ;
		hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
	}
	c->mode = openmode(omode);


@@ 205,45 212,60 @@ hotrodclose(Chan *c)
}

/*
 *  read the hotrod memory
 * Read and write use physical addresses if they can, which they usually can.
 * Most I/O is from devmnt, which has local buffers.  Therefore just check
 * that buf is in KSEG0 and is at an even address.
 */

long	 
hotrodread(Chan *c, void *buf, long n)
{
	Hotrod *hp;
	Device *dp;
	ulong *from;
	ulong *to;
	ulong *end;

	if(c->qid.path != Qhotrod)
		error(Egreg);

	/*
	 *  allow full word access only
	 */
	if((c->offset&(sizeof(ulong)-1)) || (n&(sizeof(ulong)-1)))
		error(Ebadarg);
	Hotmsg *mp;

	hp = &hotrod[c->dev];
	dp = hp->addr;
	if(c->offset >= sizeof(dp->mem))
		return 0;
	if(c->offset+n > sizeof(dp->mem))
		n = sizeof(dp->mem) - c->offset;

	/*
	 *  avoid memcpy to ensure VME 32-bit reads
	 */
	qlock(hp);
	to = buf;
	from = &dp->mem[c->offset/sizeof(ulong)];
	end = to + (n/sizeof(ulong));
	while(to != end){
		*to++ = *from++;
	switch(c->qid.path){
	case Qhotrod:
		if(n > sizeof hp->buf)
			error(Egreg);
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 *  use supplied buffer, no need to lock for reply
			 */
			mp = &u->khot;
			mp->param[2] = 0;	/* reply count */
			qlock(hp);
			mp->cmd = READ;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
			qunlock(hp);
			do
				n = mp->param[2];
			while(n == 0);
		}else{
			/*
			 *  use hotrod buffer.  lock the buffer till the reply
			 */
			mp = &u->uhot;
			mp->param[2] = 0;	/* reply count */
			qlock(&hp->buflock);
			qlock(hp);
			mp->cmd = READ;
			mp->param[0] = MP2VME(hp->buf);
			mp->param[1] = n;
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->uhot);
			qunlock(hp);
			do
				n = mp->param[2];
			while(n == 0);
			memcpy(buf, hp->buf, n);
			qunlock(&hp->buflock);
		}
		return n;
	}
	qunlock(hp);
	return n;
	error(Egreg);
	return 0;
}

/*


@@ 253,37 275,43 @@ long
hotrodwrite(Chan *c, void *buf, long n)
{
	Hotrod *hp;
	Device *dp;
	ulong *from;
	ulong *to;
	ulong *end;

	if(c->qid.path != Qhotrod)
		error(Egreg);
	/*
	 *  allow full word access only
	 */
	if((c->offset&(sizeof(ulong)-1)) || (n&(sizeof(ulong)-1)))
		error(Ebadarg);
	Hotmsg *mp;

	hp = &hotrod[c->dev];
	dp = hp->addr;
	if(c->offset >= sizeof(dp->mem))
		return 0;
	if(c->offset+n > sizeof(dp->mem))
		n = sizeof(dp->mem) - c->offset;

	/*
	 *  avoid memcpy to ensure VME 32-bit writes
	 */
	qlock(hp);
	from = buf;
	to = &dp->mem[c->offset/sizeof(ulong)];
	end = to + (n/sizeof(ulong));
	while(to != end)
		*to++ = *from++;
	qunlock(hp);
	return n;
	switch(c->qid.path){
	case 1:
		if(n > sizeof hp->buf)
			error(Egreg);
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 *  use supplied buffer, no need to lock for reply
			 */
			mp = &u->khot;
			qlock(hp);
			mp->cmd = WRITE;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
			qunlock(hp);
		}else{
			/*
			 *  use hotrod buffer.  lock the buffer till the reply
			 */
			mp = &u->uhot;
			qlock(&hp->buflock);
			qlock(hp);
			memcpy(hp->buf, buf, n);
			mp->cmd = WRITE;
			mp->param[0] = MP2VME(hp->buf);
			mp->param[1] = n;
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->uhot);
			qunlock(hp);
			qunlock(&hp->buflock);
		}
		return n;
	}
	error(Egreg);
	return 0;
}

void	 

M power/io.h => power/io.h +10 -3
@@ 71,8 71,15 @@ struct MODE {

#define MODEREG		IO2(MODE, 0xF40000)

/*
 * VME addressing.
 * MP2VME takes a physical MP bus address and returns an address
 * usable by a VME device through A32 space
 */
#define	MASTER	0x0
#define	SLAVE	0x4
#define	MP2VME(addr)	(((ulong)(addr) & 0x0fffffff) | (SLAVE<<28))


struct INTVEC {
	struct {


@@ 84,9 91,9 @@ struct INTVEC {
#define INTVECREG	IO2(INTVEC, 0xF60000)
#define	NVRAM		IO2(uchar, 0xF10000)
#define INTPENDREG	IO2(uchar, 0xF20000)	/* same as LED */
#define IO2CLRMASK	IO2(uchar, 0xFE0000)
#define IO2SETMASK	IO2(uchar, 0xFE8000)
#define IO2MASK		IO2(ushort, 0xFE8000)
#define INTPENDREG3	IO2(uchar, 0xFF0000)	/* same as ENET ID */
#define IO2CLRMASK	IO2(ulong, 0xFE0000)
#define IO2SETMASK	IO2(ulong, 0xFE8000)
#define	MPBERR0		IO2(ulong, 0xF48000)
#define	MPBERR1		IO2(ulong, 0xF4C000)
#define	RTC		(NVRAM+0x3ff8)

M power/main.c => power/main.c +3 -3
@@ 137,7 137,7 @@ ioboardinit(void)

	ioid = *IOID;
	if(ioid >= IO3R1)
		maxlevel = 11;
		maxlevel = 8;
	else
		maxlevel = 8;



@@ 177,9 177,9 @@ ioboardinit(void)
	SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */

	/*
	 *  enable all interrupts on the IO2
	 *  Enable all interrupts on the IO2.  If IO3, run in compatibility mode.
	 */
	*IO2SETMASK = 0xff;
	*IO2SETMASK = 0xff000000;

}


M power/trap.c => power/trap.c +25 -13
@@ 175,7 175,8 @@ trap(Ureg *ur)
void
intr(Ureg *ur)
{
	int i, pend;
	int i, any;
	uchar pend, npend;
	long v;
	ulong cause;



@@ 189,19 190,20 @@ intr(Ureg *ur)
		cause &= ~INTR1;
	}
	if(cause & INTR5){

		any = 0;
		if(!(*MPBERR1 & (1<<8))){
			print("MP bus error %lux %lux\n", *MPBERR0, *MPBERR1);
			*MPBERR0 = 0;
			i = *SBEADDR;
			USED(i);
			any = 1;
		}

		/*
		 *  directions from IO2 manual
		 *  1. clear all IO2 masks
		 */
		*IO2CLRMASK = 0xff;
		*IO2CLRMASK = 0xff000000;

		/*
		 *  2. wait for interrupt in progress


@@ 212,7 214,7 @@ intr(Ureg *ur)
		/*
		 *  3. read pending interrupts
		 */
		pend = SBCCREG->fintpending & 0xff;
		npend = pend = SBCCREG->fintpending;

		/*
		 *  4. clear pending register


@@ 223,22 225,26 @@ intr(Ureg *ur)
		/*
		 *  5a. process lance, scsi
		 */
	loop:
		if(pend & 1) {
			v = INTVECREG->i[0].vec;
			if(!(v & (1<<12))){
				print("io2 mp bus error %d %lux %lux\n", 0,
					*MPBERR0, *MPBERR1);
				*MPBERR0 = 0;
				any = 1;
			}
			if(ioid < IO3R1){
				if(!(v & 7))
					any = 1;
				if(!(v & (1<<2)))
					lanceintr();
				if(!(v & (1<<1)))
					lanceparity();
				if(!(v & (1<<0)))
					print("SCSI interrupt\n");
			} else {
			}else{
				if(v & 7)
					any = 1;
				if(v & (1<<2))
					lanceintr();
				if(v & (1<<1))


@@ 249,26 255,32 @@ intr(Ureg *ur)
		}
		/*
		 *  5b. process vme
		 *  i bet i can guess your level
		 *  i can guess your level
		 */
		pend >>= 1;
		for(i=1; pend; i++) {
		for(i=1; pend>>=1; i++){
			if(pend & 1) {
				v = INTVECREG->i[i].vec;
				if(!(v & (1<<12))){
					print("io2 mp bus error %d %lux %lux\n", i,
						*MPBERR0, *MPBERR1);
					print("io2 mp bus error %d %lux %lux\n",
						i, *MPBERR0, *MPBERR1);
					*MPBERR0 = 0;
				}
				v &= 0xff;
				(*vmevec[v])(v);
				any = 1;
			}
			pend >>= 1;
		}
		/*
		 *  if nothing else, assume bus error
		 */
		if(!any){
			print("bogus intr lvl 5 pend %lux on %d\n", npend, m->machno);
			delay(100);
		}
		/*
		 *  6. re-enable interrupts
		 */
		*IO2SETMASK = 0xff;
		*IO2SETMASK = 0xff000000;
		cause &= ~INTR5;
	}
	if(cause)

M ss/dat.h => ss/dat.h +1 -1
@@ 293,7 293,7 @@ struct Pgrp
	char	user[NAMELEN];
	int	nmtab;			/* highest active mount table entry, +1 */
	int	nenv;			/* highest active env table entry, +1 */
	Lock	debug;			/* single access via devproc.c */
	QLock	debug;			/* single access via devproc.c */
	Mtab	*mtab;
	Envp	*etab;
};