Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/gnot/devincon.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname gnot/devincon.c 1990/0312
## diff -e /dev/null /n/bootesdump/1990/0312/sys/src/9/68020/devincon.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"
#include	"devtab.h"

#include	"io.h"

typedef struct Incon	Incon;
typedef struct Device	Device;

#define NOW (MACHP(0)->ticks*MS2HZ)

#define DPRINT if(0)

enum {
	Minstation=	2,	/* lowest station # to poll */
	Maxstation=	15,	/* highest station # to poll */
	Nincon=		1,	/* number of incons */
	Nraw=		1024,	/* size of raw input buffer */
};

/*
 *  incon datakit board
 */
struct Device {
	uchar	cdata;
#define	cpolln	cdata
	uchar	u0;
	uchar	cstatus;
	uchar	u1;
	uchar	creset;
	uchar	u2;
	uchar	csend;
	uchar	u3;
	ushort	data_cntl;	/* data is high byte, cntl is low byte */
	uchar	status;
#define cmd	status
	uchar	u5;
	uchar	reset;
	uchar	u6;
	uchar	send;
	uchar	u7;
};
#define	INCON	((Device *)0x40700000)

struct Incon {
	QLock;

	QLock	xmit;		/* transmit lock */
	QLock	reslock;	/* reset lock */
	Device	*dev;
	int	station;	/* station number */
	int	state;		/* chip state */
	Rendez	r;		/* output process */
	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;

	/* statistics */

	ulong	overflow;	/* overflow errors */
	ulong	pack0;		/* channel 0 */
	ulong	crc;		/* crc errors */
	ulong	in;		/* bytes in */
	ulong	out;		/* bytes out */
};

Incon incon[Nincon];

/*
 *  chip state
 */
enum {
	Selecting,
	Selected,
	Dead,
};

/*
 *  internal chip registers
 */
#define	sel_polln	0
#define	sel_station	1
#define	sel_poll0	2
#define sel_rcv_cnt	3
#define sel_rcv_tim	4
#define sel_tx_cnt	5

/*
 *  CSR bits
 */
#define INCON_RUN	0x80
#define INCON_STOP	0x00
#define ENABLE_IRQ	0x40
#define ENABLE_TX_IRQ	0x20
#define INCON_ALIVE	0x80
#define TX_FULL		0x10
#define TX_EMPTY	0x08
#define RCV_EMPTY	0x04
#define OVERFLOW	0x02
#define CRC_ERROR	0x01

/*
 *  polling constants
 */
#define HT_GNOT	0x30
#define ST_UNIX 0x04
#define NCHAN 16

static void inconkproc(void*);

/*
 *  incon stream module definition
 */
static void inconoput(Queue*, Block*);
static void inconstopen(Queue*, Stream*);
static void inconstclose(Queue*);
Qinfo inconinfo = { nullput, inconoput, inconstopen, inconstclose, "incon" };

/*
 *  set the incon parameters
 */
void
inconset(Incon *ip, int cnt, int delay)
{
	Device *dev;

	if (cnt<1 || cnt>14 || delay<1 || delay>15)
		error(0, Ebadarg);

	dev = ip->dev;
	dev->cmd = sel_rcv_cnt | INCON_RUN;
	*(uchar *)&dev->data_cntl = cnt;
	dev->cmd = sel_rcv_tim | INCON_RUN;
	*(uchar *)&dev->data_cntl = delay;
	dev->cmd = INCON_RUN | ENABLE_IRQ;
}

static void
nop(void)
{
}

/*
 *  poll for a station number
 */
void 
inconpoll(Incon *ip, int station)
{
	ulong timer;
	Device *dev;

	dev = ip->dev;

	/*
	 *  get us to a known state
	 */
	ip->state = Dead;
	dev->cmd = INCON_STOP;

	/*
	 * try a station number
	 */
	dev->cmd = sel_station;
	*(uchar *)&dev->data_cntl = station;
	dev->cmd = sel_poll0;
	*(uchar *)&dev->data_cntl = HT_GNOT;
	dev->cmd = sel_rcv_cnt;
	*(uchar *)&dev->data_cntl = 3;
	dev->cmd = sel_rcv_tim;
	*(uchar *)&dev->data_cntl = 15;
	dev->cmd = sel_tx_cnt;
	*(uchar *)&dev->data_cntl = 1;
	dev->cmd = sel_polln;
	*(uchar *)&dev->data_cntl = 0x00;
	*(uchar *)&dev->data_cntl = ST_UNIX;
	*(uchar *)&dev->data_cntl = NCHAN;
	*(uchar *)&dev->data_cntl = 'g';
	*(uchar *)&dev->data_cntl = 'n';
	*(uchar *)&dev->data_cntl = 'o';
	*(uchar *)&dev->data_cntl = 't';
	dev->cpolln = 0;

	/*
	 *  poll and wait for ready (or 1/4 second)
	 */
	ip->state = Selecting;
	dev->cmd = INCON_RUN | ENABLE_IRQ;
	timer = NOW + 250;
	while (NOW < timer) {
		nop();
		if(dev->status & INCON_ALIVE){
			ip->station = station;
			ip->state = Selected;
			break;
		}
	}
}

/*
 *  reset the chip and find a new staion number
 */
void
inconrestart(Incon *ip)
{
	Device *dev;
	int i;

	if(!canqlock(&ip->reslock))
		return;

	/*
	 *  poll for incon station numbers
	 */
	for(i = Minstation; i <= Maxstation; i++){
		inconpoll(ip, i);
		if(ip->state == Selected)
			break;
	}
	switch(ip->state) {
	case Selecting:
		print("incon[%d] not polled\n", ip-incon);
		break;
	case Selected:
		print("incon[%d] station %d\n", ip-incon, ip->station);
		inconset(ip, 8, 9);
		break;
	default:
		print("incon[%d] bollixed\n", ip-incon);
		break;
	}
	qunlock(&ip->reslock);
}

/*
 *  reset all incon chips.
 */
void
inconreset(void)
{
	int i;
	Incon *ip;

	incon[0].dev = INCON;
	incon[0].state = Selected;
	incon[0].rp = incon[0].wp = incon[0].raw;
	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;
	}
}

void
inconinit(void)
{
}

/*
 *  enable the device for interrupts, spec is the device number
 */
Chan*
inconattach(char *spec)
{
	Incon *ip;
	int i;
	Chan *c;

	i = strtoul(spec, 0, 0);
	if(i >= Nincon)
		error(0, Ebadarg);
	ip = &incon[i];
	if(ip->state != Selected)
		inconrestart(ip);

	c = devattach('i', spec);
	c->dev = i;
	c->qid = CHDIR;
	return c;
}

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

int	 
inconwalk(Chan *c, char *name)
{
	return devwalk(c, name, 0, 0, streamgen);
}

void	 
inconstat(Chan *c, char *dp)
{
	devstat(c, dp, 0, 0, streamgen);
}

Chan*
inconopen(Chan *c, int omode)
{
	if(c->qid == CHDIR){
		if(omode != OREAD)
			error(0, Eperm);
	}else
		streamopen(c, &inconinfo);
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

void	 
inconcreate(Chan *c, char *name, int omode, ulong perm)
{
	error(0, Eperm);
}

void	 
inconclose(Chan *c)
{
	if(c->qid != CHDIR)
		streamclose(c);
}

long	 
inconread(Chan *c, void *buf, long n)
{
	return streamread(c, buf, n);
}

long	 
inconwrite(Chan *c, void *buf, long n)
{
	return streamwrite(c, buf, n, 0);
}

void	 
inconremove(Chan *c)
{
	error(0, Eperm);
}

void	 
inconwstat(Chan *c, char *dp)
{
	error(0, Eperm);
}

void
inconuserstr(Error *e, char *buf)
{
	consuserstr(e, buf);
}

void	 
inconerrstr(Error *e, char *buf)
{
	rooterrstr(e, buf);
}

/*
 *	the stream routines
 */

/*
 *  create the kernel process for input
 */
static void
inconstopen(Queue *q, Stream *s)
{
	Incon *ip;
	char name[32];

	ip = &incon[s->dev];
	sprint(name, "**incon%d**", s->dev);
	q->ptr = q->other->ptr = ip;
	ip->rq = q;
	kproc(name, inconkproc, ip);
}

/*
 *  kill off the kernel process
 */
static int
kDead(void *arg)
{
	Incon *ip;

	ip = (Incon *)arg;
	return ip->kstarted == 0;
}
static void
inconstclose(Queue * q)
{
	Incon *ip;

	ip = (Incon *)q->ptr;
	qlock(ip);
	ip->rq = 0;
	qunlock(ip);
	wakeup(&ip->kr);
	sleep(&ip->r, kDead, ip);
}

/*
 *  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;
		}
		freeb(bp);
	}
}

/*
 *  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
inconoput(Queue *q, Block *bp)
{
	Device *dev;
	Incon *ip;
	ulong end;
	int chan;
	int ctl;
	int n, size;

	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
	 */
	ip = (Incon *)q->ptr;
	qlock(&ip->xmit);
	dev = ip->dev;

	/*
	 *  parse message
	 */
	bp = getq(q);
	if(bp->wptr - bp->rptr < 3){
		freemsg(q, bp);
		qunlock(&ip->xmit);
		return;
	}
	chan = bp->rptr[0] | (bp->rptr[1]<<8);
	ctl = bp->rptr[2];
	bp->rptr += 3;

	/*
	 *  make sure there's an incon out there
	 */
	if(!(dev->status&INCON_ALIVE) || ip->state==Dead){
		inconrestart(ip);
		freemsg(q, bp);
		qunlock(&ip->xmit);
		return;
	}

	/*
	 *  send the 8 bit data
	 */
	for(;;){
		/*
		 *  spin till there is room
		 */
		for(end = NOW+1000; dev->status & TX_FULL;){
			nop();	/* make sure we don't optimize too much */
			if(NOW > end){
				print("incon output stuck\n");
				freemsg(q, bp);
				qunlock(&ip->xmit);
				return;
			}
		}

		/*
		 *  put in next packet
		 */
		n = bp->wptr - bp->rptr;
		if(n > 16)
			n = 16;
		size = n;
		dev->cdata = chan;
		DPRINT("CH|%uo->\n", chan);
		while(n--){
			DPRINT("->%uo\n", *bp->rptr);
			*(uchar *)&dev->data_cntl = *bp->rptr++;
		}

		/*
		 *  get next block 
		 */
		if(bp->rptr >= bp->wptr){
			if(bp->flags & S_DELIM){
				freeb(bp);
				break;
			}
			freeb(bp);
			bp = getq(q);
			if(bp==0)
				break;
		}

		/*
		 *  end packet
		 */
		dev->cdata = 0;
	}

	/*
	 *  send the control byte if there is one
	 */
	if(ctl){
		if(size >= 16){
			dev->cdata = 0;
			DPRINT("CH|%uo->\n", chan);
			dev->cdata = chan;
		}
		DPRINT("CTL|%uo->\n", ctl);
		dev->cdata = ctl;
	}
	dev->cdata = 0;

	qunlock(&ip->xmit);
	return;
}

/*
 *  return true if the raw fifo is non-empty
 */
static int
notempty(void *arg)
{
	Incon *ip;

	ip = (Incon *)arg;
	return ip->wp!=ip->rp;
}

/*
 *  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
inconkproc(void *arg)
{
	Incon *ip;
	unsigned int c;
	uchar *lim;
	ushort *p, *e;

	ip = (Incon *)arg;
	ip->kstarted = 1;
	ip->wptr = ip->buf;

	e = &ip->raw[Nraw];
	for(;;){
		/*
		 *  die if the device is closed
		 */
		qlock(ip);
		if(ip->rq == 0){
			qunlock(ip);
			ip->kstarted = 0;
			wakeup(&ip->r);
			return;
		}

		/*
		 *  sleep if input fifo empty
		 */
		while(!notempty(ip))
			sleep(&ip->kr, notempty, ip);
		p = ip->rp;

		/*
		 *  get channel number
		 */
		c = (*p++)>>8;
		if(p == e)
			p = ip->raw;
		DPRINT("<-CH|%uo\n", c);
		if(ip->chan != c){
			if(ip->wptr - ip->buf != 0)
				upstream(ip, 0);
			ip->chan = c;
		}

		/*
		 *  null byte marks end of packet
		 */
		for(lim = &ip->buf[sizeof ip->buf];;){
			if((c=*p++)&1) {
				/*
				 *  data byte, put in local buffer
				 */
				c = *ip->wptr++ = c>>8;
				DPRINT("<-%uo\n", c);
				if(ip->wptr >= lim)
					upstream(ip, 0);
			} else if (c>>=8) {
				/*
				 *  control byte ends block
				 */
				DPRINT("<-CTL|%uo\n", c);
				upstream(ip, c);
			} 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);
}

/*
 *  Receive an incon interrupt.  One entry point
 *  for all types of interrupt.  Until we figure out
 *  how to use more than one incon, this routine only
 *  is for incon[0].
 */
inconintr(Ureg *ur)
{
	uchar status;
	Incon *ip;

	ip = &incon[0];

	status = ip->dev->status;
	if(!(status & RCV_EMPTY))
		rdpackets(ip);

	/* check for exceptional conditions */
	if(status&(OVERFLOW|CRC_ERROR)){
		if(status&OVERFLOW){
			print("incon overflow\n");
			ip->overflow++;
		}
		if(status&CRC_ERROR){
			print("incon crc error\n");
			ip->crc++;
		}
	}

	/* see if it died underneath us */
	if(!(status&INCON_ALIVE)){
		switch(ip->state){
		case Selected:
			ip->dev->cmd = INCON_STOP;
			print("Incon died\n");
			break;
		case Selecting:
			print("rejected\n");
			break;
		default:
			ip->dev->cmd = INCON_STOP;
			break;
		}
		ip->state = Dead;
	}
}
.
## diffname gnot/devincon.c 1990/0315
## diff -e /n/bootesdump/1990/0312/sys/src/9/68020/devincon.c /n/bootesdump/1990/0315/sys/src/9/68020/devincon.c
665,713d
660c
				bp = nextin(ip, c);
				if(bp == 0)
					continue;
.
653,654c
				if(bp->wptr >= bp->lim){
					bp = nextin(ip, 0);
					if(bp == 0)
						continue;
				}
.
651c
				c = *bp->wptr++ = c>>8;
.
646,647c
		for(;;){
			if((c=dev->data_cntl)&1) {
.
638,639c
			if(bp->wptr - bp->rptr > 3){
				bp = nextin(ip, 0);
				if(bp == 0)
					continue;
			}
.
633,635c
		c = (dev->data_cntl)>>8;
.
629a
/*
 *  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;
		}

.
626,628c
		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);
	}
}
.
624c
		 *  send blocks upstream and stage new blocks
.
612a
		 *  sleep if input fifo empty
		 */
		sleep(&ip->kr, notempty, ip);

		/*
.
610c
	/*
	 *  create a number of blocks for input
	 */
	for(i = 0; i < Nin; i++){
		bp = ip->inb[i] = allocb(128);
		bp->wptr += 3;
	}

.
608d
602,604c
	Block *bp;
	int i;
.
574,595d
570c
	return ip->ri!=ip->wi;
.
553a
		MICROSECOND;
.
261c
		incon[i].ri = incon[i].wi = 0;
.
256c
	incon[0].ri = incon[0].wi = 0;
	inconset(&incon[0], 8, 9);
.
145c
	MICROSECOND;
	*(uchar *)&dev->data_cntl = del;
	MICROSECOND;
.
143a
	MICROSECOND;
.
142a
	MICROSECOND;
.
138c
	if (cnt<1 || cnt>14 || del<1 || del>15)
.
134c
inconset(Incon *ip, int cnt, int del)
.
68a
	Block	*inb[Nin];
	ushort	wi;		
	ushort	ri;

.
65,67c
	/*  input blocks */
.
61,62d
22c
	Nin=		32,	/* size of raw input buffer */
.
15a
static int SpEcIaL;
#define MICROSECOND SpEcIaL = 0

.
## diffname gnot/devincon.c 1990/0320
## diff -e /n/bootesdump/1990/0315/sys/src/9/68020/devincon.c /n/bootesdump/1990/0320/sys/src/9/68020/devincon.c
761c
			screenputc('+');
.
757c
			screenputc('^');
.
733,734c

		/*
		 *  pass a block on if it doesn't have room for one more
		 *  packet.  this way we don't have to check per byte.
		 */
		if(p + 16 > bp->lim){
			bp->wptr = p;
			bp = nextin(ip, 0);
			if(bp == 0)
				goto done;
			p = bp->wptr;
		}
	}	
	bp->wptr = p;

done:
	if(first != ip->wi)/**/
		wakeup(&ip->kr);
.
727c
					goto done;
				p = bp->wptr;
.
724c
				bp->wptr = p;
.
713,719c
				*p++ = c>>8;
.
700c
					goto done;
				p = bp->wptr;
.
697c
			if(p - bp->rptr > 3){
				bp->wptr = p;
.
695d
684,690d
682a
	bp = ip->inb[ip->wi];
	if(bp==0){
		droppacket(ip->dev);
		goto done;
	}
	p = bp->wptr;
.
680a
	uchar *p;
	int first = ip->wi;
.
664,667d
662c
	ip->wi = next;
.
658a
	next = (ip->wi+1)%Nin;
	if(next == ip->ri){
		bp->wptr = bp->base+3;
		droppacket(ip->dev);
		return 0;
	}
.
657a
	int next;
.
642,645c
	screenputc('!');
	while(!(dev->status & RCV_EMPTY)){
		for(i = 0; i < 17; i++){
			c = dev->data_cntl;
			if(c==0)
				break;
		}
.
625c
			bp = ip->inb[ip->ri] = allocb(Bsize);
.
599c
		bp = ip->inb[i] = allocb(Bsize);
.
563a
	MICROSECOND;
.
562d
560d
558a
			MICROSECOND;
.
557c
			MICROSECOND;
.
527d
525d
25c
	Nin=		16,	/* Blocks in the input ring */
	Bsize=		128,	/* size of an input ring block */
.
9a
#include	"ureg.h"
.
## diffname gnot/devincon.c 1990/0321
## diff -e /n/bootesdump/1990/0320/sys/src/9/68020/devincon.c /n/bootesdump/1990/0321/sys/src/9/68020/devincon.c
751d
744,745d
728,729d
706,707d
701a
		if(c == 0){
			droppacket(dev);
			continue;
		}
.
693,694c
		flushfifo(ip->dev);
		return;
.
673a
	next = (ip->wi+3)%Nin;
	if(next == ip->ri){
		bp->wptr = bp->base+3;
		return bp;
	}
	ip->wi = (ip->wi+1)%Nin;

.
672d
663,668c
	bp = ip->inb[ip->wi];
.
660c
	Block *bp;
.
652a
 *  flush the input fifo
 */
static void
flushfifo(Device *dev)
{
	while(!(dev->status & RCV_EMPTY))
		droppacket(dev);
}

/*
.
642,648c
	for(i = 0; i < 17; i++){
		c = dev->data_cntl;
		if(c==0)
			break;
.
634c
 *  drop a single packet
.
27a
	Mfifo=		0xff	/* a mask, must be 2^n-1, must be > Nin */
.
26c
	Nin=		64,	/* Blocks in the input ring */
.
## diffname gnot/devincon.c 1990/0322
## diff -e /n/bootesdump/1990/0321/sys/src/9/68020/devincon.c /n/bootesdump/1990/0322/sys/src/9/68020/devincon.c
625c
			bp = ip->inb[ip->ri];
			n = BLEN(bp);
			if(n <= 64){
				nbp = allocb(n);
				memcpy(nbp->wptr, bp->rptr, n);
				nbp->wptr += n;
				freeb(bp);
				PUTNEXT(ip->rq, nbp);
			} else {
				PUTNEXT(ip->rq, bp);
			}
.
622c
		 *  send blocks upstream and stage new blocks.  if the block is small
		 *  (< 64 bytes) copy into a smaller buffer.
.
590,591c
	Block *bp, *nbp;
	int i, n;
.
26c
	Nin=		32,	/* Blocks in the input ring */
.
## diffname gnot/devincon.c 1990/0330
## diff -e /n/bootesdump/1990/0322/sys/src/9/68020/devincon.c /n/bootesdump/1990/0330/sys/src/9/68020/devincon.c
267c
/*	inconset(&incon[0], 8, 9); /**/
.
## diffname gnot/devincon.c 1990/0331
## diff -e /n/bootesdump/1990/0330/sys/src/9/68020/devincon.c /n/bootesdump/1990/0331/sys/src/9/68020/devincon.c
628,636c
			PUTNEXT(ip->rq, bp);
.
267c
/*	inconset(&incon[0], 3, 15); /**/
.
246c
		inconset(ip, 3, 15);
.
## diffname gnot/devincon.c 1990/05312
## diff -e /n/bootesdump/1990/0331/sys/src/9/68020/devincon.c /n/bootesdump/1990/05312/sys/src/9/68020/devincon.c
759a
	if(bp->wptr != bp->base+3)
		nextin(ip, 0);
.
## diffname gnot/devincon.c 1990/0619
## diff -e /n/bootesdump/1990/05312/sys/src/9/68020/devincon.c /n/bootesdump/1990/0619/sys/src/9/68020/devincon.c
793d
789,791c
		if(status&CRC_ERROR)
.
786,787c
		if(status&OVERFLOW)
.
## diffname gnot/devincon.c 1990/0623
## diff -e /n/bootesdump/1990/0619/sys/src/9/68020/devincon.c /n/bootesdump/1990/0623/sys/src/9/68020/devincon.c
231a
	print("inconrestart\n");

.
## diffname gnot/devincon.c 1990/0629
## diff -e /n/bootesdump/1990/0623/sys/src/9/68020/devincon.c /n/bootesdump/1990/0629/sys/src/9/68020/devincon.c
809a
}

incontoggle()
{
	incondebug ^= 1;
.
679a
	if(incondebug)
		print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr)-3;
.
494a
	if(incondebug)
		print("->(%d)%uo %d\n", chan, ctl, bp->wptr - bp->rptr);

.
135a
int incondebug;

.
## diffname gnot/devincon.c 1990/0725
## diff -e /n/bootesdump/1990/0629/sys/src/9/68020/devincon.c /n/bootesdump/1990/0725/sys/src/9/68020/devincon.c
815c
		ip->state = Notliving;
.
503c
	if(!(dev->status&INCON_ALIVE) || ip->state==Notliving){
.
430c
	sleep(&ip->r, kNotliving, ip);
.
413c
kNotliving(void *arg)
.
403c
	sprint(name, "incon%d", s->dev);
.
274c
		incon[i].state = Notliving;
.
180c
	ip->state = Notliving;
.
92c
	Notliving,
.
## diffname gnot/devincon.c 1990/0731
## diff -e /n/bootesdump/1990/0725/sys/src/9/68020/devincon.c /n/bootesdump/1990/0731/sys/src/9/68020/devincon.c
693c
	ip->wi = next;
.
688c
	next = (ip->wi+1)%Nin;
.
686c
		print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr);
.
## diffname gnot/devincon.c 1990/0802
## diff -e /n/bootesdump/1990/0731/sys/src/9/68020/devincon.c /n/bootesdump/1990/0802/sys/src/9/68020/devincon.c
495a
	if(chan<=0)
		print("bad channel %d\n", chan);
.
## diffname gnot/devincon.c 1990/1024
## diff -e /n/bootesdump/1990/0802/sys/src/9/68020/devincon.c /n/bootesdump/1990/1024/sys/src/9/68020/devincon.c
612a
	/*
	 *  ignore errors
	 */
	if(waserror())
		;

.
## diffname gnot/devincon.c 1990/1101
## diff -e /n/bootesdump/1990/1024/sys/src/9/68020/devincon.c /n/bootesdump/1990/1101/sys/src/9/68020/devincon.c
648a
		locked = 0;
.
627a
		locked = 1;
.
613,617c
	locked = 0;
	if(waserror()){
		if(locked)
			qunlock(ip);
		ip->kstarted = 0;
		wakeup(&ip->r);
		return;
	}
.
600a
	int locked;
.
480d
467c
		if(streamparse("inconset", bp))
			inconsetctl(ip, bp);
		else
			freeb(bp);
.
465a
	ip = (Incon *)q->ptr;

.
160a
/*
 *  parse a set request
 */
void
inconsetctl(Incon *ip, Block *bp)
{
	char *field[3];
	int n;
	int del;
	int cnt;

	del = 15;
	n = getfields((char *)bp->rptr, field, 3, ' ');
	switch(n){
	default:
		freeb(bp);
		error(0, Ebadarg);
	case 2:
		del = strtol(field[1], 0, 0);
		if(del<0 || del>15){
			freeb(bp);
			error(0, Ebadarg);
		}
		/* fall through */
	case 1:
		cnt = strtol(field[0], 0, 0);
		if(cnt<0 || cnt>15){
			freeb(bp);
			error(0, Ebadarg);
		}
	}
	inconset(ip, cnt, del);
	freeb(bp);
}

.
## diffname gnot/devincon.c 1990/11151
## diff -e /n/bootesdump/1990/1101/sys/src/9/68020/devincon.c /n/bootesdump/1990/11151/sys/src/9/68020/devincon.c
134c
Qinfo inconinfo =
{
	nullput,
	inconoput,
	inconstopen,
	inconstclose,
	"incon"
};
.
## diffname gnot/devincon.c 1990/11211
## diff -e /n/bootesdump/1990/11151/sys/src/9/68020/devincon.c /n/bootesdump/1990/11211/sys/src/9/68020/devincon.c
416,428c
	error(Eperm);
.
410c
	error(Eperm);
.
391c
	if(c->qid.path != CHDIR)
.
385c
	error(Eperm);
.
373c
			error(Eperm);
.
371c
	if(c->qid.path == CHDIR){
.
346c
	c->qid.path = CHDIR;
	c->qid.vers = 0;
.
339c
		error(Ebadarg);
.
196c
			error(Ebadarg);
.
189c
			error(Ebadarg);
.
184c
		error(Ebadarg);
.
154c
		error(Ebadarg);
.
## diffname gnot/devincon.c 1990/1212
## diff -e /n/bootesdump/1990/11211/sys/src/9/68020/devincon.c /n/bootesdump/1990/1212/sys/src/9/68020/devincon.c
605a
		if(dev->status & TX_FULL)
			print("inconfull\n");
.
602a
			for(end = NOW+1000; dev->status & TX_FULL;){
				nop();	/* make sure we don't optimize too much */
				if(NOW > end){
					print("incon output stuck\n");
					freemsg(q, bp);
					qunlock(&ip->xmit);
					return;
				}
			}
.
## diffname gnot/devincon.c 1990/1214
## diff -e /n/bootesdump/1990/1212/sys/src/9/68020/devincon.c /n/bootesdump/1990/1214/sys/src/9/68020/devincon.c
698a
		USED(locked);
.
693d
683a
			poperror();
.
679a
		locked = 1;
.
678c
		USED(locked);
.
646c
	int i;
.
17,18c
#define MICROSECOND USED(NOW)
.
## diffname gnot/devincon.c 1991/0115
## diff -e /n/bootesdump/1990/1214/sys/src/9/68020/devincon.c /n/bootesdump/1991/0115/sys/src/9/68020/devincon.c
880c
void
incontoggle(void)
.
## diffname gnot/devincon.c 1991/0411
## diff -e /n/bootesdump/1991/0201/sys/src/9/68020/devincon.c /n/bootesdump/1991/0411/sys/src/9/gnot/devincon.c
402c
inconwrite(Chan *c, void *buf, long n, ulong offset)
.
396c
inconread(Chan *c, void *buf, long n, ulong offset)
.
## diffname gnot/devincon.c 1991/0419
## diff -e /n/bootesdump/1991/0411/sys/src/9/gnot/devincon.c /n/bootesdump/1991/0419/sys/src/9/gnot/devincon.c
361a
Chan*
inconclwalk(Chan *c, char *name)
{
	return devclwalk(c, name);
}

.
## diffname gnot/devincon.c 1991/0427
## diff -e /n/bootesdump/1991/0419/sys/src/9/gnot/devincon.c /n/bootesdump/1991/0427/sys/src/9/gnot/devincon.c
362,367d
## diffname gnot/devincon.c 1991/0906
## diff -e /n/bootesdump/1991/0427/sys/src/9/gnot/devincon.c /n/bootesdump/1991/0906/sys/src/9/gnot/devincon.c
275,276d
## diffname gnot/devincon.c 1991/1122
## diff -e /n/bootesdump/1991/0906/sys/src/9/gnot/devincon.c /n/bootesdump/1991/1122/sys/src/9/gnot/devincon.c
691a
			ip->in += BLEN(bp);
.
568a
		ip->out += n;
.
559a
		ip->wait = (n + ip->wait)>>1;
.
551c
		start = NOW;
		for(n = 0, end = start+1000; dev->status & TX_FULL; n++){
.
489c
	ulong start, end;
.
396c
	char b[256];
	Incon *i;

	if(c->qid.path == CHDIR)
		return devdirread(c, buf, n, incondir, 1, streamgen);
	else if(c->qid.path == Qstats){
		i = &incon[c->dev];
		sprint(b, "in: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n", i->in,
			i->out, i->overflow, i->crc, i->wait);
		return stringread(buf, n, b, offset);
	} else
		return streamread(c, buf, n);
.
369c
	if(c->qid.path == CHDIR || c->qid.path == Qstats){
.
363c
	devstat(c, dp, incondir, 1, streamgen);
.
357c
	return devwalk(c, name, incondir, 1, streamgen);
.
143a
Dirtab incondir[]={
	"stats",		{Qstats},	0,		0444,
};

.
80a
	ulong	wait;		/* wait time in milliseconds */
.
27c
	Mfifo=		0xff,	/* a mask, must be 2^n-1, must be > Nin */

	Qstats=		1,	/* qid of the statistics file */
.
## diffname gnot/devincon.c 1991/1209
## diff -e /n/bootesdump/1991/1122/sys/src/9/gnot/devincon.c /n/bootesdump/1991/1209/sys/src/9/gnot/devincon.c
831a
				if(bp==0){
					flushfifo(ip->dev);
					return;
				}
.
811a
				if(bp==0){
					flushfifo(ip->dev);
					return;
				}
.
## diffname gnot/devincon.c 1991/1219
## diff -e /n/bootesdump/1991/1209/sys/src/9/gnot/devincon.c /n/bootesdump/1991/1219/sys/src/9/gnot/devincon.c
458,465d
450a
	wakeup(&ip->kr);
	sleep(&ip->r, kNotliving, ip);
.
440a
 *  first wait for any old ones to die
.
439a
 * for sleeping while kproc dies
 */
static int
kNotliving(void *arg)
{
	Incon *ip;

	ip = (Incon *)arg;
	return ip->kstarted == 0;
}

/*
.
## diffname gnot/devincon.c 1992/0111
## diff -e /n/bootesdump/1991/1219/sys/src/9/gnot/devincon.c /n/bootesdump/1992/0111/sys/src/9/gnot/devincon.c
6c
#include	"../port/error.h"
.
## diffname gnot/devincon.c 1992/0321
## diff -e /n/bootesdump/1992/0111/sys/src/9/gnot/devincon.c /n/bootesdump/1992/0321/sys/src/9/gnot/devincon.c
2c
#include	"../port/lib.h"
.
## diffname gnot/devincon.c 1992/0611
## diff -e /n/bootesdump/1992/0321/sys/src/9/gnot/devincon.c /n/bootesdump/1992/0611/sys/src/9/gnot/devincon.c
877a
void
.
## diffname gnot/devincon.c 1992/0623
## diff -e /n/bootesdump/1992/0611/sys/src/9/gnot/devincon.c /n/bootesdump/1992/0623/sys/src/9/gnot/devincon.c
865c
	if(bp->wptr != bp->rptr+3)
.
778c
		bp->wptr = bp->rptr+3;
.
770,772c
	bp->rptr[0] = ip->chan;
	bp->rptr[1] = ip->chan>>8;
	bp->rptr[2] = c;
.
545,549d
527a
	if(BLEN(bp) < 3){
		bp = pullup(bp, 3);
		if(bp == 0){
			print("inconoput pullup failed\n");
			return;
		}
	}
.
412c
		return readstr(offset, buf, n, b);
.
## diffname gnot/devincon.c 1992/0711
## diff -e /n/bootesdump/1992/0623/sys/src/9/gnot/devincon.c /n/bootesdump/1992/0711/sys/src/9/gnot/devincon.c
885a
	USED(ur);
.
672c
	Block *bp;
.
431a
	USED(c, dp);
.
425a
	USED(c);
.
419a
	USED(offset);
.
389a
	USED(c, name, omode, perm);
.
312d
276d
## diffname gnot/devincon.c 1993/0501 # deleted
## diff -e /n/bootesdump/1992/0711/sys/src/9/gnot/devincon.c /n/fornaxdump/1993/0501/sys/src/brazil/gnot/devincon.c
1,925d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].