plan 9 kernel history: overview | file list | diff list

1991/0227/power/devhotrod.c (diff list | history)

power/devhotrod.c on 1990/1013
1990/1013    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
#include	"devtab.h" 
1991/0212    
#include	"fcall.h" 
1990/1013    
 
#include	"io.h" 
1991/0215    
#include	"hrod.h" 
1990/1013    
 
typedef struct Hotrod	Hotrod; 
1991/0209    
typedef struct HotQ	HotQ; 
1990/1013    
 
enum { 
	Vmevec=		0xd2,		/* vme vector for interrupts */ 
	Intlevel=	5,		/* level to interrupt on */ 
1991/0209    
	Qdir=		0,		/* Qid's */ 
	Qhotrod=	1, 
1991/0215    
	NhotQ=		NRQ,		/* size of communication queues */ 
1991/0209    
	Nhotrod=	1, 
1990/1013    
}; 
 
1991/0209    
struct HotQ{ 
	ulong	i;			/* index into queue */ 
	Hotmsg	*msg[NhotQ];		/* pointer to command buffer */ 
	ulong	pad[3];			/* unused; for hotrod prints */ 
}; 
1990/1013    
 
1991/0209    
 
struct Hotrod{ 
	QLock; 
1991/0212    
	QLock		buflock; 
1991/0209    
	Lock		busy; 
1991/0215    
	Hot		*addr;		/* address of the device */ 
1990/1106    
	int		vec;		/* vme interrupt vector */ 
1991/0209    
	HotQ		*wq;		/* write this queue to send cmds */ 
	int		wi;		/* where to write next cmd */ 
	HotQ		rq;		/* read this queue to receive replies */ 
	int		ri;		/* where to read next response */ 
1990/1106    
	Rendez		r; 
1991/0220    
	uchar		buf[MAXFDATA+MAXMSG]; 
1990/1013    
}; 
 
Hotrod hotrod[Nhotrod]; 
 
1990/1106    
void	hotrodintr(int); 
1990/1013    
 
1991/0215    
#define	HOTROD	VMEA24SUP(Hot, 0xB00000); 
 
1991/0209    
/* 
 * Commands 
 */ 
enum{ 
	RESET=	0,	/* params: Q address, length of queue */ 
	REBOOT=	1,	/* params: none */ 
1991/0212    
	READ=	2,	/* params: buffer, count, returned count */ 
	WRITE=	3,	/* params: buffer, count */ 
1991/0214    
	TEST=	7,	/* params: none */ 
1991/0209    
}; 
 
void 
hotsend(Hotrod *h, Hotmsg *m) 
1990/1013    
{ 
1991/0220    
/* print("hotsend send %d %d %lux %lux\n", h->wi, m->cmd, m, m->param[0]); /**/ 
1991/0212    
	h->wq->msg[h->wi] = (Hotmsg*)MP2VME(m); 
1991/0215    
	do 
		delay(1); 
	while(h->wq->msg[h->wi]); 
1991/0220    
/* print("hotsend done\n"); /**/ 
1991/0209    
	h->wi++; 
	if(h->wi >= NhotQ) 
		h->wi = 0; 
1990/1013    
} 
 
/* 
 *  reset all hotrod boards 
 */ 
void 
hotrodreset(void) 
{ 
	int i; 
1990/1018    
	Hotrod *hp; 
1990/1013    
 
1991/0209    
	for(hp=hotrod,i=0; i<Nhotrod; i++,hp++){ 
		hp->addr = HOTROD+i; 
		/* 
		 * Write queue is at end of hotrod memory 
		 */ 
1991/0215    
		hp->wq = (HotQ*)(&hp->addr->hostrp); 
1991/0209    
		hp->vec = Vmevec+i; 
		setvmevec(hp->vec, hotrodintr); 
1990/1013    
	}	 
	wbflush(); 
	delay(20); 
} 
 
void 
hotrodinit(void) 
{ 
} 
 
/* 
 *  enable the device for interrupts, spec is the device number 
 */ 
Chan* 
hotrodattach(char *spec) 
{ 
1990/1106    
	Hotrod *hp; 
1990/1013    
	int i; 
	Chan *c; 
 
	i = strtoul(spec, 0, 0); 
	if(i >= Nhotrod) 
1990/11211    
		error(Ebadarg); 
1990/1013    
 
	c = devattach('H', spec); 
	c->dev = i; 
1990/11211    
	c->qid.path = CHDIR; 
	c->qid.vers = 0; 
1990/1013    
	return c; 
} 
 
Chan* 
hotrodclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int	  
hotrodwalk(Chan *c, char *name) 
{ 
1991/0209    
	if(c->qid.path != CHDIR) 
		return 0; 
	if(strncmp(name, "hotrod", 6) == 0){ 
		c->qid.path = Qhotrod; 
		return 1; 
	} 
	return 0; 
1990/1013    
} 
 
void	  
hotrodstat(Chan *c, char *dp) 
{ 
1991/0209    
	print("hotrodstat\n"); 
	error(Egreg); 
1990/1013    
} 
 
1991/0227    
#define	NTESTBUF	256 
ulong	testbuf[NTESTBUF]; 
 
1990/1013    
Chan* 
hotrodopen(Chan *c, int omode) 
{ 
1990/1106    
	Hotrod *hp; 
1991/0212    
	Hotmsg *mp; 
1990/1106    
 
1990/11211    
	if(c->qid.path == CHDIR){ 
1990/1013    
		if(omode != OREAD) 
1990/11211    
			error(Eperm); 
1991/0209    
	}else if(c->qid.path == Qhotrod){ 
		hp = &hotrod[c->dev]; 
		if(!canlock(&hp->busy)) 
			error(Einuse); 
		/* 
		 * Clear communications region 
		 */ 
		memset(hp->wq->msg, 0, sizeof(hp->wq->msg)); 
		hp->wq->i = 0; 
 
		/* 
		 * Issue reset 
		 */ 
		hp->wi = 0; 
		hp->ri = 0; 
1991/0212    
		mp = &u->khot; 
		mp->cmd = RESET; 
		mp->param[0] = MP2VME(&hp->rq); 
		mp->param[1] = NhotQ; 
1991/0209    
		hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot); 
1991/0215    
		delay(100); 
1991/0214    
		print("reset\n"); 
1991/0219    
 
		/* 
		 * Issue test 
		 */ 
		mp = &u->khot; 
		mp->cmd = TEST; 
1991/0227    
		mp->param[0] = MP2VME(testbuf); 
		mp->param[1] = NTESTBUF; 
1991/0219    
		hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot); 
		delay(100); 
		print("tested\n"); 
1990/1018    
	} 
1990/1013    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
 
void	  
hotrodcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1990/11211    
	error(Eperm); 
1990/1013    
} 
 
void	  
hotrodclose(Chan *c) 
{ 
1991/0209    
	Hotrod *hp; 
 
	hp = &hotrod[c->dev]; 
	if(c->qid.path != CHDIR){ 
		u->khot.cmd = REBOOT; 
		hotsend(hp, &((User*)(u->p->upage->pa|KZERO))->khot); 
		unlock(&hp->busy); 
	} 
1990/1013    
} 
 
/* 
1991/0212    
 * 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. 
1990/1013    
 */ 
1991/0212    
 
1990/1013    
long	  
hotrodread(Chan *c, void *buf, long n) 
{ 
	Hotrod *hp; 
1991/0212    
	Hotmsg *mp; 
1991/0215    
	ulong l; 
1990/1013    
 
	hp = &hotrod[c->dev]; 
1991/0212    
	switch(c->qid.path){ 
	case Qhotrod: 
1991/0220    
		if(n > sizeof hp->buf){ 
			print("hotrod bufsize\n"); 
1991/0212    
			error(Egreg); 
1991/0220    
		} 
1991/0212    
		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); 
1991/0220    
			l = 100*1000*1000; 
1991/0212    
			do 
				n = mp->param[2]; 
1991/0215    
			while(n==0 && --l>0); 
			if(n == 0){ 
				print("devhotrod: give up\n"); 
				error(Egreg); 
			} 
1991/0212    
		}else{ 
			/* 
1991/0215    
			 *  use hotrod buffer.  lock the buffer until the reply 
1991/0212    
			 */ 
			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); 
1991/0215    
			l = 100*1000*1000; 
1991/0212    
			do 
				n = mp->param[2]; 
1991/0215    
			while(n==0 && --l>0); 
1991/0212    
			memcpy(buf, hp->buf, n); 
			qunlock(&hp->buflock); 
1991/0215    
			if(n == 0){ 
				print("devhotrod: give up\n"); 
				error(Egreg); 
			} 
1991/0212    
		} 
		return n; 
1990/1020    
	} 
1991/0220    
	print("hotrod read unk\n"); 
1991/0212    
	error(Egreg); 
	return 0; 
1990/1013    
} 
 
/* 
 *  write hotrod memory 
 */ 
long	  
hotrodwrite(Chan *c, void *buf, long n) 
{ 
	Hotrod *hp; 
1991/0212    
	Hotmsg *mp; 
1990/1013    
 
	hp = &hotrod[c->dev]; 
1991/0212    
	switch(c->qid.path){ 
	case 1: 
1991/0220    
		if(n > sizeof hp->buf){ 
			print("hotrod write bufsize\n"); 
1991/0212    
			error(Egreg); 
1991/0220    
		} 
1991/0212    
		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; 
	} 
1991/0220    
	print("hotrod write unk\n"); 
1991/0212    
	error(Egreg); 
	return 0; 
1990/1013    
} 
 
void	  
hotrodremove(Chan *c) 
{ 
1990/11211    
	error(Eperm); 
1990/1013    
} 
 
void	  
hotrodwstat(Chan *c, char *dp) 
{ 
1990/11211    
	error(Eperm); 
1990/1013    
} 
 
1990/1106    
void 
1990/1013    
hotrodintr(int vec) 
{ 
	Hotrod *hp; 
 
1991/0220    
/*	print("hotrod%d interrupt\n", vec - Vmevec); /**/ 
1990/1013    
	hp = &hotrod[vec - Vmevec]; 
	if(hp < hotrod || hp > &hotrod[Nhotrod]){ 
		print("bad hotrod vec\n"); 
		return; 
	} 
1991/0219    
	hp->addr->lcsr3 &= ~INT_VME; 
1990/1013    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)