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

power/devhs.c (diff list | history)

1990/0227/sys/src/9/power/devhs.c:8,251990/0312/sys/src/9/power/devhs.c:8,62 (short | long)
1990/0227    
 
#include	"io.h" 
 
1990/0312    
typedef struct Hsvme	Hsvme; 
typedef struct Device	Device; 
 
1990/0227    
enum { 
	Maxtxburst=	1024,		/* maximum transmit burst size */ 
1990/0312    
	Maxburst=	1023,		/* maximum transmit burst size */ 
1990/0227    
	Vmevec=		0xd0,		/* vme vector for interrupts */ 
	Intlevel=	5,		/* level to interrupt on */ 
1990/0312    
	Nhsvme=		1, 
1990/0227    
}; 
 
struct hsvmestats { 
	ulong	parity; 
	ulong	rintr; 
	ulong	tintr; 
} hsvmestats; 
1990/0312    
/* 
 *  hsvme datakit board 
 */ 
struct Device { 
	ushort	version; 
	ushort	pad0x02; 
	ushort	vector; 
	ushort	pad0x06; 
	ushort	csr; 
	ushort	pad0x0A; 
	ushort	data; 
}; 
#define HSVME		VMEA24SUP(Device, 0xF90000) 
1990/0227    
 
1990/0312    
struct Hsvme { 
	QLock; 
 
	QLock	xmit; 
	Device	*addr; 
	int	vec;		/* interupt vector */ 
	Rendez	r;		/* output process */ 
	Rendez	kr;		/* input kernel process */ 
	int	chan;		/* current input channel */ 
	Queue	*rq;		/* read queue */ 
	uchar	buf[1024];	/* bytes being collected */ 
	uchar	*wptr;		/* pointer into buf */ 
	int	kstarted;	/* true if kernel process started */ 
 
	/* statistics */ 
 
	ulong	parity;		/* parity errors */ 
	ulong	rintr;		/* rcv interrupts */ 
	ulong	tintr;		/* transmit interrupts */ 
	ulong	in;		/* bytes in */ 
	ulong	out;		/* bytes out */ 
}; 
 
Hsvme hsvme[Nhsvme]; 
 
1990/0227    
#define ALIVE		0x0001 
#define IENABLE		0x0004 
#define EXOFLOW		0x0008 
1990/0227/sys/src/9/power/devhs.c:42,621990/0312/sys/src/9/power/devhs.c:79,108
1990/0227    
#define TXEOD		0x0400 
#define NND		0x8000 
 
Rendez hsvmer; 
                 
#define DELAY(n)	{ \ 
	register int N = 12*(n); \ 
	while (--N > 0); \ 
	} 
                 
static void hsvmeintr(int); 
1990/0312    
static void hsvmekproc(void*); 
1990/0227    
 
1990/0312    
/* 
 *  hsvme stream module definition 
 */ 
static void hsvmeoput(Queue*, Block*); 
static void hsvmestopen(Queue*, Stream*); 
static void hsvmestclose(Queue*); 
Qinfo hsvmeinfo = { nullput, hsvmeoput, hsvmestopen, hsvmestclose, "hsvme" }; 
 
/* 
 *  restart a VME board 
 */ 
1990/0227    
void 
hsvmerestart(struct hsvme *addr) 
1990/0312    
hsvmerestart(Hsvme *hp) 
1990/0227    
{ 
1990/0312    
	Device *addr; 
 
	addr = hp->addr; 
 
1990/0227    
	addr->csr = RESET; 
	wbflush(); 
	DELAY(20000); 
1990/0312    
	delay(20); 
1990/0227    
 
	/* 
	 *  set interrupt vector 
1990/0227/sys/src/9/power/devhs.c:64,921990/0312/sys/src/9/power/devhs.c:110,141
1990/0227    
	 *  set forcew to a known value 
	 *  interrupt on level `Intlevel' 
	 */ 
	addr->vector = 0xd0; 
1990/0312    
	addr->vector = hp->vec; 
1990/0227    
	addr->csr = NORESET|IPL(Intlevel)|IENABLE|ALIVE; 
	wbflush(); 
	DELAY(500); 
1990/0312    
	delay(1); 
1990/0227    
	addr->csr = NORESET|IPL(Intlevel)|FORCEW|IENABLE|ALIVE; 
	wbflush(); 
	DELAY(500); 
1990/0312    
	delay(1); 
1990/0227    
} 
 
1990/0312    
/* 
 *  reset all vme boards 
 */ 
1990/0227    
void 
hsvmereset(void) 
{ 
	struct hsvme *addr; 
1990/0312    
	int i; 
	Hsvme *hp; 
1990/0227    
 
	addr = HSVME; 
	addr->csr = RESET; 
1990/0312    
	for(i=0; i<Nhsvme; i++){ 
		hsvme[i].addr = HSVME+i; 
		hsvme[i].vec = Vmevec+i; 
		hsvme[i].addr->csr = RESET; 
		setvmevec(hsvme[i].vec, hsvmeintr); 
	}	 
1990/0227    
	wbflush(); 
	DELAY(20000); 
                 
	/* 
	 *  routine to call on interrupt 
	 */ 
	setvmevec(Vmevec, hsvmeintr); 
1990/0312    
	delay(20); 
1990/0227    
} 
 
void 
1990/0227/sys/src/9/power/devhs.c:95,1171990/0312/sys/src/9/power/devhs.c:144,169
1990/0227    
} 
 
/* 
 *  enable the device for interrupts 
1990/0312    
 *  enable the device for interrupts, spec is the device number 
1990/0227    
 */ 
static int 
never(void *arg) 
{ 
	return 0; 
} 
Chan* 
hsvmeattach(char *spec) 
{ 
	struct hsvme *addr; 
1990/0312    
	Hsvme *hp; 
	int i; 
	Chan *c; 
1990/0227    
 
	addr = HSVME; 
	hsvmerestart(addr); 
	print("hsvme csr %ux\n", addr->csr); 
1990/0312    
	i = strtoul(spec, 0, 0); 
	if(i >= Nhsvme) 
		error(0, Ebadarg); 
	hp = &hsvme[i]; 
	hsvmerestart(hp); 
	print("hsvme [%d] csr %ux\n", i, hp->addr->csr); 
1990/0227    
 
	return devattach('h', spec); 
1990/0312    
	c = devattach('h', spec); 
	c->dev = i; 
	c->qid = CHDIR; 
	return c; 
1990/0227    
} 
 
Chan* 
1990/0227/sys/src/9/power/devhs.c:123,1471990/0312/sys/src/9/power/devhs.c:175,197
1990/0227    
int	  
hsvmewalk(Chan *c, char *name) 
{ 
	if(c->qid != CHDIR) 
		return 0; 
	if(strcmp(name, "hsvme") == 0){ 
		c->qid = 1; 
		return 1; 
	} 
	return 0; 
1990/0312    
	return devwalk(c, name, 0, 0, streamgen); 
1990/0227    
} 
 
void	  
hsvmestat(Chan *c, char *dp) 
{ 
	print("hsvmestat\n"); 
	error(0, Egreg); 
1990/0312    
	devstat(c, dp, 0, 0, streamgen); 
1990/0227    
} 
 
Chan* 
hsvmeopen(Chan *c, int omode) 
{ 
1990/0312    
	if(c->qid == CHDIR){ 
		if(omode != OREAD) 
			error(0, Eperm); 
	}else 
		streamopen(c, &hsvmeinfo); 
1990/0227    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
1990/0227/sys/src/9/power/devhs.c:157,1761990/0312/sys/src/9/power/devhs.c:207,226
1990/0227    
void	  
hsvmeclose(Chan *c) 
{ 
1990/0312    
	if(c->qid != CHDIR) 
		streamclose(c); 
1990/0227    
} 
 
long	  
hsvmeread(Chan *c, void *buf, long n) 
{ 
	error(0, Egreg); 
	return 0; 
1990/0312    
	return streamread(c, buf, n); 
1990/0227    
} 
 
long	  
hsvmewrite(Chan *c, void *buf, long n) 
{ 
	error(0, Egreg); 
	return 0; 
1990/0312    
	return streamwrite(c, buf, n, 0); 
1990/0227    
} 
 
void	  
1990/0227/sys/src/9/power/devhs.c:197,2271990/0312/sys/src/9/power/devhs.c:247,562
1990/0227    
	rooterrstr(e, buf); 
} 
 
1990/0312    
/* 
 *	the stream routines 
 */ 
 
/* 
 *  create the kernel process for input 
 */ 
1990/0227    
static void 
hsvmeintr(int vec) 
1990/0312    
hsvmestopen(Queue *q, Stream *s) 
1990/0227    
{ 
	ushort csr; 
	struct hsvme *addr; 
1990/0312    
	Hsvme *hp; 
	char name[32]; 
1990/0227    
 
	print("hsvme intr\n"); 
	addr = HSVME; 
	wbflush(); 
	csr = addr->csr; 
	do { 
		if (addr->csr & REF) { 
			hsvmestats.rintr++; 
			print("hsvme rintr\n"); 
1990/0312    
	hp = &hsvme[s->dev]; 
	sprint(name, "**hsvme%d**", s->dev); 
	q->ptr = q->other->ptr = hp; 
	hp->rq = q; 
	kproc(name, hsvmekproc, hp); 
} 
 
/* 
 *  kill off the kernel process 
 */ 
static int 
kdead(void *arg) 
{ 
	Hsvme *hp; 
 
	hp = (Hsvme *)arg; 
	return hp->kstarted == 0; 
} 
static void 
hsvmestclose(Queue * q) 
{ 
	Hsvme *hp; 
 
	hp = (Hsvme *)q->ptr; 
	qlock(hp); 
	hp->rq = 0; 
	qunlock(hp); 
	wakeup(&hp->kr); 
	sleep(&hp->r, kdead, hp); 
} 
 
/* 
 *  free all blocks of a message in `q', `bp' is the first block 
 *  of the message 
 */ 
static void 
freemsg(Queue *q, Block *bp) 
{ 
	for(; bp; bp = getq(q)){ 
		if(bp->flags & S_DELIM){ 
			freeb(bp); 
			return; 
1990/0227    
		} 
		if (addr->csr & XHF) { 
			hsvmestats.tintr++; 
			print("hsvme tintr\n"); 
1990/0312    
		freeb(bp); 
	} 
} 
 
/* 
 *  return true if the output fifo is at least half empty. 
 *  the implication is that it can take at least another 1000 byte burst. 
 */ 
static int 
halfempty(void *arg) 
{ 
	Device *addr; 
 
	addr = (Device*)arg; 
	return addr->csr & XHF; 
} 
 
/* 
 *  output a block 
 * 
 *  the first 2 bytes of every message are the channel number, 
 *  low order byte first.  the third is a possible trailing control 
 *  character. 
 */ 
void 
hsvmeoput(Queue *q, Block *bp) 
{ 
	Device *addr; 
	Hsvme *hp; 
	int burst; 
	int chan; 
	int ctl; 
	int n; 
 
	if(bp->type != M_DATA){ 
		freeb(bp); 
		return; 
	} 
 
	/* 
	 *  get a whole message before handing bytes to the device 
	 */ 
	if(!putq(q, bp)) 
		return; 
 
	/* 
	 *  one transmitter at a time 
	 */ 
	hp = (Hsvme *)q->ptr; 
	qlock(&hp->xmit); 
	addr = hp->addr; 
 
	/* 
	 *  parse message 
	 */ 
	bp = getq(q); 
	if(bp->wptr - bp->rptr < 3){ 
		freemsg(q, bp); 
		qunlock(&hp->xmit); 
		return; 
	} 
	chan = CHNO | *bp->rptr++ | (*bp->rptr++<<8); 
	ctl = *bp->rptr++; 
 
	/* 
	 *  send the 8 bit data, burst are up to Maxburst (9-bit) bytes long 
	 */ 
	if(!(addr->csr & XHF)) 
		sleep(&hp->r, halfempty, addr); 
/*	print("->%.2uo\n", CHNO|chan);/**/ 
	addr->data = CHNO|chan; 
	burst = Maxburst; 
	while(bp){ 
		if(burst == 0){ 
			addr->data = TXEOD; 
/*			print("->%.2uo\n", TXEOD); /**/ 
			if(!(addr->csr & XHF)) 
				sleep(&hp->r, halfempty, addr); 
/*			print("->%.2uo\n", CHNO|chan); /**/ 
			addr->data = CHNO|chan; 
			burst = Maxburst; 
1990/0227    
		} 
		if ((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)) { 
			hsvmestats.parity++; 
			hsvmerestart(addr); 
			print("hsvme %ux: reset, csr = 0x%x\n", 
				HSVME, csr); 
1990/0312    
		n = bp->wptr - bp->rptr; 
		if(n > burst) 
			n = burst; 
		burst -= n; 
		while(n--){ 
/*			print("->%.2uo\n", *bp->rptr); /**/ 
			addr->data = *bp->rptr++; 
1990/0227    
		} 
		wbflush(); 
	} while ((csr = addr->csr) & REF); 
1990/0312    
		if(bp->rptr >= bp->wptr){ 
			if(bp->flags & S_DELIM){ 
				freeb(bp); 
				break; 
			} 
			freeb(bp); 
			bp = getq(q); 
		} 
	} 
 
	/* 
	 *  send the control byte if there is one 
	 */ 
	if(ctl){ 
/*		print("->%.2uo\n", CTL|ctl); /**/ 
		addr->data = CTL|ctl; 
	} 
 
	/* 
	 *  start the fifo emptying 
	 */ 
/*	print("->%.2uo\n", TXEOD); /**/ 
	addr->data = TXEOD; 
 
	qunlock(&hp->xmit); 
} 
 
/* 
 *  return true if the input fifo is non-empty 
 */ 
static int 
notempty(void *arg) 
{ 
	Device *addr; 
 
	addr = (Device *)arg; 
	return addr->csr & REF; 
} 
 
/* 
 *  fill a block with what is currently buffered and send it upstream 
 */ 
static void 
upstream(Hsvme *hp, unsigned int ctl) 
{ 
	int n; 
	Block *bp; 
 
	n = hp->wptr - hp->buf; 
	bp = allocb(3 + n); 
	bp->wptr[0] = hp->chan; 
	bp->wptr[1] = hp->chan>>8; 
	bp->wptr[2] = ctl; 
	if(n) 
		memcpy(&bp->wptr[3], hp->buf, n); 
	bp->wptr += 3 + n; 
	bp->flags |= S_DELIM; 
	PUTNEXT(hp->rq, bp); 
	hp->wptr = hp->buf; 
} 
 
/* 
 *  Read bytes from the input fifo.  Since we take an interrupt every 
 *  time the fifo goes non-empty, we need to waste time to let the 
 *  fifo fill up. 
 */ 
static void 
hsvmekproc(void *arg) 
{ 
	Hsvme *hp; 
	Device *addr; 
	unsigned int c; 
 
	hp = (Hsvme *)arg; 
	addr = hp->addr; 
	hp->kstarted = 1; 
	hp->wptr = hp->buf; 
 
	for(;;){ 
		/* 
		 *  die if the device is closed 
		 */ 
		qlock(hp); 
		if(hp->rq == 0){ 
			qunlock(hp); 
			hp->kstarted = 0; 
			wakeup(&hp->r); 
			return; 
		} 
 
		/* 
		 *  let the fifo fill a bit 
		 */ 
		delay(1); 
 
		/* 
		 *  0xFFFF means an empty fifo 
		 */ 
		while ((c = addr->data) != 0xFFFF) { 
/*			print(" %.2uo<-\n", c); /**/ 
			if(c & CHNO){ 
				c &= 0x1FF; 
				if(hp->chan == c) 
					continue; 
				/* 
				 *  new channel, put anything saved upstream 
				 */ 
				if(hp->wptr - hp->buf != 0) 
					upstream(hp, 0); 
				hp->chan = c; 
			} else if(c & NND){ 
				/* 
				 *  ctl byte, this ends a message 
				 */ 
				upstream(hp, c); 
			} else { 
				/* 
				 *  data byte, put in local buffer 
				 */ 
				*hp->wptr++ = c; 
				if(hp->wptr == &hp->buf[sizeof hp->buf]) 
					upstream(hp, 0); 
			} 
		} 
		qunlock(hp); 
 
		/* 
		 *  sleep if input fifo empty 
		 */ 
		if(!notempty(addr)) 
			sleep(&hp->kr, notempty, addr); 
	} 
} 
 
/* 
 *  only one flavor interrupt.   we have to use the less than half full 
 *  and not empty bits to figure out whom to wake. 
 */ 
static void 
hsvmeintr(int vec) 
{ 
	ushort csr; 
	Device *addr; 
	Hsvme *hp; 
 
	hp = &hsvme[vec - Vmevec]; 
	if(hp < hsvme || hp > &hsvme[Nhsvme]){ 
		print("bad hsvme vec\n"); 
		return; 
	} 
	csr = hp->addr->csr; 
 
	if (csr & REF) { 
		hp->rintr++; 
		wakeup(&hp->kr); 
	} 
	if (csr & XHF) { 
		hp->tintr++; 
		wakeup(&hp->r); 
	} 
	if ((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)) { 
		hp->parity++; 
		hsvmerestart(hp); 
		print("hsvme %d: reset, csr = 0x%ux\n", 
			HSVME, csr); 
	} 
1990/0227    
} 
1990/0312/sys/src/9/power/devhs.c:364,3711990/0315/sys/src/9/power/devhs.c:364,372 (short | long)
1990/0312    
		qunlock(&hp->xmit); 
		return; 
	} 
	chan = CHNO | *bp->rptr++ | (*bp->rptr++<<8); 
	ctl = *bp->rptr++; 
1990/0315    
	chan = CHNO | bp->rptr[0] | (bp->rptr[1]<<8); 
	ctl = bp->rptr[2]; 
	bp->rptr += 3; 
1990/0312    
 
	/* 
	 *  send the 8 bit data, burst are up to Maxburst (9-bit) bytes long 
1990/0315/sys/src/9/power/devhs.c:158,1641990/0403/sys/src/9/power/devhs.c:158,163 (short | long)
1990/0312    
		error(0, Ebadarg); 
	hp = &hsvme[i]; 
	hsvmerestart(hp); 
	print("hsvme [%d] csr %ux\n", i, hp->addr->csr); 
1990/0227    
 
1990/0312    
	c = devattach('h', spec); 
	c->dev = i; 
1990/0315/sys/src/9/power/devhs.c:466,4711990/0403/sys/src/9/power/devhs.c:465,471
1990/0312    
	Hsvme *hp; 
	Device *addr; 
	unsigned int c; 
1990/0403    
	int miss; 
1990/0312    
 
	hp = (Hsvme *)arg; 
	addr = hp->addr; 
1990/0315/sys/src/9/power/devhs.c:485,4991990/0403/sys/src/9/power/devhs.c:485,498
1990/0312    
		} 
 
		/* 
		 *  let the fifo fill a bit 
1990/0403    
		 *  if we loop many times without finding a character, sleep 
1990/0312    
		 */ 
		delay(1); 
                 
1990/0403    
		for(miss = 0; miss < 10; miss++){ 
1990/0312    
		/* 
		 *  0xFFFF means an empty fifo 
		 */ 
		while ((c = addr->data) != 0xFFFF) { 
/*			print(" %.2uo<-\n", c); /**/ 
1990/0403    
			miss = 0; 
1990/0312    
			if(c & CHNO){ 
				c &= 0x1FF; 
				if(hp->chan == c) 
1990/0315/sys/src/9/power/devhs.c:517,5221990/0403/sys/src/9/power/devhs.c:516,522
1990/0312    
				if(hp->wptr == &hp->buf[sizeof hp->buf]) 
					upstream(hp, 0); 
			} 
1990/0403    
		} 
1990/0312    
		} 
		qunlock(hp); 
 
1990/0403/sys/src/9/power/devhs.c:260,2661990/0722/sys/src/9/power/devhs.c:260,266 (short | long)
1990/0312    
	char name[32]; 
1990/0227    
 
1990/0312    
	hp = &hsvme[s->dev]; 
	sprint(name, "**hsvme%d**", s->dev); 
1990/0722    
	sprint(name, "hsvme%d", s->dev); 
1990/0312    
	q->ptr = q->other->ptr = hp; 
	hp->rq = q; 
	kproc(name, hsvmekproc, hp); 
1990/0722/sys/src/9/power/devhs.c:485,4941990/0816/sys/src/9/power/devhs.c:485,490 (short | long)
1990/0312    
		} 
 
		/* 
1990/0403    
		 *  if we loop many times without finding a character, sleep 
1990/0312    
		 */ 
1990/0403    
		for(miss = 0; miss < 10; miss++){ 
1990/0312    
		/* 
		 *  0xFFFF means an empty fifo 
		 */ 
		while ((c = addr->data) != 0xFFFF) { 
1990/0722/sys/src/9/power/devhs.c:516,5221990/0816/sys/src/9/power/devhs.c:512,517
1990/0312    
				if(hp->wptr == &hp->buf[sizeof hp->buf]) 
					upstream(hp, 0); 
			} 
1990/0403    
		} 
1990/0312    
		} 
		qunlock(hp); 
 
1990/0816/sys/src/9/power/devhs.c:488,4931990/0826/sys/src/9/power/devhs.c:488,494 (short | long)
1990/0312    
		 *  0xFFFF means an empty fifo 
		 */ 
		while ((c = addr->data) != 0xFFFF) { 
1990/0826    
			hp->in++; 
1990/0403    
			miss = 0; 
1990/0312    
			if(c & CHNO){ 
				c &= 0x1FF; 
1990/0826/sys/src/9/power/devhs.c:554,5591990/0930/sys/src/9/power/devhs.c:554,559 (short | long)
1990/0312    
		hp->parity++; 
		hsvmerestart(hp); 
		print("hsvme %d: reset, csr = 0x%ux\n", 
			HSVME, csr); 
1990/0930    
			vec - Vmevec, csr); 
1990/0312    
	} 
1990/0227    
} 
1990/0930/sys/src/9/power/devhs.c:466,4711990/1101/sys/src/9/power/devhs.c:466,472 (short | long)
1990/0312    
	Device *addr; 
	unsigned int c; 
1990/0403    
	int miss; 
1990/1101    
	int locked; 
1990/0312    
 
	hp = (Hsvme *)arg; 
	addr = hp->addr; 
1990/0930/sys/src/9/power/devhs.c:472,4821990/1101/sys/src/9/power/devhs.c:473,493
1990/0312    
	hp->kstarted = 1; 
	hp->wptr = hp->buf; 
 
1990/1101    
	locked = 0; 
	if(waserror()){ 
		if(locked) 
			qunlock(hp); 
		hp->kstarted = 0; 
		wakeup(&hp->r); 
		return; 
	} 
 
1990/0312    
	for(;;){ 
		/* 
		 *  die if the device is closed 
		 */ 
		qlock(hp); 
1990/1101    
		locked = 1; 
1990/0312    
		if(hp->rq == 0){ 
			qunlock(hp); 
			hp->kstarted = 0; 
1990/0930/sys/src/9/power/devhs.c:515,5201990/1101/sys/src/9/power/devhs.c:526,532
1990/0312    
			} 
		} 
		qunlock(hp); 
1990/1101    
		locked = 0; 
1990/0312    
 
		/* 
		 *  sleep if input fifo empty 
1990/1101/sys/src/9/power/devhs.c:88,941990/11151/sys/src/9/power/devhs.c:88,101 (short | long)
1990/0312    
static void hsvmeoput(Queue*, Block*); 
static void hsvmestopen(Queue*, Stream*); 
static void hsvmestclose(Queue*); 
Qinfo hsvmeinfo = { nullput, hsvmeoput, hsvmestopen, hsvmestclose, "hsvme" }; 
1990/11151    
Qinfo hsvmeinfo = 
{ 
	nullput, 
	hsvmeoput, 
	hsvmestopen, 
	hsvmestclose, 
	"hsvme" 
}; 
1990/0312    
 
/* 
 *  restart a VME board 
1990/11151/sys/src/9/power/devhs.c:162,1741990/11211/sys/src/9/power/devhs.c:162,174 (short | long)
1990/0227    
 
1990/0312    
	i = strtoul(spec, 0, 0); 
	if(i >= Nhsvme) 
		error(0, Ebadarg); 
1990/11211    
		error(Ebadarg); 
1990/0312    
	hp = &hsvme[i]; 
	hsvmerestart(hp); 
1990/0227    
 
1990/0312    
	c = devattach('h', spec); 
	c->dev = i; 
	c->qid = CHDIR; 
1990/11211    
	c->qid.path = CHDIR; 
1990/0312    
	return c; 
1990/0227    
} 
 
1990/11151/sys/src/9/power/devhs.c:193,2011990/11211/sys/src/9/power/devhs.c:193,201
1990/0227    
Chan* 
hsvmeopen(Chan *c, int omode) 
{ 
1990/0312    
	if(c->qid == CHDIR){ 
1990/11211    
	if(c->qid.path == CHDIR){ 
1990/0312    
		if(omode != OREAD) 
			error(0, Eperm); 
1990/11211    
			error(Eperm); 
1990/0312    
	}else 
		streamopen(c, &hsvmeinfo); 
1990/0227    
	c->mode = openmode(omode); 
1990/11151/sys/src/9/power/devhs.c:207,2191990/11211/sys/src/9/power/devhs.c:207,219
1990/0227    
void	  
hsvmecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	error(0, Eperm); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void	  
hsvmeclose(Chan *c) 
{ 
1990/0312    
	if(c->qid != CHDIR) 
1990/11211    
	if(c->qid.path != CHDIR) 
1990/0312    
		streamclose(c); 
1990/0227    
} 
 
1990/11151/sys/src/9/power/devhs.c:232,2561990/11211/sys/src/9/power/devhs.c:232,244
1990/0227    
void	  
hsvmeremove(Chan *c) 
{ 
	error(0, Eperm); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void	  
hsvmewstat(Chan *c, char *dp) 
{ 
	error(0, Eperm); 
} 
                 
void 
hsvmeuserstr(Error *e, char *buf) 
{ 
	consuserstr(e, buf); 
} 
                 
void	  
hsvmeerrstr(Error *e, char *buf) 
{ 
	rooterrstr(e, buf); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1990/0312    
/* 
1990/11211/sys/src/9/power/devhs.c:460,4661990/1214/sys/src/9/power/devhs.c:460,465 (short | long)
1990/0312    
	Hsvme *hp; 
	Device *addr; 
	unsigned int c; 
1990/0403    
	int miss; 
1990/1101    
	int locked; 
1990/0312    
 
	hp = (Hsvme *)arg; 
1990/11211/sys/src/9/power/devhs.c:481,4861990/1214/sys/src/9/power/devhs.c:480,486
1990/0312    
		/* 
		 *  die if the device is closed 
		 */ 
1990/1214    
		USED(locked);		/* so locked = 0 and locked = 1 stay */ 
1990/0312    
		qlock(hp); 
1990/1101    
		locked = 1; 
1990/0312    
		if(hp->rq == 0){ 
1990/11211/sys/src/9/power/devhs.c:487,4921990/1214/sys/src/9/power/devhs.c:487,493
1990/0312    
			qunlock(hp); 
			hp->kstarted = 0; 
			wakeup(&hp->r); 
1990/1214    
			poperror(); 
1990/0312    
			return; 
		} 
 
1990/11211/sys/src/9/power/devhs.c:495,5011990/1214/sys/src/9/power/devhs.c:496,501
1990/0312    
		 */ 
		while ((c = addr->data) != 0xFFFF) { 
1990/0826    
			hp->in++; 
1990/0403    
			miss = 0; 
1990/0312    
			if(c & CHNO){ 
				c &= 0x1FF; 
				if(hp->chan == c) 
1990/11211/sys/src/9/power/devhs.c:520,5251990/1214/sys/src/9/power/devhs.c:520,526
1990/0312    
					upstream(hp, 0); 
			} 
		} 
1990/1214    
		USED(locked); 
1990/0312    
		qunlock(hp); 
1990/1101    
		locked = 0; 
1990/0312    
 
1990/1214/sys/src/9/power/devhs.c:442,4481991/0318/sys/src/9/power/devhs.c:442,448 (short | long)
1990/0312    
	bp->wptr[1] = hp->chan>>8; 
	bp->wptr[2] = ctl; 
	if(n) 
		memcpy(&bp->wptr[3], hp->buf, n); 
1991/0318    
		memmove(&bp->wptr[3], hp->buf, n); 
1990/0312    
	bp->wptr += 3 + n; 
	bp->flags |= S_DELIM; 
	PUTNEXT(hp->rq, bp); 
1991/0318/sys/src/9/power/devhs.c:218,2301991/0411/sys/src/9/power/devhs.c:218,230 (short | long)
1990/0227    
} 
 
long	  
hsvmeread(Chan *c, void *buf, long n) 
1991/0411    
hsvmeread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1990/0312    
	return streamread(c, buf, n); 
1990/0227    
} 
 
long	  
hsvmewrite(Chan *c, void *buf, long n) 
1991/0411    
hsvmewrite(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1990/0312    
	return streamwrite(c, buf, n, 0); 
1990/0227    
} 
1991/0411/sys/src/9/power/devhs.c:184,1891991/0419/sys/src/9/power/devhs.c:184,195 (short | long)
1990/0312    
	return devwalk(c, name, 0, 0, streamgen); 
1990/0227    
} 
 
1991/0419    
Chan* 
hsvmeclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
 
1990/0227    
void	  
hsvmestat(Chan *c, char *dp) 
{ 
1991/0419/sys/src/9/power/devhs.c:184,1951991/0427/sys/src/9/power/devhs.c:184,189 (short | long)
1990/0312    
	return devwalk(c, name, 0, 0, streamgen); 
1990/0227    
} 
 
1991/0419    
Chan* 
hsvmeclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
                 
1990/0227    
void	  
hsvmestat(Chan *c, char *dp) 
{ 
1991/0427/sys/src/9/power/devhs.c:45,501991/0921/sys/src/9/power/devhs.c:45,51 (short | long)
1990/0312    
	uchar	buf[1024];	/* bytes being collected */ 
	uchar	*wptr;		/* pointer into buf */ 
	int	kstarted;	/* true if kernel process started */ 
1991/0921    
	int	started; 
1990/0312    
 
	/* statistics */ 
 
1991/0427/sys/src/9/power/devhs.c:124,1291991/0921/sys/src/9/power/devhs.c:125,131
1990/0227    
	addr->csr = NORESET|IPL(Intlevel)|FORCEW|IENABLE|ALIVE; 
	wbflush(); 
1990/0312    
	delay(1); 
1991/0921    
	hp->started = 1; 
1990/0227    
} 
 
1990/0312    
/* 
1991/0427/sys/src/9/power/devhs.c:164,1701991/0921/sys/src/9/power/devhs.c:166,173
1990/0312    
	if(i >= Nhsvme) 
1990/11211    
		error(Ebadarg); 
1990/0312    
	hp = &hsvme[i]; 
	hsvmerestart(hp); 
1991/0921    
	if(!hp->started) 
		hsvmerestart(hp); 
1990/0227    
 
1990/0312    
	c = devattach('h', spec); 
	c->dev = i; 
1991/0921/sys/src/9/power/devhs.c:210,2151991/1214/sys/src/9/power/devhs.c:210,216 (short | long)
1990/0227    
void	  
hsvmecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1214    
	USED(c); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1991/0921/sys/src/9/power/devhs.c:235,2401991/1214/sys/src/9/power/devhs.c:236,242
1990/0227    
void	  
hsvmeremove(Chan *c) 
{ 
1991/1214    
	USED(c); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1991/0921/sys/src/9/power/devhs.c:241,2461991/1214/sys/src/9/power/devhs.c:243,249
1990/0227    
void	  
hsvmewstat(Chan *c, char *dp) 
{ 
1991/1214    
	USED(c); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1991/1214/sys/src/9/power/devhs.c:3,91992/0111/sys/src/9/power/devhs.c:3,9 (short | long)
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
#include	"devtab.h" 
 
#include	"io.h" 
1992/0111/sys/src/9/power/devhs.c:352,3571992/0117/sys/src/9/power/devhs.c:352,361 (short | long)
1990/0312    
	 *  one transmitter at a time 
	 */ 
	hp = (Hsvme *)q->ptr; 
1992/0117    
	if(waserror()){ 
		qunlock(&hp->xmit); 
		nexterror(); 
	} 
1990/0312    
	qlock(&hp->xmit); 
	addr = hp->addr; 
 
1992/0111/sys/src/9/power/devhs.c:419,4241992/0117/sys/src/9/power/devhs.c:423,429
1990/0312    
	addr->data = TXEOD; 
 
	qunlock(&hp->xmit); 
1992/0117    
	poperror(); 
1990/0312    
} 
 
/* 
1992/0117/sys/src/9/power/devhs.c:18,231992/0123/sys/src/9/power/devhs.c:18,25 (short | long)
1990/0312    
	Nhsvme=		1, 
1990/0227    
}; 
 
1992/0123    
#define NOW (MACHP(0)->ticks*MS2HZ) 
 
1990/0312    
/* 
 *  hsvme datakit board 
 */ 
1992/0117/sys/src/9/power/devhs.c:44,491992/0123/sys/src/9/power/devhs.c:46,52
1990/0312    
	Queue	*rq;		/* read queue */ 
	uchar	buf[1024];	/* bytes being collected */ 
	uchar	*wptr;		/* pointer into buf */ 
1992/0123    
	ulong	time;		/* time byte in buf[0] arrived */ 
1990/0312    
	int	kstarted;	/* true if kernel process started */ 
1991/0921    
	int	started; 
1990/0312    
 
1992/0117/sys/src/9/power/devhs.c:458,4631992/0123/sys/src/9/power/devhs.c:461,467
1990/0312    
	bp->flags |= S_DELIM; 
	PUTNEXT(hp->rq, bp); 
	hp->wptr = hp->buf; 
1992/0123    
	hp->time = 0; 
1990/0312    
} 
 
/* 
1992/0117/sys/src/9/power/devhs.c:526,5451992/0123/sys/src/9/power/devhs.c:530,558
1990/0312    
				/* 
				 *  data byte, put in local buffer 
				 */ 
1992/0123    
				if(hp->time == 0) 
					hp->time = NOW + 100; 
1990/0312    
				*hp->wptr++ = c; 
				if(hp->wptr == &hp->buf[sizeof hp->buf]) 
					upstream(hp, 0); 
			} 
		} 
1992/0123    
		if(hp->time && NOW >= hp->time) 
			upstream(hp, 0); 
1990/1214    
		USED(locked); 
1990/0312    
		qunlock(hp); 
1990/1101    
		locked = 0; 
1990/0312    
 
		/* 
		 *  sleep if input fifo empty 
1992/0123    
		 *  Sleep if input fifo empty. Make sure we don't hold onto 
		 *  any byte for more tha 1/10 second. 
1990/0312    
		 */ 
		if(!notempty(addr)) 
			sleep(&hp->kr, notempty, addr); 
1992/0123    
		if(!(addr->csr & REF)){ 
			if(hp->wptr == hp->buf) 
				sleep(&hp->kr, notempty, addr); 
			else 
				tsleep(&hp->kr, notempty, addr, 100); 
		} 
1990/0312    
	} 
} 
 
1992/0123/sys/src/9/power/devhs.c:1,51992/0321/sys/src/9/power/devhs.c:1,5 (short | long)
1990/0227    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/power/devhs.c:8,441992/0612/sys/src/9/power/devhs.c:8,60 (short | long)
1990/0227    
 
#include	"io.h" 
 
1990/0312    
typedef struct Hsvme	Hsvme; 
typedef struct Device	Device; 
1992/0612    
typedef struct Hs	Hs; 
1990/0312    
 
1990/0227    
enum { 
1990/0312    
	Maxburst=	1023,		/* maximum transmit burst size */ 
1990/0227    
	Vmevec=		0xd0,		/* vme vector for interrupts */ 
1992/0612    
	Intvec=		0xd0,		/* vme vector for interrupts */ 
1990/0227    
	Intlevel=	5,		/* level to interrupt on */ 
1990/0312    
	Nhsvme=		1, 
1990/0227    
}; 
1992/0612    
	Nhs=		1, 
1990/0227    
 
1992/0123    
#define NOW (MACHP(0)->ticks*MS2HZ) 
1992/0612    
	/* 
	 * csr flags 
	 */ 
	ALIVE		= 0x0001, 
	IENABLE		= 0x0004, 
	EXOFLOW		= 0x0008, 
	IRQ		= 0x0010, 
	EMUTE		= 0x0020, 
	EPARITY		= 0x0040, 
	EFRAME		= 0x0080, 
	EROFLOW		= 0x0100, 
	REF		= 0x0800, 
	XFF		= 0x4000, 
	XHF		= 0x8000, 
1992/0123    
 
1990/0312    
/* 
 *  hsvme datakit board 
 */ 
struct Device { 
	ushort	version; 
	ushort	pad0x02; 
	ushort	vector; 
	ushort	pad0x06; 
	ushort	csr; 
	ushort	pad0x0A; 
	ushort	data; 
1992/0612    
	/* 
	 * csr reset flags 
	 */ 
	FORCEW		= 0x0008, 
	NORESET		= 0xFF00, 
	RESET		= 0x0000, 
 
	/* 
	 * data flags 
	 */ 
	CTL		= 0x0100, 
	CHNO		= 0x0200, 
	TXEOD		= 0x0400, 
	NND		= 0x8000, 
1990/0312    
}; 
#define HSVME		VMEA24SUP(Device, 0xF90000) 
1990/0227    
 
1990/0312    
struct Hsvme { 
1992/0612    
#define NOW (MACHP(0)->ticks*MS2HZ) 
#define IPL(x)		((x)<<5) 
 
struct Hs { 
1990/0312    
	QLock; 
 
	QLock	xmit; 
	Device	*addr; 
1992/0612    
	HSdev	*addr; 
1990/0312    
	int	vec;		/* interupt vector */ 
	Rendez	r;		/* output process */ 
	Rendez	kr;		/* input kernel process */ 
1992/0321/sys/src/9/power/devhs.c:59,1131992/0612/sys/src/9/power/devhs.c:75,104
1990/0312    
	ulong	out;		/* bytes out */ 
}; 
 
Hsvme hsvme[Nhsvme]; 
1992/0612    
Hs hs[Nhs]; 
1990/0312    
 
1990/0227    
#define ALIVE		0x0001 
#define IENABLE		0x0004 
#define EXOFLOW		0x0008 
#define IRQ		0x0010 
#define EMUTE		0x0020 
#define EPARITY		0x0040 
#define EFRAME		0x0080 
#define EROFLOW		0x0100 
#define REF		0x0800 
#define XFF		0x4000 
#define XHF		0x8000 
1992/0612    
static void hsintr(int); 
static void hskproc(void*); 
1990/0227    
 
#define FORCEW		0x0008 
#define IPL(x)		((x)<<5) 
#define NORESET		0xFF00 
#define RESET		0x0000 
                 
#define CTL		0x0100 
#define CHNO		0x0200 
#define TXEOD		0x0400 
#define NND		0x8000 
                 
static void hsvmeintr(int); 
1990/0312    
static void hsvmekproc(void*); 
1990/0227    
                 
1990/0312    
/* 
 *  hsvme stream module definition 
1992/0612    
 *  hs stream module definition 
1990/0312    
 */ 
static void hsvmeoput(Queue*, Block*); 
static void hsvmestopen(Queue*, Stream*); 
static void hsvmestclose(Queue*); 
1990/11151    
Qinfo hsvmeinfo = 
1992/0612    
static void hsoput(Queue*, Block*); 
static void hsstopen(Queue*, Stream*); 
static void hsstclose(Queue*); 
Qinfo hsinfo = 
1990/11151    
{ 
	nullput, 
	hsvmeoput, 
	hsvmestopen, 
	hsvmestclose, 
	"hsvme" 
1992/0612    
	hsoput, 
	hsstopen, 
	hsstclose, 
	"hs" 
1990/11151    
}; 
1990/0312    
 
/* 
 *  restart a VME board 
 */ 
1990/0227    
void 
1990/0312    
hsvmerestart(Hsvme *hp) 
1992/0612    
hsrestart(Hs *hp) 
1990/0227    
{ 
1990/0312    
	Device *addr; 
1992/0612    
	HSdev *addr; 
1990/0312    
 
	addr = hp->addr; 
 
1992/0321/sys/src/9/power/devhs.c:117,1231992/0612/sys/src/9/power/devhs.c:108,114
1990/0227    
 
	/* 
	 *  set interrupt vector 
	 *  turn on addrice 
1992/0612    
	 *  turn on device 
1990/0227    
	 *  set forcew to a known value 
	 *  interrupt on level `Intlevel' 
	 */ 
1992/0321/sys/src/9/power/devhs.c:135,1501992/0612/sys/src/9/power/devhs.c:126,142
1990/0312    
 *  reset all vme boards 
 */ 
1990/0227    
void 
hsvmereset(void) 
1992/0612    
hsreset(void) 
1990/0227    
{ 
1990/0312    
	int i; 
	Hsvme *hp; 
1992/0612    
	Hs *hp; 
1990/0227    
 
1990/0312    
	for(i=0; i<Nhsvme; i++){ 
		hsvme[i].addr = HSVME+i; 
		hsvme[i].vec = Vmevec+i; 
		hsvme[i].addr->csr = RESET; 
		setvmevec(hsvme[i].vec, hsvmeintr); 
1992/0612    
	for(i=0; i<Nhs; i++){ 
		hp = &hs[i]; 
		hp->addr = HSDEV+i; 
		hp->vec = Intvec+i; 
		hp->addr->csr = RESET; 
		setvmevec(hp->vec, hsintr); 
1990/0312    
	}	 
1990/0227    
	wbflush(); 
1990/0312    
	delay(20); 
1992/0321/sys/src/9/power/devhs.c:151,1571992/0612/sys/src/9/power/devhs.c:143,149
1990/0227    
} 
 
void 
hsvmeinit(void) 
1992/0612    
hsinit(void) 
1990/0227    
{ 
} 
 
1992/0321/sys/src/9/power/devhs.c:159,1761992/0612/sys/src/9/power/devhs.c:151,168
1990/0312    
 *  enable the device for interrupts, spec is the device number 
1990/0227    
 */ 
Chan* 
hsvmeattach(char *spec) 
1992/0612    
hsattach(char *spec) 
1990/0227    
{ 
1990/0312    
	Hsvme *hp; 
1992/0612    
	Hs *hp; 
1990/0312    
	int i; 
	Chan *c; 
1990/0227    
 
1990/0312    
	i = strtoul(spec, 0, 0); 
	if(i >= Nhsvme) 
1992/0612    
	if(i >= Nhs) 
1990/11211    
		error(Ebadarg); 
1990/0312    
	hp = &hsvme[i]; 
1992/0612    
	hp = &hs[i]; 
1991/0921    
	if(!hp->started) 
		hsvmerestart(hp); 
1992/0612    
		hsrestart(hp); 
1990/0227    
 
1990/0312    
	c = devattach('h', spec); 
	c->dev = i; 
1992/0321/sys/src/9/power/devhs.c:179,2091992/0612/sys/src/9/power/devhs.c:171,201
1990/0227    
} 
 
Chan* 
hsvmeclone(Chan *c, Chan *nc) 
1992/0612    
hsclone(Chan *c, Chan *nc) 
1990/0227    
{ 
	return devclone(c, nc); 
} 
 
int	  
hsvmewalk(Chan *c, char *name) 
1992/0612    
hswalk(Chan *c, char *name) 
1990/0227    
{ 
1990/0312    
	return devwalk(c, name, 0, 0, streamgen); 
1990/0227    
} 
 
void	  
hsvmestat(Chan *c, char *dp) 
1992/0612    
hsstat(Chan *c, char *dp) 
1990/0227    
{ 
1990/0312    
	devstat(c, dp, 0, 0, streamgen); 
1990/0227    
} 
 
Chan* 
hsvmeopen(Chan *c, int omode) 
1992/0612    
hsopen(Chan *c, int omode) 
1990/0227    
{ 
1990/11211    
	if(c->qid.path == CHDIR){ 
1990/0312    
		if(omode != OREAD) 
1990/11211    
			error(Eperm); 
1990/0312    
	}else 
		streamopen(c, &hsvmeinfo); 
1992/0612    
		streamopen(c, &hsinfo); 
1990/0227    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
1992/0321/sys/src/9/power/devhs.c:211,2171992/0612/sys/src/9/power/devhs.c:203,209
1990/0227    
} 
 
void	  
hsvmecreate(Chan *c, char *name, int omode, ulong perm) 
1992/0612    
hscreate(Chan *c, char *name, int omode, ulong perm) 
1990/0227    
{ 
1991/1214    
	USED(c); 
1990/11211    
	error(Eperm); 
1992/0321/sys/src/9/power/devhs.c:218,2241992/0612/sys/src/9/power/devhs.c:210,216
1990/0227    
} 
 
void	  
hsvmeclose(Chan *c) 
1992/0612    
hsclose(Chan *c) 
1990/0227    
{ 
1990/11211    
	if(c->qid.path != CHDIR) 
1990/0312    
		streamclose(c); 
1992/0321/sys/src/9/power/devhs.c:225,2431992/0612/sys/src/9/power/devhs.c:217,235
1990/0227    
} 
 
long	  
1991/0411    
hsvmeread(Chan *c, void *buf, long n, ulong offset) 
1992/0612    
hsread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1990/0312    
	return streamread(c, buf, n); 
1990/0227    
} 
 
long	  
1991/0411    
hsvmewrite(Chan *c, void *buf, long n, ulong offset) 
1992/0612    
hswrite(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1990/0312    
	return streamwrite(c, buf, n, 0); 
1990/0227    
} 
 
void	  
hsvmeremove(Chan *c) 
1992/0612    
hsremove(Chan *c) 
1990/0227    
{ 
1991/1214    
	USED(c); 
1990/11211    
	error(Eperm); 
1992/0321/sys/src/9/power/devhs.c:244,2501992/0612/sys/src/9/power/devhs.c:236,242
1990/0227    
} 
 
void	  
hsvmewstat(Chan *c, char *dp) 
1992/0612    
hswstat(Chan *c, char *dp) 
1990/0227    
{ 
1991/1214    
	USED(c); 
1990/11211    
	error(Eperm); 
1992/0321/sys/src/9/power/devhs.c:258,2971992/0612/sys/src/9/power/devhs.c:250,294
1990/0312    
 *  create the kernel process for input 
 */ 
1990/0227    
static void 
1990/0312    
hsvmestopen(Queue *q, Stream *s) 
1992/0612    
hsstopen(Queue *q, Stream *s) 
1990/0227    
{ 
1990/0312    
	Hsvme *hp; 
1992/0612    
	Hs *hp; 
1990/0312    
	char name[32]; 
1990/0227    
 
1990/0312    
	hp = &hsvme[s->dev]; 
1990/0722    
	sprint(name, "hsvme%d", s->dev); 
1992/0612    
	hp = &hs[s->dev]; 
	sprint(name, "hs%d", s->dev); 
1990/0312    
	q->ptr = q->other->ptr = hp; 
	hp->rq = q; 
	kproc(name, hsvmekproc, hp); 
1992/0612    
	kproc(name, hskproc, hp); 
1990/0312    
} 
 
/* 
 *  kill off the kernel process 
1992/0612    
 *  ask kproc to die and wait till it happens 
1990/0312    
 */ 
static int 
kdead(void *arg) 
{ 
	Hsvme *hp; 
1992/0612    
	Hs *hp; 
1990/0312    
 
	hp = (Hsvme *)arg; 
1992/0612    
	hp = (Hs *)arg; 
1990/0312    
	return hp->kstarted == 0; 
} 
static void 
hsvmestclose(Queue * q) 
1992/0612    
hsstclose(Queue * q) 
1990/0312    
{ 
	Hsvme *hp; 
1992/0612    
	Hs *hp; 
1990/0312    
 
	hp = (Hsvme *)q->ptr; 
1992/0612    
	hp = (Hs *)q->ptr; 
1990/0312    
	qlock(hp); 
	hp->rq = 0; 
	qunlock(hp); 
	wakeup(&hp->kr); 
	sleep(&hp->r, kdead, hp); 
1992/0612    
	while(waserror()) 
		; 
	while(hp->kstarted){ 
		wakeup(&hp->kr); 
		sleep(&hp->r, kdead, hp); 
	} 
	poperror(); 
1990/0312    
} 
 
/* 
1992/0321/sys/src/9/power/devhs.c:317,3251992/0612/sys/src/9/power/devhs.c:314,322
1990/0312    
static int 
halfempty(void *arg) 
{ 
	Device *addr; 
1992/0612    
	HSdev *addr; 
1990/0312    
 
	addr = (Device*)arg; 
1992/0612    
	addr = (HSdev*)arg; 
1990/0312    
	return addr->csr & XHF; 
} 
 
1992/0321/sys/src/9/power/devhs.c:331,3401992/0612/sys/src/9/power/devhs.c:328,337
1990/0312    
 *  character. 
 */ 
void 
hsvmeoput(Queue *q, Block *bp) 
1992/0612    
hsoput(Queue *q, Block *bp) 
1990/0312    
{ 
	Device *addr; 
	Hsvme *hp; 
1992/0612    
	HSdev *addr; 
	Hs *hp; 
1990/0312    
	int burst; 
	int chan; 
	int ctl; 
1992/0321/sys/src/9/power/devhs.c:354,3651992/0612/sys/src/9/power/devhs.c:351,362
1990/0312    
	/* 
	 *  one transmitter at a time 
	 */ 
	hp = (Hsvme *)q->ptr; 
1992/0612    
	hp = (Hs *)q->ptr; 
	qlock(&hp->xmit); 
1992/0117    
	if(waserror()){ 
		qunlock(&hp->xmit); 
		nexterror(); 
	} 
1990/0312    
	qlock(&hp->xmit); 
	addr = hp->addr; 
 
	/* 
1992/0321/sys/src/9/power/devhs.c:369,3741992/0612/sys/src/9/power/devhs.c:366,372
1990/0312    
	if(bp->wptr - bp->rptr < 3){ 
		freemsg(q, bp); 
		qunlock(&hp->xmit); 
1992/0612    
		poperror(); 
1990/0312    
		return; 
	} 
1990/0315    
	chan = CHNO | bp->rptr[0] | (bp->rptr[1]<<8); 
1992/0321/sys/src/9/power/devhs.c:435,4431992/0612/sys/src/9/power/devhs.c:433,441
1990/0312    
static int 
notempty(void *arg) 
{ 
	Device *addr; 
1992/0612    
	HSdev *addr; 
1990/0312    
 
	addr = (Device *)arg; 
1992/0612    
	addr = (HSdev *)arg; 
1990/0312    
	return addr->csr & REF; 
} 
 
1992/0321/sys/src/9/power/devhs.c:445,4511992/0612/sys/src/9/power/devhs.c:443,449
1990/0312    
 *  fill a block with what is currently buffered and send it upstream 
 */ 
static void 
upstream(Hsvme *hp, unsigned int ctl) 
1992/0612    
upstream(Hs *hp, unsigned int ctl) 
1990/0312    
{ 
	int n; 
	Block *bp; 
1992/0321/sys/src/9/power/devhs.c:470,4831992/0612/sys/src/9/power/devhs.c:468,481
1990/0312    
 *  fifo fill up. 
 */ 
static void 
hsvmekproc(void *arg) 
1992/0612    
hskproc(void *arg) 
1990/0312    
{ 
	Hsvme *hp; 
	Device *addr; 
1992/0612    
	Hs *hp; 
	HSdev *addr; 
1990/0312    
	unsigned int c; 
1990/1101    
	int locked; 
1990/0312    
 
	hp = (Hsvme *)arg; 
1992/0612    
	hp = (Hs *)arg; 
1990/0312    
	addr = hp->addr; 
	hp->kstarted = 1; 
	hp->wptr = hp->buf; 
1992/0321/sys/src/9/power/devhs.c:509,5151992/0612/sys/src/9/power/devhs.c:507,513
1990/0312    
		/* 
		 *  0xFFFF means an empty fifo 
		 */ 
		while ((c = addr->data) != 0xFFFF) { 
1992/0612    
		while((c = addr->data) != 0xFFFF){ 
1990/0826    
			hp->in++; 
1990/0312    
			if(c & CHNO){ 
				c &= 0x1FF; 
1992/0321/sys/src/9/power/devhs.c:561,5911992/0612/sys/src/9/power/devhs.c:559,589
1990/0312    
 *  and not empty bits to figure out whom to wake. 
 */ 
static void 
hsvmeintr(int vec) 
1992/0612    
hsintr(int vec) 
1990/0312    
{ 
	ushort csr; 
	Device *addr; 
	Hsvme *hp; 
1992/0612    
	HSdev *addr; 
	Hs *hp; 
1990/0312    
 
	hp = &hsvme[vec - Vmevec]; 
	if(hp < hsvme || hp > &hsvme[Nhsvme]){ 
		print("bad hsvme vec\n"); 
1992/0612    
	hp = &hs[vec - Intvec]; 
	if(hp < hs || hp > &hs[Nhs]){ 
		print("bad hs vec\n"); 
1990/0312    
		return; 
	} 
	csr = hp->addr->csr; 
 
	if (csr & REF) { 
1992/0612    
	if(csr & REF){ 
1990/0312    
		hp->rintr++; 
		wakeup(&hp->kr); 
	} 
	if (csr & XHF) { 
1992/0612    
	if(csr & XHF){ 
1990/0312    
		hp->tintr++; 
		wakeup(&hp->r); 
	} 
	if ((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)) { 
1992/0612    
	if((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)){ 
1990/0312    
		hp->parity++; 
		hsvmerestart(hp); 
		print("hsvme %d: reset, csr = 0x%ux\n", 
1990/0930    
			vec - Vmevec, csr); 
1992/0612    
		hsrestart(hp); 
		print("hs %d: reset, csr = 0x%ux\n", 
			vec - Intvec, csr); 
1990/0312    
	} 
1990/0227    
} 
1992/0612/sys/src/9/power/devhs.c:341,3461992/0623/sys/src/9/power/devhs.c:341,353 (short | long)
1990/0312    
		freeb(bp); 
		return; 
	} 
1992/0623    
	if(BLEN(bp) < 3){ 
		bp = pullup(bp, 3); 
		if(bp == 0){ 
			print("hsoput pullup failed\n"); 
			return; 
		} 
	} 
1990/0312    
 
	/* 
	 *  get a whole message before handing bytes to the device 
1992/0612/sys/src/9/power/devhs.c:363,3741992/0623/sys/src/9/power/devhs.c:370,375
1990/0312    
	 *  parse message 
	 */ 
	bp = getq(q); 
	if(bp->wptr - bp->rptr < 3){ 
		freemsg(q, bp); 
		qunlock(&hp->xmit); 
1992/0612    
		poperror(); 
1990/0312    
		return; 
	} 
1990/0315    
	chan = CHNO | bp->rptr[0] | (bp->rptr[1]<<8); 
	ctl = bp->rptr[2]; 
	bp->rptr += 3; 
1992/0623/sys/src/9/power/devhs.c:544,5541992/0703/sys/src/9/power/devhs.c:544,554 (short | long)
1990/0312    
 
		/* 
1992/0123    
		 *  Sleep if input fifo empty. Make sure we don't hold onto 
		 *  any byte for more tha 1/10 second. 
1992/0703    
		 *  any byte for more than 1/10 second. 
1990/0312    
		 */ 
1992/0123    
		if(!(addr->csr & REF)){ 
			if(hp->wptr == hp->buf) 
				sleep(&hp->kr, notempty, addr); 
1992/0703    
				tsleep(&hp->kr, notempty, addr, 2000); 
1992/0123    
			else 
				tsleep(&hp->kr, notempty, addr, 100); 
		} 
1992/0703/sys/src/9/power/devhs.c:206,2111992/0711/sys/src/9/power/devhs.c:206,214 (short | long)
1992/0612    
hscreate(Chan *c, char *name, int omode, ulong perm) 
1990/0227    
{ 
1991/1214    
	USED(c); 
1992/0711    
	USED(name); 
	USED(omode); 
	USED(perm); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1992/0703/sys/src/9/power/devhs.c:219,2241992/0711/sys/src/9/power/devhs.c:222,228
1990/0227    
long	  
1992/0612    
hsread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1992/0711    
	USED(offset); 
1990/0312    
	return streamread(c, buf, n); 
1990/0227    
} 
 
1992/0703/sys/src/9/power/devhs.c:225,2301992/0711/sys/src/9/power/devhs.c:229,235
1990/0227    
long	  
1992/0612    
hswrite(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1992/0711    
	USED(offset); 
1990/0312    
	return streamwrite(c, buf, n, 0); 
1990/0227    
} 
 
1992/0703/sys/src/9/power/devhs.c:239,2441992/0711/sys/src/9/power/devhs.c:244,250
1992/0612    
hswstat(Chan *c, char *dp) 
1990/0227    
{ 
1991/1214    
	USED(c); 
1992/0711    
	USED(dp); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1992/0703/sys/src/9/power/devhs.c:563,5691992/0711/sys/src/9/power/devhs.c:569,574
1992/0612    
hsintr(int vec) 
1990/0312    
{ 
	ushort csr; 
1992/0612    
	HSdev *addr; 
	Hs *hp; 
1990/0312    
 
1992/0612    
	hp = &hs[vec - Intvec]; 
Too many diffs (26 > 25). Stopping.


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