~kris/9p

9hist

73a0085afd27f31d6a8571208971b8b084b22998 — David du Colombier 35 years ago 70acb15
Plan 9 from Bell Labs 1991-03-06
4 files changed, 96 insertions(+), 54 deletions(-)

M port/devmnt.c
M power/dat.h
M power/devhotrod.c
M power/io.h
M port/devmnt.c => port/devmnt.c +5 -0
@@ 708,8 708,13 @@ mntxmit(Mnt *m, Mnthdr *mh)
	/*
	 * Read response
	 */
	if(waserror()){		/* 3 */
		mntflush(m, mh);
		nexterror();
	}
	mh->mbr = mballoc();
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE);
	poperror();		/* 3 */
	mqfree(q);
	poperror();		/* 2 */


M power/dat.h => power/dat.h +15 -8
@@ 68,6 68,12 @@ struct QLock
	Lock	queue;			/* to access list */
};

struct Rendez
{
	Lock;
	Proc	*p;
};

struct Label
{
	ulong	pc;


@@ 96,6 102,9 @@ struct Hotmsg
{
	ulong	cmd;
	ulong	param[5];
	Rendez	r;
	short	intr;			/* flag: interrupt has occurred */
	short	abort;			/* flag: don't interrupt */
};

#define	CHDIR	0x80000000L


@@ 298,12 307,6 @@ struct PTE
	Page	*page;
};

struct Rendez
{
	Lock;
	Proc	*p;
};

struct Seg
{
	Proc	*proc;			/* process owning this segment */


@@ 367,14 370,18 @@ struct User
	 * This is the easiest way to allocate
	 * them, but not the prettiest or most general.
	 */
	union{
	union{				/* for i/o from kernel */
		Bit3msg	kbit3;
		Hotmsg	khot;
	};
	union{
	union{				/* for i/o from user */
		Bit3msg	ubit3;
		Hotmsg	uhot;
	};
	union{				/* special location for Tflush */
		Bit3msg	fbit3;
		Hotmsg	fhot;
	};
	/*
	 * Rest of structure controlled by devproc.c and friends.
	 * lock(&p->debug) to modify.

M power/devhotrod.c => power/devhotrod.c +74 -45
@@ 10,43 10,37 @@
#include	"io.h"
#include	"hrod.h"

/*
 * If defined, causes memory test to be run at device open
 */
#ifdef	ENABMEMTEST
void	mem(Hot*, ulong*, ulong);
#endif

/*
 * If set, causes data transfers to have checksums
 */
#define	ENABCKSUM	0
#define	ENABCKSUM	1

typedef struct Hotrod	Hotrod;
typedef struct HotQ	HotQ;

enum {
enum{
	Vmevec=		0xd2,		/* vme vector for interrupts */
	Intlevel=	5,		/* level to interrupt on */
	Qdir=		0,		/* Qid's */
	Qhotrod=	1,
	NhotQ=		NRQ,		/* size of communication queues */
	Nhotrod=	1,
};

struct HotQ{
	ulong	i;			/* index into queue */
	Hotmsg	*msg[NhotQ];		/* pointer to command buffer */
	ulong	pad[3];			/* unused; for hotrod prints */
};


struct Hotrod{
	QLock;
	QLock		buflock;
	Lock		busy;
	Hot		*addr;		/* address of the device */
	int		vec;		/* vme interrupt vector */
	HotQ		*wq;		/* write this queue to send cmds */
	int		wi;		/* where to write next cmd */
	HotQ		rq;		/* read this queue to receive replies */
	ulong		rq[NRQ];	/* read this queue to receive replies */
	int		ri;		/* where to read next response */
	Rendez		r;
	uchar		buf[MAXFDATA+MAXMSG];
};



@@ 74,10 68,10 @@ hotsend(Hotrod *h, Hotmsg *m)
	long l;

/* print("hotsend send %d %d %lux %lux\n", h->wi, m->cmd, m, m->param[0]); /**/
	mp = &h->wq->msg[h->wi];
	mp = (Hotmsg**)&h->addr->hostrq[h->wi];
	*mp = (Hotmsg*)MP2VME(m);
	h->wi++;
	if(h->wi >= NhotQ)
	if(h->wi >= NRQ)
		h->wi = 0;
	l = 0;
	while(*mp){


@@ 103,7 97,6 @@ hotrodreset(void)
		/*
		 * Write queue is at end of hotrod memory
		 */
		hp->wq = (HotQ*)(&hp->addr->hostrp);
		hp->vec = Vmevec+i;
		setvmevec(hp->vec, hotrodintr);
	}	


@@ 181,8 174,8 @@ hotrodopen(Chan *c, int omode)
		/*
		 * Clear communications region
		 */
		memset(hp->wq->msg, 0, sizeof(hp->wq->msg));
		hp->wq->i = 0;
		memset(hp->addr->hostrq, 0, NRQ*sizeof(ulong));
		hp->addr->hostrp = 0;

		/*
		 * Issue reset


@@ 191,13 184,13 @@ hotrodopen(Chan *c, int omode)
		hp->ri = 0;
		mp = &u->khot;
		mp->cmd = RESET;
		mp->param[0] = MP2VME(&hp->rq);
		mp->param[1] = NhotQ;
		mp->param[0] = MP2VME(hp->rq);
		mp->param[1] = NRQ;
		hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
		delay(100);
		print("reset\n");

#ifdef asdf
#ifdef ENABMEMTEST
		/*
		 * Issue test
		 */


@@ 253,6 246,12 @@ hotsum(ulong *p, int n, ulong doit)
	return sum;
}

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

/*
 * 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


@@ 264,7 263,7 @@ hotrodread(Chan *c, void *buf, long n)
{
	Hotrod *hp;
	Hotmsg *mp;
	ulong l, m;
	ulong l, m, isflush;

	hp = &hotrod[c->dev];
	switch(c->qid.path){


@@ 277,19 276,35 @@ hotrodread(Chan *c, void *buf, long n)
			/*
			 *  use supplied buffer, no need to lock for reply
			 */
			mp = &u->khot;
			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;	/* checksum */
			mp->param[3] = 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);
			mp->abort = isflush;
			mp->intr = 0;
			hotsend(hp, mp);
			qunlock(hp);
			l = 100*1000*1000;
			do
			if(isflush){		/* busy loop */
				l = 100*1000*1000;
				do
					m = mp->param[3];
				while(m==0 && --l>0);
			}else{
				if(waserror()){
					mp->abort = 1;
					nexterror();
				}
				sleep(&mp->r, hotmsgintr, mp);
				m = mp->param[3];
			while(m==0 && --l>0);
			}
			if(m==0 || m>n){
				print("devhotrod: count %ld %ld\n", m, n);
				error(Egreg);


@@ 299,11 314,13 @@ hotrodread(Chan *c, void *buf, long n)
					hotsum(buf, n, 1), mp->param[2]);
				error(Eio);
			}
			if(!isflush)
				poperror();
		}else{
			/*
			 *  use hotrod buffer.  lock the buffer until the reply
			 * use hotrod buffer. lock the buffer until the reply
			 */
			mp = &u->uhot;
			mp = &((User*)(u->p->upage->pa|KZERO))->uhot;
			mp->param[2] = 0;	/* checksum */
			mp->param[3] = 0;	/* reply count */
			qlock(&hp->buflock);


@@ 311,7 328,9 @@ hotrodread(Chan *c, void *buf, long n)
			mp->cmd = READ;
			mp->param[0] = MP2VME(hp->buf);
			mp->param[1] = n;
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->uhot);
			mp->abort = 1;
			mp->intr = 0;
			hotsend(hp, mp);
			qunlock(hp);
			l = 100*1000*1000;
			do


@@ 338,9 357,6 @@ hotrodread(Chan *c, void *buf, long n)
	return 0;
}

/*
 *  write hotrod memory
 */
long	 
hotrodwrite(Chan *c, void *buf, long n)
{


@@ 356,21 372,23 @@ hotrodwrite(Chan *c, void *buf, long n)
		}
		if((((ulong)buf)&(KSEGM|3)) == KSEG0){
			/*
			 *  use supplied buffer, no need to lock for reply
			 * use supplied buffer, no need to lock for reply
			 */
			mp = &u->khot;
			mp = &((User*)(u->p->upage->pa|KZERO))->khot;
			if(mp->abort)	/* use reserved flush msg */
				mp = &((User*)(u->p->upage->pa|KZERO))->fhot;
			qlock(hp);
			mp->cmd = WRITE;
			mp->param[0] = MP2VME(buf);
			mp->param[1] = n;
			mp->param[2] = hotsum(buf, n, ENABCKSUM);
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot);
			hotsend(hp, mp);
			qunlock(hp);
		}else{
			/*
			 *  use hotrod buffer.  lock the buffer until the reply
			 * use hotrod buffer.  lock the buffer until the reply
			 */
			mp = &u->uhot;
			mp = &((User*)(u->p->upage->pa|KZERO))->uhot;
			qlock(&hp->buflock);
			qlock(hp);
			memcpy(hp->buf, buf, n);


@@ 378,7 396,7 @@ hotrodwrite(Chan *c, void *buf, long n)
			mp->param[0] = MP2VME(hp->buf);
			mp->param[1] = n;
			mp->param[2] = hotsum((ulong*)hp->buf, n, ENABCKSUM);
			hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->uhot);
			hotsend(hp, mp);
			qunlock(hp);
			qunlock(&hp->buflock);
		}


@@ 404,17 422,27 @@ hotrodwstat(Chan *c, char *dp)
void
hotrodintr(int vec)
{
	Hotrod *hp;
	Hotrod *h;
	Hotmsg *hm;

/*	print("hotrod%d interrupt\n", vec - Vmevec); /**/
	hp = &hotrod[vec - Vmevec];
	if(hp < hotrod || hp > &hotrod[Nhotrod]){
	h = &hotrod[vec - Vmevec];
	if(h < hotrod || h > &hotrod[Nhotrod]){
		print("bad hotrod vec\n");
		return;
	}
	hp->addr->lcsr3 &= ~INT_VME;
	h->addr->lcsr3 &= ~INT_VME;
	hm = (Hotmsg*)VME2MP(h->rq[h->ri]);
	h->rq[h->ri] = 0;
	h->ri++;
	if(h->ri >= NRQ)
		h->ri = 0;
	hm->intr = 1;
	if(hm->abort)
		return;
	wakeup(&hm->r);
}

#ifdef	ENABMEMTEST
void
mem(Hot *hot, ulong *buf, ulong size)
{


@@ 504,3 532,4 @@ part4:
		}
	}
}
#endif

M power/io.h => power/io.h +2 -1
@@ 74,11 74,12 @@ struct MODE {
/*
 * VME addressing.
 * MP2VME takes a physical MP bus address and returns an address
 * usable by a VME device through A32 space
 * usable by a VME device through A32 space.  VME2MP is its inverse
 */
#define	MASTER	0x0
#define	SLAVE	0x4
#define	MP2VME(addr)	(((ulong)(addr) & 0x0fffffff) | (SLAVE<<28))
#define	VME2MP(addr)	(((ulong)(addr) & 0x0fffffff) | KZERO)


struct INTVEC {