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

1990/0315/gnot/devincon.c (diff list | history)

1990/0312/sys/src/9/gnot/devincon.c:13,181990/0315/sys/src/9/gnot/devincon.c:13,21 (short | long | prev | next)
1990/0312    
 
#define NOW (MACHP(0)->ticks*MS2HZ) 
 
1990/0315    
static int SpEcIaL; 
#define MICROSECOND SpEcIaL = 0 
 
1990/0312    
#define DPRINT if(0) 
 
enum { 
1990/0312/sys/src/9/gnot/devincon.c:19,251990/0315/sys/src/9/gnot/devincon.c:22,28
1990/0312    
	Minstation=	2,	/* lowest station # to poll */ 
	Maxstation=	15,	/* highest station # to poll */ 
	Nincon=		1,	/* number of incons */ 
	Nraw=		1024,	/* size of raw input buffer */ 
1990/0315    
	Nin=		32,	/* size of raw input buffer */ 
1990/0312    
}; 
 
/* 
1990/0312/sys/src/9/gnot/devincon.c:58,711990/0315/sys/src/9/gnot/devincon.c:61,74
1990/0312    
	Rendez	kr;		/* input kernel process */ 
	ushort	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 */ 
 
	ushort	raw[Nraw]; 
	ushort	*rp; 
	ushort	*wp; 
1990/0315    
	/*  input blocks */ 
1990/0312    
 
1990/0315    
	Block	*inb[Nin]; 
	ushort	wi;		 
	ushort	ri; 
 
1990/0312    
	/* statistics */ 
 
	ulong	overflow;	/* overflow errors */ 
1990/0312/sys/src/9/gnot/devincon.c:131,1481990/0315/sys/src/9/gnot/devincon.c:134,155
1990/0312    
 *  set the incon parameters 
 */ 
void 
inconset(Incon *ip, int cnt, int delay) 
1990/0315    
inconset(Incon *ip, int cnt, int del) 
1990/0312    
{ 
	Device *dev; 
 
	if (cnt<1 || cnt>14 || delay<1 || delay>15) 
1990/0315    
	if (cnt<1 || cnt>14 || del<1 || del>15) 
1990/0312    
		error(0, Ebadarg); 
 
	dev = ip->dev; 
	dev->cmd = sel_rcv_cnt | INCON_RUN; 
1990/0315    
	MICROSECOND; 
1990/0312    
	*(uchar *)&dev->data_cntl = cnt; 
1990/0315    
	MICROSECOND; 
1990/0312    
	dev->cmd = sel_rcv_tim | INCON_RUN; 
	*(uchar *)&dev->data_cntl = delay; 
1990/0315    
	MICROSECOND; 
	*(uchar *)&dev->data_cntl = del; 
	MICROSECOND; 
1990/0312    
	dev->cmd = INCON_RUN | ENABLE_IRQ; 
} 
 
1990/0312/sys/src/9/gnot/devincon.c:253,2641990/0315/sys/src/9/gnot/devincon.c:260,272
1990/0312    
 
	incon[0].dev = INCON; 
	incon[0].state = Selected; 
	incon[0].rp = incon[0].wp = incon[0].raw; 
1990/0315    
	incon[0].ri = incon[0].wi = 0; 
	inconset(&incon[0], 8, 9); 
1990/0312    
	for(i=1; i<Nincon; i++){ 
		incon[i].dev = INCON+i; 
		incon[i].state = Dead; 
		incon[i].dev->cmd = INCON_STOP; 
		incon[i].rp = incon[i].wp = incon[i].raw; 
1990/0315    
		incon[i].ri = incon[i].wi = 0; 
1990/0312    
	} 
} 
 
1990/0312/sys/src/9/gnot/devincon.c:551,5561990/0315/sys/src/9/gnot/devincon.c:559,565
1990/0312    
		} 
		DPRINT("CTL|%uo->\n", ctl); 
		dev->cdata = ctl; 
1990/0315    
		MICROSECOND; 
1990/0312    
	} 
	dev->cdata = 0; 
 
1990/0312/sys/src/9/gnot/devincon.c:567,5981990/0315/sys/src/9/gnot/devincon.c:576,585
1990/0312    
	Incon *ip; 
 
	ip = (Incon *)arg; 
	return ip->wp!=ip->rp; 
1990/0315    
	return ip->ri!=ip->wi; 
1990/0312    
} 
 
/* 
 *  fill a block with what is currently buffered and send it upstream 
 */ 
static void 
upstream(Incon *ip, unsigned int ctl) 
{ 
	int n; 
	Block *bp; 
                 
	n = ip->wptr - ip->buf; 
	bp = allocb(3 + n); 
	bp->wptr[0] = ip->chan; 
	bp->wptr[1] = ip->chan>>8; 
	bp->wptr[2] = ctl; 
	if(n) 
		memcpy(&bp->wptr[3], ip->buf, n); 
	bp->wptr += 3 + n; 
	bp->flags |= S_DELIM; 
	PUTNEXT(ip->rq, bp); 
	ip->wptr = ip->buf; 
} 
                 
/* 
 *  Read bytes from the raw input circular buffer. 
 */ 
static void 
1990/0312/sys/src/9/gnot/devincon.c:599,6151990/0315/sys/src/9/gnot/devincon.c:586,612
1990/0312    
inconkproc(void *arg) 
{ 
	Incon *ip; 
	unsigned int c; 
	uchar *lim; 
	ushort *p, *e; 
1990/0315    
	Block *bp; 
	int i; 
1990/0312    
 
	ip = (Incon *)arg; 
	ip->kstarted = 1; 
	ip->wptr = ip->buf; 
 
	e = &ip->raw[Nraw]; 
1990/0315    
	/* 
	 *  create a number of blocks for input 
	 */ 
	for(i = 0; i < Nin; i++){ 
		bp = ip->inb[i] = allocb(128); 
		bp->wptr += 3; 
	} 
 
1990/0312    
	for(;;){ 
		/* 
1990/0315    
		 *  sleep if input fifo empty 
		 */ 
		sleep(&ip->kr, notempty, ip); 
 
		/* 
1990/0312    
		 *  die if the device is closed 
		 */ 
		qlock(ip); 
1990/0312/sys/src/9/gnot/devincon.c:621,6421990/0315/sys/src/9/gnot/devincon.c:618,704
1990/0312    
		} 
 
		/* 
		 *  sleep if input fifo empty 
1990/0315    
		 *  send blocks upstream and stage new blocks 
1990/0312    
		 */ 
		while(!notempty(ip)) 
			sleep(&ip->kr, notempty, ip); 
		p = ip->rp; 
1990/0315    
		while(ip->ri != ip->wi){ 
			PUTNEXT(ip->rq, ip->inb[ip->ri]); 
			bp = ip->inb[ip->ri] = allocb(128); 
			bp->wptr += 3; 
			ip->ri = (ip->ri+1)%Nin; 
		} 
		qunlock(ip); 
	} 
} 
1990/0312    
 
1990/0315    
/* 
 *  drop an input packet on the floor 
 */ 
static void 
droppacket(Device *dev) 
{ 
	int i; 
	int c; 
 
	for(i = 0; i < 17; i++){ 
		c = dev->data_cntl; 
		if(c==0) 
			break; 
	} 
} 
 
/* 
 *  advance the queue. if we've run out of staged input blocks, 
 *  drop the packet and return 0.  otherwise return the next input 
 *  block to fill. 
 */ 
static Block * 
nextin(Incon *ip, unsigned int c) 
{ 
	Block *bp = ip->inb[ip->wi]; 
 
	bp->base[0] = ip->chan; 
	bp->base[1] = ip->chan>>8; 
	bp->base[2] = c; 
	ip->wi = (ip->wi + 1) % Nin; 
 
	if(((ip->wi+1)%Nin) == ip->ri){ 
		droppacket(ip->dev); 
		return 0; 
	} 
	return ip->inb[ip->wi]; 
} 
 
/* 
 *  read the packets from the device into the staged input blocks. 
 *  we have to do this at interrupt tevel to turn off the interrupts. 
 */ 
static void 
rdpackets(Incon *ip) 
{ 
	Block *bp; 
	unsigned int c; 
	Device *dev; 
 
	dev = ip->dev; 
	while(!(dev->status & RCV_EMPTY)){ 
		bp = ip->inb[ip->wi]; 
		if(((ip->wi+1)%Nin) == ip->ri || bp==0){ 
			c = dev->data_cntl; 
			droppacket(dev); 
			continue; 
		} 
 
1990/0312    
		/* 
		 *  get channel number 
		 */ 
		c = (*p++)>>8; 
		if(p == e) 
			p = ip->raw; 
1990/0315    
		c = (dev->data_cntl)>>8; 
1990/0312    
		DPRINT("<-CH|%uo\n", c); 
		if(ip->chan != c){ 
			if(ip->wptr - ip->buf != 0) 
				upstream(ip, 0); 
1990/0315    
			if(bp->wptr - bp->rptr > 3){ 
				bp = nextin(ip, 0); 
				if(bp == 0) 
					continue; 
			} 
1990/0312    
			ip->chan = c; 
		} 
 
1990/0312/sys/src/9/gnot/devincon.c:643,7161990/0315/sys/src/9/gnot/devincon.c:705,734
1990/0312    
		/* 
		 *  null byte marks end of packet 
		 */ 
		for(lim = &ip->buf[sizeof ip->buf];;){ 
			if((c=*p++)&1) { 
1990/0315    
		for(;;){ 
			if((c=dev->data_cntl)&1) { 
1990/0312    
				/* 
				 *  data byte, put in local buffer 
				 */ 
				c = *ip->wptr++ = c>>8; 
1990/0315    
				c = *bp->wptr++ = c>>8; 
1990/0312    
				DPRINT("<-%uo\n", c); 
				if(ip->wptr >= lim) 
					upstream(ip, 0); 
1990/0315    
				if(bp->wptr >= bp->lim){ 
					bp = nextin(ip, 0); 
					if(bp == 0) 
						continue; 
				} 
1990/0312    
			} else if (c>>=8) { 
				/* 
				 *  control byte ends block 
				 */ 
				DPRINT("<-CTL|%uo\n", c); 
				upstream(ip, c); 
1990/0315    
				bp = nextin(ip, c); 
				if(bp == 0) 
					continue; 
1990/0312    
			} else { 
				/* end of packet */ 
				break; 
			} 
			if(p == e) 
				p = ip->raw; 
		} 
		ip->rp = p; 
		qunlock(ip); 
	} 
} 
                 
/* 
 *  read the packets from the device into the raw input buffer. 
 *  we have to do this at interrupt tevel to turn off the interrupts. 
 */ 
static 
rdpackets(Incon *ip) 
{ 
	Device *dev; 
	unsigned int c; 
	ushort *p, *e; 
	int n; 
                 
	dev = ip->dev; 
	while(!(dev->status & RCV_EMPTY)){ 
		n = ip->rp - ip->wp; 
		if(n <= 0) 
			n += Nraw; 
		if(n < 19){ 
			/* 
			 *  no room in the raw queue, throw it away 
			 */ 
			c = (dev->data_cntl)>>8; 
			for(c=0;c<18;c++){ 
				if(dev->data_cntl == 0) 
					break; 
			} 
		} else { 
			/* 
			 *  put packet in the raw queue 
			 */ 
			p = ip->wp; 
			e = &ip->raw[Nraw]; 
			*p++ = dev->data_cntl; 
			if(p == e) 
				p = ip->raw; 
			do { 
				*p++ = c = dev->data_cntl; 
				if(p == e) 
					p = ip->raw; 
			} while(c); 
			ip->wp = p; 
		} 
	} 
	wakeup(&ip->kr); 


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