~kris/9p

9hist

4b784ab08ca76e708266478ceeb90957cd5de71b — David du Colombier 30 years ago 774f0f5
Plan 9 from Bell Labs 1996-06-08
5 files changed, 92 insertions(+), 110 deletions(-)

M pc/ether79c970.c
M pc/ether82557.c
M pc/etherelnk3.c
M pc/u.h
M port/devns16552.c
M pc/ether79c970.c => pc/ether79c970.c +5 -5
@@ 185,8 185,8 @@ promiscuous(void* arg, int on)
	ctlr = ether->ctlr;

	/*
	 * Put the chip into promiscuous mode. First we must wait until
	 * anyone transmitting is done, then we can stop the chip and put
	 * Put the chip into promiscuous mode. First must wait until
	 * anyone transmitting is done, then stop the chip and put
	 * it in promiscuous mode. Restarting is made harder by the chip
	 * reloading the transmit and receive descriptor pointers with their
	 * base addresses when Strt is set (unlike the older Lance chip),


@@ 284,7 284,7 @@ interrupt(Ureg*, void* arg)
	/*
	 * Receiver interrupt: run round the descriptor ring logging
	 * errors and passing valid receive data up to the higher levels
	 * until we encounter a descriptor still owned by the chip.
	 * until a descriptor is encountered still owned by the chip.
	 */
	if(csr0 & Rint){
		rdre = &ctlr->rdr[ctlr->rdrx];


@@ 371,8 371,8 @@ reset(Ether* ether)

	/*
	 * Any adapter matches if no ether->port is supplied, otherwise the
	 * ports must match. First see if we've already found an adapter that fits
	 * the bill. If not then scan for another.
	 * ports must match. First see if an adapter that fits the bill has
	 * already been found. If not then scan for another.
	 */
	port = 0;
	for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){

M pc/ether82557.c => pc/ether82557.c +0 -2
@@ 434,7 434,6 @@ interrupt(Ureg*, void* arg)
					etherrloop(ether, rfd, rfd->count & 0x3FFF);
					ether->inpackets++;
				}
else print("%s#%d: rfd->field %uX\n", ctlr->type,  ctlr->ctlrno, rfd->field);

				/*
				 * Reinitialise the frame for reception and bump


@@ 463,7 462,6 @@ else print("%s#%d: rfd->field %uX\n", ctlr->type,  ctlr->ctlrno, rfd->field);
			while(csr8r(ctlr, Command))
				;
			csr8w(ctlr, Command, RUresume);
print("%s#%d: status %uX\n", ctlr->type,  ctlr->ctlrno, status);

			status &= ~StatRNR;
		}

M pc/etherelnk3.c => pc/etherelnk3.c +0 -2
@@ 564,7 564,6 @@ receive(Ether* ether)
		 */
		if(rxstatus & rxError){
			if(ctlr->rxstatus9){
iprint("R%uX|", rxstatus);
				switch(rxstatus & rxError9){

				case rxOverrun9:


@@ 588,7 587,6 @@ iprint("R%uX|", rxstatus);
			}
			else{
				rxerror = inb(port+RxError);
iprint("R%uX|", rxerror);
				if(rxerror & rxOverrun)
					ether->overflows++;
				if(rxerror & (oversizedFrame|runtFrame))

M pc/u.h => pc/u.h +2 -1
@@ 1,8 1,9 @@
#define nil		((void*)0)
typedef	unsigned short	ushort;
typedef	unsigned char	uchar;
typedef	signed char	schar;
typedef unsigned int	uint;
typedef unsigned long	ulong;
typedef   signed char	schar;
typedef	long		vlong;
typedef union Length	Length;
typedef ushort		Rune;

M port/devns16552.c => port/devns16552.c +85 -100
@@ 72,54 72,56 @@ typedef struct Uart Uart;
struct Uart
{
	QLock;
	int	opens;

	Uart	*elist;		/* next enabled interface */
	int	enabled;
	Uart	*elist;			/* next enabled interface */
	char	name[NAMELEN];

	uchar	sticky[8];	/* sticky write register values */
	uchar	sticky[8];		/* sticky write register values */
	ulong	port;
	Lock	plock;		/* for printing variable */
	ulong	freq;		/* clock frequency */
	int	opens;
	uchar	mask;		/* bits/char */
	uchar	istat;		/* last istat read */
	uchar	fifoon;		/* fifo's enabled */
	uchar	nofifo;		/* earlier chip version with nofifo */
	int	enabled;
	ulong	freq;			/* clock frequency */
	uchar	mask;			/* bits/char */
	int	dev;
	int	baud;			/* baud rate */

	int	frame;		/* framing errors */
	int	overrun;	/* rcvr overruns */
	int	baud;		/* baud rate */

	/* flow control */
	int	xonoff;		/* software flow control on */
	int	blocked;
	int	modem;		/* hardware flow control on */
	int	cts;		/* ... cts state */
	int	ctsbackoff;
	int	rts;		/* ... rts state */
	Rendez	r;
	uchar	istat;			/* last istat read */
	int	frame;			/* framing errors */
	int	overrun;		/* rcvr overruns */

	/* buffers */
	int	(*putc)(Queue*, int);
	Queue	*iq;
	Queue	*oq;

	/* staging areas to avoid some of the per character costs */
	Lock	flock;			/* fifo */
	uchar	fifoon;			/* fifo's enabled */
	uchar	nofifo;			/* earlier chip version with nofifo */

	Lock	rlock;			/* receive */
	uchar	istage[Stagesize];
	uchar	*ip;
	uchar	*ie;

	int	haveinput;

	Lock	tlock;			/* transmit */
	uchar	ostage[Stagesize];
	uchar	*op;
	uchar	*oe;

	int	modem;			/* hardware flow control on */
	int	xonoff;			/* software flow control on */
	int	blocked;
	int	cts;
	int	ctsbackoff;

	Rendez	r;
};

static Uart *uart[Nuart];
static int nuart;

static int haveinput;
struct Uartalloc {
	Lock;
	Uart *elist;	/* list of enabled interfaces */


@@ 209,27 211,18 @@ ns16552dtr(Uart *p, int n)
void
ns16552rts(Uart *p, int n)
{
	int x;

	x = splhi();
	lock(&p->plock);

	if(n)
		p->sticky[Mctl] |= Rts;
	else
		p->sticky[Mctl] &= ~Rts;

	uartwrreg(p, Mctl, 0);
	p->rts = n;

	unlock(&p->plock);
	splx(x);
}

/*
 *  send break
 */
void
static void
ns16552break(Uart *p, int ms)
{
	if(ms == 0)


@@ 240,7 233,7 @@ ns16552break(Uart *p, int ms)
	uartwrreg(p, Format, 0);
}

void
static void
ns16552fifoon(Uart *p)
{
	ulong i, x;


@@ 276,33 269,40 @@ ns16552fifoon(Uart *p)
/*
 *  modem flow control on/off (rts/cts)
 */
void
static void
ns16552mflow(Uart *p, int n)
{
	ilock(&p->tlock);
	if(n){
		p->sticky[Iena] |= Imstat;
		uartwrreg(p, Iena, 0);
		p->modem = 1;
		p->cts = uartrdreg(p, Mstat) & Cts;

		/* turn on fifo's */
		ns16552fifoon(p);
	} else {
		p->sticky[Iena] &= ~Imstat;
		uartwrreg(p, Iena, 0);
		p->modem = 0;
		p->cts = 1;
		iunlock(&p->tlock);
	}
	iunlock(&p->tlock);

	ilock(&p->flock);
	if(n)
		/* turn on fifo's */
		ns16552fifoon(p);
	else {
		/* turn off fifo's */
		p->fifoon = 0;
		uartwrreg(p, Fifoctl, 0);
	}
	iunlock(&p->flock);
}

/*
 *  turn on a port's interrupts.  set DTR and RTS
 */
void
static void
ns16552enable(Uart *p)
{
	Uart **l;


@@ 327,8 327,10 @@ ns16552enable(Uart *p)
	/*
	 *  assume we can send
	 */
	ilock(&p->tlock);
	p->cts = 1;
	p->blocked = 0;
	iunlock(&p->tlock);

	/*
	 *  set baud rate to the last used


@@ 351,7 353,7 @@ ns16552enable(Uart *p)
/*
 *  turn off a port's interrupts.  reset DTR and RTS
 */
void
static void
ns16552disable(Uart *p)
{
	Uart **l;


@@ 374,7 376,10 @@ ns16552disable(Uart *p)
	ns16552dtr(p, 0);
	ns16552rts(p, 0);
	ns16552mflow(p, 0);
	p->xonoff = p->blocked = 0;
	ilock(&p->tlock);
	p->blocked = 0;
	iunlock(&p->tlock);
	p->xonoff = 0;

	uartpower(p->dev, 0);



@@ 410,30 415,23 @@ stageoutput(Uart *p)
 *  (re)start output
 */
static void
ns16552kick(Uart *p)
ns16552kick0(Uart *p)
{
	int x, n;

	x = splhi();
	lock(&p->plock);
	if((uartrdreg(p, Lstat) & Outready))
	if(p->cts && p->blocked == 0)
	if(p->op < p->oe || stageoutput(p)){
		n = 0;
		while((uartrdreg(p, Lstat) & Outready) == 0){
			if(++n > 100000){
				print("stuck serial line\n");
				break;
			}
		}
		do{
			outb(p->port + Data, *(p->op++));
			if(p->op >= p->oe && stageoutput(p) == 0)
				break;
		}while(uartrdreg(p, Lstat) & Outready);
	if(p->cts == 0 || p->blocked)
		return;
	while(uartrdreg(p, Lstat) & Outready){
		if(p->op >= p->oe && stageoutput(p) == 0)
			break;
		outb(p->port + Data, *(p->op++));
	}
	unlock(&p->plock);
	splx(x);
}

static void
ns16552kick(Uart *p)
{
	ilock(&p->tlock);
	ns16552kick0(p);
	iunlock(&p->tlock);
}

/*


@@ 444,7 442,9 @@ ns16552flow(Uart *p)
{
	if(p->modem){
		ns16552rts(p, 1);
		haveinput = 1;
		ilock(&p->rlock);
		p->haveinput = 1;
		iunlock(&p->rlock);
	}
}



@@ 519,22 519,6 @@ ns16552special(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, 
}

/*
 *  reset the interface
 */
void
ns16552shake(Uart *p)
{
	int xonoff, modem;

	xonoff = p->xonoff;
	modem = p->modem;
	ns16552disable(p);
	ns16552enable(p);
	p->xonoff = xonoff;
	ns16552mflow(p, modem);
}

/*
 *  handle an interrupt to a single uart
 */
void


@@ 564,6 548,7 @@ ns16552intr(int dev)
		case 4:	/* received data available */
		case 12:
			ch = uartrdreg(p, Data) & 0xff;
			lock(&p->tlock);
			if(p->xonoff){
				if(ch == CTLS){
					p->blocked = 1;


@@ 572,37 557,31 @@ ns16552intr(int dev)
					 /* clock gets output going again */
				}
			}
			unlock(&p->tlock);
			if(p->putc)
				(*p->putc)(p->iq, ch);
			else {
				lock(&p->rlock);
				if(p->ip < p->ie)
					*p->ip++ = ch;
				haveinput = 1;
				p->haveinput = 1;
				unlock(&p->rlock);
			}
			break;
	
		case 2:	/* transmitter not full */
			lock(&p->plock);
			l = uartrdreg(p, Lstat) & Outready;
			if(l && p->cts && p->blocked == 0)
			if(p->op < p->oe || stageoutput(p)){
				do{
					outb(p->port + Data, *(p->op++));
					if(p->op >= p->oe && stageoutput(p) == 0)
						break;
					l = uartrdreg(p, Lstat) & Outready;
				}while(l);
			}
			unlock(&p->plock);
			ns16552kick(p);
			break;
	
		case 0:	/* modem status */
			ch = uartrdreg(p, Mstat);
			if(ch & Ctsc){
				lock(&p->tlock);
				l = p->cts;
				p->cts = ch & Cts;
				if(l == 0 && p->cts)
					p->ctsbackoff = 2; /* clock gets output going again */
				unlock(&p->tlock);
			}
			break;
	


@@ 633,8 612,10 @@ uartclock(void)
	Uart *p;

	for(p = uartalloc.elist; p; p = p->elist){

		/* this amortizes cost of qproduce to many chars */
		if(haveinput){
		lock(&p->rlock);
		if(p->haveinput){
			n = p->ip - p->istage;
			if(n > 0 && p->iq){
				if(n > Stagesize)


@@ 644,15 625,18 @@ uartclock(void)
				else
					p->ip = p->istage;
			}
			p->haveinput = 0;
		}
		unlock(&p->rlock);

		/* this adds hysteresis to hardware flow control */
		lock(&p->tlock);
		if(p->ctsbackoff){
			if(--(p->ctsbackoff) == 0)
				ns16552kick(p);
				ns16552kick0(p);
		}
		unlock(&p->tlock);
	}
	haveinput = 0;
}

Dirtab *ns16552dir;


@@ 672,7 656,6 @@ setlength(int i)
		if(p && p->opens && p->iq)
			ns16552dir[3*i].length = qlen(p->iq);
	}
		
}

/*


@@ 792,7 775,7 @@ ns16552close(Chan *c)
	}
}

static long
long
uartstatus(Chan*, Uart *p, void *buf, long n, long offset)
{
	uchar mstat;


@@ 855,7 838,7 @@ ns16552bread(Chan *c, long n, ulong offset)
	return devbread(c, n, offset);
}

static void
void
ns16552ctl(Uart *p, char *cmd)
{
	int i, n;


@@ 944,8 927,10 @@ ns16552write(Chan *c, void *buf, long n, ulong)
	 *  The fifo's turn themselves off sometimes.
	 *  It must be something I don't understand. -- presotto
	 */
	lock(&p->flock);
	if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0)
		ns16552fifoon(p);
	unlock(&p->flock);

	switch(NETTYPE(c->qid.path)){
	case Ndataqid: