~kris/9p

9hist

d9329cfd73c4b72130b3adb72a5f0ef3629ba49b — David du Colombier 34 years ago 8c434f5
Plan 9 from Bell Labs 1992-06-13
3 files changed, 160 insertions(+), 219 deletions(-)

M port/devmnt.c
M power/dat.h
R power/{devhotrod => devcyc}.c
M port/devmnt.c => port/devmnt.c +3 -4
@@ 48,8 48,7 @@ struct Mntalloc
	int	id;
}mntalloc;

#define BITBOTCH	256
#define MAXRPC		(MAXFDATA+MAXMSG+BITBOTCH)
#define MAXRPC		(MAXFDATA+MAXMSG)
#define limit(n, max)	(n > max ? max : n)

Chan 	*mattach(Mnt*, char*, char*);


@@ 540,8 539,8 @@ mntrdwr(int type, Chan *c, void *buf, long n, ulong offset)
void
mountrpc(Mnt *m, Mntrpc *r)
{
	r->reply.tag = 0;		/* safety check */
	r->reply.type = 4;		/* safety check */
	r->reply.tag = 0;		/* safety checks */
	r->reply.type = 4;
	mountio(m, r);
	if(r->reply.type == Rerror)
		error(r->reply.ename);

M power/dat.h => power/dat.h +7 -30
@@ 1,7 1,6 @@
typedef struct Bit3msg	Bit3msg;
typedef struct Conf	Conf;
typedef struct FPsave	FPsave;
typedef struct Hotmsg	Hotmsg;
typedef struct Cycmsg	Cycmsg;
typedef struct Lance	Lance;
typedef struct Lancemem	Lancemem;
typedef struct Label	Label;


@@ 101,25 100,12 @@ struct PMMU

#include "../port/portdat.h"

/*
 *  machine dependent definitions not used by ../port/dat.h
 */
struct Bit3msg
{
	ulong	cmd;
	ulong	addr;
	ulong	count;
	ulong	rcount;
};

struct Hotmsg
struct Cycmsg
{
	ulong	cmd;
	ulong	param[5];
	Rendez	r;
	uchar	intr;			/* flag: interrupt has occurred */
	uchar	abort;			/* flag: don't interrupt */
	ushort	wlen;			/* length of last message written */
};

struct Mach


@@ 221,7 207,7 @@ struct User
	Chan	*dot;
	/*
	 * Rest of structure controlled by devproc.c and friends.
	 * lock(&p->debug) to modify.
	 * qlock(&p->debug) to modify.
	 */
	Note	note[NNOTE];
	short	nnote;


@@ 236,22 222,13 @@ struct User
	 *  machine dependent User stuff
	 */
	/*
	 * I/O point for bit3 and hotrod interfaces.
	 * I/O point for hotrod interfaces.
	 * This is the easiest way to allocate
	 * them, but not the prettiest or most general.
	 */
	union{				/* for i/o from kernel */
		Bit3msg	kbit3;
		Hotmsg	khot;
	};
	union{				/* for i/o from user */
		Bit3msg	ubit3;
		Hotmsg	uhot;
	};
	union{				/* special location for Tflush */
		Bit3msg	fbit3;
		Hotmsg	fhot;
	};
	Cycmsg	kcyc;
	Cycmsg	ucyc;
	Cycmsg	fcyc;
};

extern register Mach	*m;

R power/devhotrod.c => power/devcyc.c +150 -185
@@ 1,4 1,3 @@
#define	BITBOTCH	256	/* remove with BIT3 */
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"


@@ 12,24 11,24 @@
#include	"../../fs/cyc/comm.h"


typedef struct Commrod	Commrod;
typedef struct Commcyc	Commcyc;

enum
{
	Vmevec=		0xd2,		/* vme vector for interrupts */
	Intlevel=	5,		/* level to interrupt on */
	Qdir=		0,		/* Qid's */
	Qhotrod=	1,
	Nhotrod=	1,
	Qcyc=		1,
	Ncyc=		1,
};

Dirtab hotroddir[]={
	"hotrod",	{Qhotrod},	0,	0600,
Dirtab cycdir[]={
	"cyc",	{Qcyc},	0,	0600,
};

#define	NHOTRODDIR	(sizeof hotroddir/sizeof(Dirtab))
#define	NCYCDIR	(sizeof cycdir/sizeof(Dirtab))

struct Commrod
struct Commcyc
{
	Lock;
	QLock		buflock;


@@ 38,28 37,27 @@ struct Commrod
	int		vec;		/* vme interrupt vector */
	int		wi;		/* where to write next cmd */
	int		ri;		/* where to read next reply */
	uchar		buf[MAXFDATA+MAXMSG+BITBOTCH];
	uchar		buf[MAXFDATA+MAXMSG];
};

Commrod hotrod[Nhotrod];
Commcyc cyclone[Ncyc];

void	hotrodintr(int);
void	cycintr(int);

#define	HOTROD	VMEA24SUP(Comm, 0x10000);
#define	CYCLONE	VMEA24SUP(Comm, 0x10000);

/*
 * Commands
 */

Hotmsg**
hotsend(Commrod *h, Hotmsg *m)
Cycmsg**
cycsend(Commcyc *h, Cycmsg *m)
{
	Hotmsg **mp;
int i;
	Cycmsg **mp;

	lock(h);
	mp = (Hotmsg**)&h->addr->reqstq[h->wi];
	*mp = (Hotmsg*)MP2VME(m);
	mp = (Cycmsg**)&h->addr->reqstq[h->wi];
	*mp = (Cycmsg*)MP2VME(m);
	h->wi++;
	if(h->wi >= NRQ)
		h->wi = 0;


@@ 68,7 66,7 @@ int i;
}

void
hotwait(Hotmsg **mp)
cycwait(Cycmsg **mp)
{
	ulong l;



@@ 77,33 75,33 @@ hotwait(Hotmsg **mp)
		delay(0);	/* just a subroutine call; stay off VME */
		if(++l > 10*1000*1000){
			l = 0;
			panic("hotsend blocked");
			panic("cycsend blocked");
		}
	}
	return;
}

/*
 *  reset all hotrod boards
 *  reset all cyclone boards
 */
void
hotrodreset(void)
cycreset(void)
{
	int i;
	Commrod *hp;
	Commcyc *cp;

	for(hp=hotrod,i=0; i<Nhotrod; i++,hp++){
		hp->addr = HOTROD+i;
	for(cp=cyclone,i=0; i<Ncyc; i++,cp++){
		cp->addr = CYCLONE+i;
		/*
		 * Write queue is at end of hotrod memory
		 * Write queue is at end of cyclone memory
		 */
		hp->vec = Vmevec+i;
		setvmevec(hp->vec, hotrodintr);
		cp->vec = Vmevec+i;
		setvmevec(cp->vec, cycintr);
	}	
}

void
hotrodinit(void)
cycinit(void)
{
}



@@ 111,17 109,16 @@ hotrodinit(void)
 *  enable the device for interrupts, spec is the device number
 */
Chan*
hotrodattach(char *spec)
cycattach(char *spec)
{
	Commrod *hp;
	int i;
	Chan *c;

	i = strtoul(spec, 0, 0);
	if(i >= Nhotrod)
	if(i >= Ncyc)
		error(Ebadarg);

	c = devattach('H', spec);
	c = devattach('C', spec);
	c->dev = i;
	c->qid.path = CHDIR;
	c->qid.vers = 0;


@@ 129,53 126,53 @@ hotrodattach(char *spec)
}

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

int	 
hotrodwalk(Chan *c, char *name)
cycwalk(Chan *c, char *name)
{
	return devwalk(c, name, hotroddir, NHOTRODDIR, devgen);
	return devwalk(c, name, cycdir, NCYCDIR, devgen);
}

void	 
hotrodstat(Chan *c, char *dp)
cycstat(Chan *c, char *dp)
{
	devstat(c, dp, hotroddir, NHOTRODDIR, devgen);
	devstat(c, dp, cycdir, NCYCDIR, devgen);
}

Chan*
hotrodopen(Chan *c, int omode)
cycopen(Chan *c, int omode)
{
	Commrod *hp;
	Hotmsg *mp, **hmp;
	Commcyc *cp;
	Cycmsg *mp, **cmp;

	if(c->qid.path == CHDIR){
		if(omode != OREAD)
			error(Eperm);
	}else if(c->qid.path == Qhotrod){
		hp = &hotrod[c->dev];
		if(!canlock(&hp->busy))
	}else if(c->qid.path == Qcyc){
		cp = &cyclone[c->dev];
		if(!canlock(&cp->busy))
			error(Einuse);
		/*
		 * Clear communications region
		 */
		memset(hp->addr->reqstq, 0, NRQ*sizeof(ulong));
		hp->addr->reqstp = 0;
		memset(hp->addr->replyq, 0, NRQ*sizeof(ulong));
		hp->addr->replyp = 0;
		memset(cp->addr->reqstq, 0, NRQ*sizeof(ulong));
		cp->addr->reqstp = 0;
		memset(cp->addr->replyq, 0, NRQ*sizeof(ulong));
		cp->addr->replyp = 0;

		/*
		 * Issue reset
		 */
		hp->wi = 0;
		hp->ri = 0;
		mp = &u->khot;
		cp->wi = 0;
		cp->ri = 0;
		mp = &u->kcyc;
		mp->cmd = Ureset;
		hmp = hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
		hotwait(hmp);
		cmp = cycsend(cp, &((User*)(u->p->upage->pa|KZERO))->kcyc);
		cycwait(cmp);
		delay(100);
		print("reset\n");
	}


@@ 186,43 183,30 @@ hotrodopen(Chan *c, int omode)
}

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

void	 
hotrodclose(Chan *c)
cycclose(Chan *c)
{
	Commrod *hp;
	Hotmsg **hmp;
	Commcyc *cp;
	Cycmsg **cmp;

	hp = &hotrod[c->dev];
	cp = &cyclone[c->dev];
	if(c->qid.path != CHDIR){
		u->khot.cmd = Ureboot;
		hmp = hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
		hotwait(hmp);
		unlock(&hp->busy);
		u->kcyc.cmd = Ureboot;
		cmp = cycsend(cp, &((User*)(u->p->upage->pa|KZERO))->kcyc);
		cycwait(cmp);
		unlock(&cp->busy);
	}
}

ulong
hotsum(ulong *p, int n, ulong doit)
{
	ulong sum;

	if(!doit)
		return 0;
	sum = 0;
	n = (n+sizeof(ulong)-1)/sizeof(ulong);
	while(--n >= 0)
		sum += *p++;
	return sum;
}

int
hotmsgintr(Hotmsg *hm)
cycmsgintr(Cycmsg *hm)
{
	return hm->intr;
}


@@ 234,200 218,181 @@ hotmsgintr(Hotmsg *hm)
 */

long	 
hotrodread(Chan *c, void *buf, long n, ulong offset)
cycread(Chan *c, void *buf, long n, ulong offset)
{
	Commrod *hp;
	Hotmsg *mp, **hmp;
	User *pu;
	Commcyc *cp;
	Cycmsg *mp, **cmp;
	ulong l, m, isflush;

	hp = &hotrod[c->dev];
	cp = &cyclone[c->dev];
	switch(c->qid.path & ~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, hotroddir, NHOTRODDIR, devgen);
		return devdirread(c, buf, n, cycdir, NCYCDIR, devgen);

	case Qhotrod:
		if(n > sizeof hp->buf){
			print("hotrod bufsize %d %d\n", n, sizeof hp->buf);
	case Qcyc:
		if(n > sizeof cp->buf){
			print("cyclone bufsize %d %d\n", n, sizeof cp->buf);
			error(Egreg);
		}
		pu = (User*)(u->p->upage->pa|KZERO);
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 *  use supplied buffer, no need to lock for reply
			 */
			isflush = 0;
			mp = &((User*)(u->p->upage->pa|KZERO))->khot;
			if(mp->abort){	/* use reserved flush msg */
				mp = &((User*)(u->p->upage->pa|KZERO))->fhot;
				isflush = 1;
			}
			mp->param[2] = 0;	/* reply checksum */
			mp->param[3] = 0xDEADBEEF;	/* reply count */

			mp = &pu->kcyc;
			mp->cmd = Uread;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			mp->abort = isflush;
			mp->param[2] = 0;		/* reply checksum */
			mp->param[3] = 0xdeadbeef;	/* reply count */
			mp->intr = 0;
			hmp = hotsend(hp, mp);
			if(isflush){		/* busy loop */
				l = 100*1000*1000;
				do
					m = mp->param[3];
				while(m==0 && --l>0);
				print("isflush blocked\n");
			}else{
				if(waserror()){
					if(*hmp && *hmp==mp)
						hotwait(hmp);
					mp->abort = 1;
					nexterror();
				}
				sleep(&mp->r, hotmsgintr, mp);
				m = mp->param[3];
			}
			cycsend(cp, mp);

			while(waserror())
				;
			sleep(&mp->r, cycmsgintr, mp);
			poperror();

			m = mp->param[3];
			if(m==0 || m>n){
				print("devhotrod: count 0x%lux 0x%lux\n", m, n);
				print("devcyc: count 0x%lux 0x%lux\n", m, n);
				error(Egreg);
			}
			if(mp->param[2] != hotsum(buf, m, mp->param[2])){
				print("hotrod cksum err is %lux sb %lux\n",
					hotsum(buf, m, 1), mp->param[2]);
				error(Eio);
			}
			mp->abort = 0;
			if(isflush)
				u->khot.abort = 0;	/* flushed message's done too */
			else
				poperror();
		}else{
		}
		else{
			/*
			 * use hotrod buffer. lock the buffer until the reply
			 * use cyclone buffer. lock the buffer until the reply
			 */
			mp = &((User*)(u->p->upage->pa|KZERO))->uhot;
			mp->param[2] = 0;	/* reply checksum */
			mp->param[3] = 0;	/* reply count */
			qlock(&hp->buflock);
			mp = &pu->ucyc;
			qlock(&cp->buflock);
			mp->cmd = Uread;
			mp->param[0] = MP2VME(hp->buf);
			mp->param[0] = MP2VME(cp->buf);
			mp->param[1] = n;
			mp->abort = 1;
			mp->param[2] = 0;	/* reply checksum */
			mp->param[3] = 0;	/* reply count */
			mp->intr = 0;
			hmp = hotsend(hp, mp);
			hotwait(hmp);
			cmp = cycsend(cp, mp);
			cycwait(cmp);
			l = 100*1000*1000;
			do
				m = mp->param[3];
			while(m==0 && --l>0);
			if(m==0 || m>n){
				print("devhotrod: count %ld %ld\n", m, n);
				qunlock(&hp->buflock);
				print("devcyc: count %ld %ld\n", m, n);
				qunlock(&cp->buflock);
				error(Egreg);
			}
			if(mp->param[2] != hotsum((ulong*)hp->buf, m, mp->param[2])){
				print("hotrod cksum err is %lux sb %lux\n",
					hotsum((ulong*)hp->buf, m, 1), mp->param[2]);
				qunlock(&hp->buflock);
				error(Eio);
			}
			memmove(buf, hp->buf, m);
			mp->abort = 0;
			qunlock(&hp->buflock);
			memmove(buf, cp->buf, m);
			qunlock(&cp->buflock);
		}
		return m;
	}
	print("hotrod read unk\n");
	print("devcyc read unk\n");
	error(Egreg);
	return 0;
}

long	 
hotrodwrite(Chan *c, void *buf, long n, ulong offset)
cycwrite(Chan *c, void *buf, long n, ulong offset)
{
	Commrod *hp;
	Hotmsg *mp, **hmp;
	User *pu;
	Commcyc *cp;
	Cycmsg *mp, **cmp;

	hp = &hotrod[c->dev];
	cp = &cyclone[c->dev];
	switch(c->qid.path & ~CHDIR){
	case Qdir:
		return devdirread(c, buf, n, hotroddir, NHOTRODDIR, devgen);
		return devdirread(c, buf, n, cycdir, NCYCDIR, devgen);

	case Qhotrod:
		if(n > sizeof hp->buf){
			print("hotrod write bufsize\n");
	case Qcyc:
		if(n > sizeof cp->buf){
			print("cyclone write bufsize\n");
			error(Egreg);
		}
		pu = (User*)(u->p->upage->pa|KZERO);
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 * use supplied buffer, no need to lock for reply
			 */
			mp = &((User*)(u->p->upage->pa|KZERO))->khot;
			mp->wlen = n;
			if(mp->abort)	/* use reserved flush msg */
				mp = &((User*)(u->p->upage->pa|KZERO))->fhot;
			mp = &pu->kcyc;

			mp->cmd = Uwrite;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			mp->param[2] = 0;
			hmp = hotsend(hp, mp);
			hotwait(hmp);

			cmp = cycsend(cp, mp);
			cycwait(cmp);
		}else{
			/*
			 * use hotrod buffer.  lock the buffer until the reply
			 * use cyclone buffer.  lock the buffer until the reply
			 */
			mp = &((User*)(u->p->upage->pa|KZERO))->uhot;
			mp->wlen = n;
			qlock(&hp->buflock);
			memmove(hp->buf, buf, n);
			mp = &pu->ucyc;
			qlock(&cp->buflock);
			memmove(cp->buf, buf, n);

			mp->cmd = Uwrite;
			mp->param[0] = MP2VME(hp->buf);
			mp->param[0] = MP2VME(cp->buf);
			mp->param[1] = n;
			mp->param[2] = 0;
			hmp = hotsend(hp, mp);
			hotwait(hmp);
			qunlock(&hp->buflock);

			cmp = cycsend(cp, mp);
			cycwait(cmp);
			qunlock(&cp->buflock);
		}
		return n;
	}
	print("hotrod write unk\n");
	print("cyclone write unk\n");
	error(Egreg);
	return 0;
}

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

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

void
hotrodintr(int vec)
cycintr(int vec)
{
	Commrod *h;
	Hotmsg *hm;
	ulong l;
	Cycmsg *cm;
	Commcyc *h;
	ulong l, n, *r;

	h = &hotrod[vec - Vmevec];
	if(h<hotrod || h>&hotrod[Nhotrod]){
		print("bad hotrod vec\n");
	h = &cyclone[vec - Vmevec];
	if(h<cyclone || h>&cyclone[Ncyc]){
		print("bad cyclone vec\n");
		return;
	}
	while(l = h->addr->replyq[h->ri]){	/* assign = */
		hm = (Hotmsg*)(VME2MP(l));
		h->addr->replyq[h->ri] = 0;
		h->ri++;

	r = h->addr->replyq;

	for(;;) {
		l = r[h->ri];
		if(l == 0)
			break;

		r[h->ri++] = 0;
		if(h->ri >= NRQ)
			h->ri = 0;
		hm->intr = 1;
		if(hm->param[3]==0 || hm->param[3] > 10000)
			print("hotrodintr count 0x%lux\n", hm->param[3]);
		if(!hm->abort)
			wakeup(&hm->r);

		cm = (Cycmsg*)VME2MP(l);
		cm->intr = 1;
		n = cm->param[3];
		if(n==0 || n > 10000)
			print("cycintr count 0x%lux\n", n);

		wakeup(&cm->r);
	}
}