Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/bitsy/devuart.c

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


## diffname bitsy/devuart.c 2000/0904
## diff -e /dev/null /n/emeliedump/2000/0904/sys/src/9/bitsy/devuart.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"

#include	"../port/netif.h"

enum
{
	Nuart = 1,
	Stagesize= 1024,
};

/* hardware registers */
typedef struct Uartregs Uartregs;
struct Uartregs
{
	ulong	ctl0;
	ulong	ctl1;
	ulong	ctl2;
	ulong	ctl3;
	uchar	dummyd[4];
	ulong	data;
	uchar	dummyf[4];
	ulong	status0;
	ulong	status1;
};
#define	UART3REGS IOA(Uartregs, 0x50000)

/* ctl0 bits */
enum
{
	XmitNotFull = (1 << 2),
};

/* software representation */
typedef struct Uart Uart;
struct Uart
{
	QLock;
	int	opens;

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

	uchar	sticky[8];		/* sticky write register values */
	uchar	osticky[8];		/* kernel saved sticky write register values */
	ulong	port;			/* io ports */
	ulong	freq;			/* clock frequency */
	uchar	mask;			/* bits/char */
	int	dev;
	int	baud;			/* baud rate */

	uchar	istat;			/* last istat read */
	int	frame;			/* framing errors */
	int	overrun;		/* rcvr overruns */

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

	Lock	flock;			/* fifo */
	uchar	fifoon;			/* fifo's enabled */
	uchar	type;			/* chip version */

	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, dsr, dcd, dcdts;		/* keep track of modem status */ 
	int	ctsbackoff;
	int	hup_dsr, hup_dcd;	/* send hangup upstream? */
	int	dohup;

	int	kinuse;		/* device in use by kernel */

	Rendez	r;
};
static	Uart*	uart[Nuart];
static	int	nuart;

static Dirtab *uartdir;
static int uartndir;

/*
 * means the kernel is using this for debugging output
 */
static char	Ekinuse[] = "device in use by kernel";

/*
 *  default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,
 *  transmit and receive enabled, interrupts disabled.
 */
static void
uartsetup0(Uart *p)
{
	memset(p->sticky, 0, sizeof(p->sticky));
	/*
	 *  set rate to 9600 baud.
	 *  8 bits/character.
	 *  1 stop bit.
	 *  interrupts enabled.
	 */
//	p->sticky[Format] = Bits8;
//	uartwrreg(p, Format, 0);
//	p->sticky[Mctl] |= Inton;
//	uartwrreg(p, Mctl, 0x0);

//	uartsetbaud(p, 9600);

//	p->iq = qopen(4*1024, 0, uartflow, p);
//	p->oq = qopen(4*1024, 0, uartkick, p);
	if(p->iq == nil || p->oq == nil)
		panic("uartsetup0");

	p->ip = p->istage;
	p->ie = &p->istage[Stagesize];
	p->op = p->ostage;
	p->oe = p->ostage;
}

/*
 *  called by main() to create a new duart
 */
void
uartsetup(ulong port, ulong freq, char *name, int type)
{
	Uart *p;

	if(nuart >= Nuart)
		return;

	p = xalloc(sizeof(Uart));
	uart[nuart] = p;
	strcpy(p->name, name);
	p->dev = nuart;
	nuart++;
	p->port = port;
	p->freq = freq;
	p->type = type;
	uartsetup0(p);
}

static void
uartenable(Uart *p)
{
	USED(p);
}

static void
uartdisable(Uart *p)
{
	USED(p);
}

static long
uartstatus(Chan*, Uart *p, void *buf, long n, long offset)
{
	USED(p);
//		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
//		"dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
	return readstr(offset, buf, n, "");
}

static void
setlength(int i)
{
	Uart *p;

	if(i > 0){
		p = uart[i];
		if(p && p->opens && p->iq)
			uartdir[3*i].length = qlen(p->iq);
	} else for(i = 0; i < nuart; i++){
		p = uart[i];
		if(p && p->opens && p->iq)
			uartdir[3*i].length = qlen(p->iq);
	}
}

static void
uartreset(void)
{
	int i;
	Dirtab *dp;

	nuart = Nuart;

	uartndir = 3*nuart;
	uartdir = xalloc(uartndir * sizeof(Dirtab));
	dp = uartdir;
	for(i = 0; i < nuart; i++){
		/* 3 directory entries per port */
		sprint(dp->name, "eia%d", i);
		dp->qid.path = NETQID(i, Ndataqid);
		dp->perm = 0660;
		dp++;
		sprint(dp->name, "eia%dctl", i);
		dp->qid.path = NETQID(i, Nctlqid);
		dp->perm = 0660;
		dp++;
		sprint(dp->name, "eia%dstat", i);
		dp->qid.path = NETQID(i, Nstatqid);
		dp->perm = 0444;
		dp++;
	}

}


static Chan*
uartattach(char *spec)
{
	return devattach('t', spec);
}

static int
uartwalk(Chan *c, char *name)
{
	return devwalk(c, name, uartdir, uartndir, devgen);
}

static void
uartstat(Chan *c, char *dp)
{
	if(NETTYPE(c->qid.path) == Ndataqid)
		setlength(NETID(c->qid.path));
	devstat(c, dp, uartdir, uartndir, devgen);
}

static Chan*
uartopen(Chan *c, int omode)
{
	Uart *p;

	c = devopen(c, omode, uartdir, uartndir, devgen);

	switch(NETTYPE(c->qid.path)){
	case Nctlqid:
	case Ndataqid:
		p = uart[NETID(c->qid.path)];
		if(p->kinuse)
			error(Ekinuse);
		qlock(p);
		if(p->opens++ == 0){
			uartenable(p);
			qreopen(p->iq);
			qreopen(p->oq);
		}
		qunlock(p);
		break;
	}

	return c;
}

static void
uartclose(Chan *c)
{
	Uart *p;

	if(c->qid.path & CHDIR)
		return;
	if((c->flag & COPEN) == 0)
		return;
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
	case Nctlqid:
		p = uart[NETID(c->qid.path)];
		if(p->kinuse)
			error(Ekinuse);
		qlock(p);
		if(--(p->opens) == 0){
			uartdisable(p);
			qclose(p->iq);
			qclose(p->oq);
			p->ip = p->istage;
			p->dcd = p->dsr = p->dohup = 0;
		}
		qunlock(p);
		break;
	}
}

static long
uartread(Chan *c, void *buf, long n, vlong off)
{
	Uart *p;
	ulong offset = off;

	if(c->qid.path & CHDIR){
		setlength(-1);
		return devdirread(c, buf, n, uartdir, uartndir, devgen);
	}

	p = uart[NETID(c->qid.path)];
	if(p->kinuse)
		error(Ekinuse);
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		return qread(p->iq, buf, n);
	case Nctlqid:
		return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
	case Nstatqid:
		return uartstatus(c, p, buf, n, offset);
	}

	return 0;
}

static void
uartctl(Uart *p, char *cmd)
{
	int i, n;
	char *f[32];
	int nf;

	/* let output drain for a while */
	for(i = 0; i < 16 && qlen(p->oq); i++)
		tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125);

	nf = getfields(cmd, f, nelem(f), 1, " \t\n");

	for(i = 0; i < nf; i++){

		if(strncmp(f[i], "break", 5) == 0){
//			uartbreak(p, 0);
			continue;
		}

		n = atoi(f[i]+1);
		switch(*f[i]){
		case 'B':
		case 'b':
//			uartsetbaud(p, n);
			break;
		case 'C':
		case 'c':
//			uartdcdhup(p, n);
			break;
		case 'D':
		case 'd':
//			uartdtr(p, n);
			break;
		case 'E':
		case 'e':
//			uartdsrhup(p, n);
			break;
		case 'f':
		case 'F':
			qflush(p->oq);
			break;
		case 'H':
		case 'h':
			qhangup(p->iq, 0);
			qhangup(p->oq, 0);
			break;
		case 'i':
		case 'I':
//			lock(&p->flock);
//			uartfifo(p, n);
//			unlock(&p->flock);
			break;
		case 'L':
		case 'l':
//			uartbits(p, n);
			break;
		case 'm':
		case 'M':
//			uartmflow(p, n);
			break;
		case 'n':
		case 'N':
			qnoblock(p->oq, n);
			break;
		case 'P':
		case 'p':
//			uartparity(p, *(cmd+1));
			break;
		case 'K':
		case 'k':
//			uartbreak(p, n);
			break;
		case 'R':
		case 'r':
//			uartrts(p, n);
			break;
		case 'Q':
		case 'q':
			qsetlimit(p->iq, n);
			qsetlimit(p->oq, n);
			break;
		case 'T':
		case 't':
//			uartdcdts(p, n);
			break;
		case 'W':
		case 'w':
			/* obsolete */
			break;
		case 'X':
		case 'x':
			ilock(&p->tlock);
			p->xonoff = n;
			iunlock(&p->tlock);
			break;
		}
	}
}

static long
uartwrite(Chan *c, void *buf, long n, vlong)
{
	Uart *p;
	char cmd[32];

	if(c->qid.path & CHDIR)
		error(Eperm);

	p = uart[NETID(c->qid.path)];
	if(p->kinuse)
		error(Ekinuse);

	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		return qwrite(p->oq, buf, n);
	case Nctlqid:
		if(n >= sizeof(cmd))
			n = sizeof(cmd)-1;
		memmove(cmd, buf, n);
		cmd[n] = 0;
		uartctl(p, cmd);
		return n;
	}
}

static void
uartwstat(Chan *c, char *dp)
{
	Dir d;
	Dirtab *dt;

	if(!iseve())
		error(Eperm);
	if(CHDIR & c->qid.path)
		error(Eperm);
	if(NETTYPE(c->qid.path) == Nstatqid)
		error(Eperm);

	dt = &uartdir[3 * NETID(c->qid.path)];
	convM2D(dp, &d);
	d.mode &= 0666;
	dt[0].perm = dt[1].perm = d.mode;
}

Dev uartdevtab = {
	't',
	"uart",

	uartreset,
	devinit,
	uartattach,
	devclone,
	uartwalk,
	uartstat,
	uartopen,
	devcreate,
	uartclose,
	uartread,
	devbread,
	uartwrite,
	devbwrite,
	devremove,
	uartwstat,
};

void
putuartstr(char *str)
{
	Uartregs *ur;

	ur = UART3REGS;
	while(*str){
		/* wait for output ready */
		while(ur->status1 & XmitNotFull)
			;
		ur->data = *str++;

	}
}
.
## diffname bitsy/devuart.c 2000/0905
## diff -e /n/emeliedump/2000/0904/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/0905/sys/src/9/bitsy/devuart.c
504d
501c
		while((ur->status1 & XmitNotFull) == 0)
.
499c
	while(n-- > 0){
.
494c
serialputs(char *str, int n)
.
35a
	/* status register 1 bits */
	XmitBusy = (1 << 0),
.
27c
	ulong	dummyb;
.
25c
	ulong	dummya;
.
## diffname bitsy/devuart.c 2000/0906
## diff -e /n/emeliedump/2000/0905/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/0906/sys/src/9/bitsy/devuart.c
500c
	ur = uart3regs;
.
32a
static Uartregs *uart3regs = UART3REGS;

.
31d
## diffname bitsy/devuart.c 2000/0907
## diff -e /n/emeliedump/2000/0906/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/0907/sys/src/9/bitsy/devuart.c
32c
Uartregs *uart3regs = UART3REGS;
.
18d
## diffname bitsy/devuart.c 2000/0928
## diff -e /n/emeliedump/2000/0907/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/0928/sys/src/9/bitsy/devuart.c
506a
	while((ur->status1 & XmitBusy))
		;
.
## diffname bitsy/devuart.c 2000/0930
## diff -e /n/emeliedump/2000/0928/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/0930/sys/src/9/bitsy/devuart.c
507c
	while((ur->status1 & Tbusy))
.
503c
		while((ur->status1 & Tnotfull) == 0)
.
494a
static void
uartsetbaud(Uart *p, int rate)
{
	ulong brconst;

	if(rate <= 0)
		return;

	brconst = (p->freq+8*rate-1)/(16*rate) - 1;
	p->regs->ctl[1] = (brconst>>8) & 0xf;
	p->regs->ctl[2] = brconst;

	p->baud = rate;
}

.
205c
	uartsetup(uart3regs, ;
.
198a
/*
 *  setup the '#t' directory
 */
.
171c
	p->sticky[3] &= ~(Rintena|Tintena);
	p->regs->ctl[3] = p->sticky[3];
.
167a
/*
 *  disable interrupts. clear DTR, and RTS
 */
.
165c
	p->sticky[3] |= Rintena|Tintena;
	p->regs->ctl[3] = p->sticky[3];
.
143,161d
141c
 *  enable a port's interrupts.  set DTR and RTS
.
132c
		panic("uartsetup");
.
127,130c
	p->iq = qopen(4*1024, 0, uartflow, p);
	p->oq = qopen(4*1024, 0, uartkick, p);
.
122,125c
	p->sticky[0] = Bits8;
	p->regs->ctl[0] = p->sticky[0];
	p->sticky[3] = Rena|Tena;
	p->regs->ctl[3] = p->sticky[3];
	uartsetbaud(p, 115200);
.
120c
	 *  interrupts disabled.
.
117c
	 *  set rate to 115200 baud.
.
115a

.
114a
	Uart *p;

	if(nuart >= Nuart)
		return;

	p = xalloc(sizeof(Uart));
	uart[nuart] = p;
	strcpy(p->name, name);
	p->dev = nuart++;
	p->port = port;
	p->freq = freq;
	p->regs = regs;

.
113c
uartsetup(Uartregs *regs, ulong freq, char *name)
.
109,110c
 *  define a Uart.
.
107a
static void	uartsetbaud(Uart *p, int rate);

.
104c
 * means the kernel is using this as a console
.
69,72d
60c
	int	parity;			/* parity errors */
.
57d
52,54c
	uchar	sticky[4];		/* sticky write register values */
.
46a
	Uartregs	*regs;
.
45a
	int	dev;
.
40a
Uartregs *uart3regs = UART3REGS;

.
36,38c
	/* ctl[0] bits */
	Parity=		1<<0,
	Even=		1<<1,
	Stop1=		0<<2,
	Stop2=		1<<2,
	Bits7=		0<<3,
	Bits8=		1<<3,
	SCE=		1<<4,	/* synchronous clock enable */
	RCE=		1<<5,	/* rx on falling edge of clock */
	TCE=		1<<6,	/* tx on falling edge of clock */

	/* ctl[3] bits */
	Rena=		1<<0,	/* receiver enable */
	Tena=		1<<1,	/* transmitter enable */
	Break=		1<<2,	/* force TXD3 low */
	Rintena=	1<<3,	/* enable receive interrupt */
	Tintena=	1<<4,	/* enable transmitter interrupt */
	Loopback=	1<<5,	/* loop back data */

	/* data bits */
	DEparity=	1<<8,	/* parity error */
	DEframe=		1<<9,	/* framing error */
	DEoverrun=	1<<10,	/* overrun error */

	/* status0 bits */
	Tint=		1<<0,	/* transmit fifo half full interrupt */
	Rint0=		1<<1,	/* receiver fifo 1/3-2/3 full */
	Rint1=		1<<2,	/* receiver fifo not empty and receiver idle */
	Breakstart=	1<<3,
	Breakend=	1<<4,
	Fifoerror=	1<<5,	/* fifo error */

	/* status1 bits */
	Tbusy=		1<<0,	/* transmitting */
	Rnotempty=	1<<1,	/* receive fifo not empty */
	Tnotfull=	1<<2,	/* transmit fifo not full */
	ParityError=	1<<3,
	FrameError=	1<<4,
	Overrun=	1<<5,
.
31,33d
20,23c
	ulong	ctl[4];
.
## diffname bitsy/devuart.c 2000/1002
## diff -e /n/emeliedump/2000/0930/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1002/sys/src/9/bitsy/devuart.c
537a
}

/*
 *  turn on/off rts
 */
static void
uartrts(Uart *p, int on)
{
}

/*
 *  restart input if it's off
 */
static void
uartflow(void *v)
{
	Uart *p;

	p = v;
	if(p->modem){
		uartrts(p, 1);
		ilock(&p->rlock);
		p->haveinput = 1;
		iunlock(&p->rlock);
	}
}

/*
 *  restart output if not blocked and OK to send
 */
static void
uartkick0(void *v)
{
	int i;
	Uart *p;

	p = v;
	if(p->cts == 0 || p->blocked)
		return;

	/*
	 *  128 here is an arbitrary limit to make sure
	 *  we don't stay in this loop too long.  If the
	 *  chips output queue is longer than 128, too
	 *  bad -- presotto
	 */
	for(i = 0; i < 128; i++){
//		if(!(uartrdreg(p, Lstat) & Outready))
//			break;
//		if(p->op >= p->oe && stageoutput(p) == 0)
//			break;
//		outb(p->port + Data, *(p->op++));
	}
}

static void
uartkick(void *v)
{
	Uart *p;

	p = v;
	ilock(&p->tlock);
	uartkick0(p);
	iunlock(&p->tlock);
.
524a
/*
 *  set the buad rate
 */
.
235,236d
152d
135a
static void	uartflow(void *v);
static void	uartkick0(void *v);
static void	uartkick(void *v);
static void	uartrts(Uart *p, int on);
.
## diffname bitsy/devuart.c 2000/1006
## diff -e /n/emeliedump/2000/1002/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1006/sys/src/9/bitsy/devuart.c
605a
}

static void
uartintr(Ureg*, void *x)
{
	Uart *p;

	p = x;
.
548c
uartrts(Uart*, int)
.
256d
191a
	intrenable(IRQuart3, uartintr, p, p->name);
.
184a
 *  setup all uarts (called early by main() to allow debugging output to
 *  a serial port)
 */
void
uartsetup(void)
{
	uart3regs = mapspecial(UART3REGS, 64);
	uartsetup0(uart3regs, 36864000, "serialport3");
}

/*
.
145c
uartsetup0(Uartregs *regs, ulong freq, char *name)
.
139a
static void	uartintr(Ureg*, void*);
.
## diffname bitsy/devuart.c 2000/1007
## diff -e /n/emeliedump/2000/1006/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1007/sys/src/9/bitsy/devuart.c
590,641c
	n = qconsume(p->oq, p->ostage, Stagesize);
	if(n <= 0)
		return 0;
	p->op = p->ostage;
	p->oe = p->ostage + n;
	return n;
.
587,588c
	int n;
.
584,585c
int
uartstageoutput(Uart *p)
.
582c
 *  put some bytes into the local queue to avoid calling
 *  qconsume for every character
.
570,578c
	p->dcdts = n;
.
568c
uartdcdts(Uart *p, int n)
.
565c
 *  save dcd timestamps for gps clock
.
561a
	p->hup_dcd = n;
.
560c
uartdcdhup(Uart *p, int n)
.
556,558d
544,553c
	p->hup_dsr = n;
.
542c
uartdsrhup(Uart *p, int n)
.
539c
 * decide if we should hangup when dsr or dcd drops.
.
456c
			uartdcdts(p, n);
.
447c
			(*p->phys->rts)(p, n);
.
443c
			(*p->phys->dobreak)(p, n);
.
439c
			(*p->phys->parity)(p, *(cmd+1));
.
431c
			(*p->phys->modemctl)(p, n);
.
427c
			(*p->phys->bits)(p, n);
.
421,423d
408c
			uartdsrhup(p, n);
.
404c
			(*p->phys->dtr)(p, n);
.
400c
			uartdcdhup(p, n);
.
396c
			(*p->phys->baud)(p, n);
.
388c
			(*p->phys->dobreak)(p, 0);
.
366c
		return (*p->phys->status)(p, buf, n, offset);
.
335c
			(*p->phys->disable)(p);
.
307c
			(*p->phys->enable)(p, 1);
.
200,226d
185,198d
182a
	return p;
.
174,175c
	p->iq = qopen(4*1024, 0, p->phys->flow, p);
	p->oq = qopen(4*1024, 0, p->phys->kick, p);
.
168,172c
	(*p->phys->bits)(p, 8);
	(*p->phys->stop)(p, 1);
	(*p->phys->baud)(p, 115200);
	(*p->phys->enable)(p, 0);
.
166c
	 *  enabled with interrupts disabled.
.
160,161d
158a
	p->phys = phys;
.
151c
		return nil;
.
145,146c
Uart*
uartsetup(PhysUart *phys, void *regs, ulong freq, char *name)
.
143c
 *  define a Uart
.
135,140c
static void	uartdcdhup(Uart*, int);
static void	uartdcdts(Uart*, int);
static void	uartdsrhup(Uart*, int);
.
17,123d
11,15d
## diffname bitsy/devuart.c 2000/1015
## diff -e /n/emeliedump/2000/1007/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1015/sys/src/9/bitsy/devuart.c
416a
}

/*
 *  restart output
 */
void
uartkick(void *v)
{
	Uart *p = v;

	ilock(&p->tlock);
	(*p->phys->kick)(p);
	iunlock(&p->tlock);
}

/*
 *  streceiveage a character at interrupt time
 */
void
uartrecv(Uart *p,  char ch)
{
	/* software flow control */
	if(p->xonoff){
		if(ch == CTLS){
			p->blocked = 1;
		}else if (ch == CTLQ){
			p->blocked = 0;
			p->ctsbackoff = 2; /* clock gets output going again */
		}
	}

	/* receive the character */
	if(p->putc)
		p->putc(p->iq, ch);
	else {
		ilock(&p->rlock);
		if(p->ip < p->ie)
			*p->ip++ = ch;
		p->haveinput = 1;
		iunlock(&p->rlock);
	}
}

/*
 *  we save up input characters till clock time to reduce
 *  per character interrupt overhead.
 *
 *  There's also a bit of code to get a stalled print going.
 *  It shouldn't happen, but it does.  Obviously I don't
 *  understand something.  Since it was there, I bundled a
 *  restart after flow control with it to give some hysteresis
 *  to the hardware flow control.  This makes compressing
 *  modems happier but will probably bother something else.
 *	 -- presotto
 */
static void
uartclock(void)
{
	int n;
	Uart *p;

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

		/* this amortizes cost of qproduce to many chars */
		if(p->haveinput){
			ilock(&p->rlock);
			if(p->haveinput){
				n = p->ip - p->istage;
				if(n > 0 && p->iq){
					if(n > Stagesize)
						panic("uartclock");
					if(qproduce(p->iq, p->istage, n) < 0)
						(*p->phys->rts)(p, 0);
					else
						p->ip = p->istage;
				}
				p->haveinput = 0;
			}
			iunlock(&p->rlock);
		}
		if(p->dohup){
			ilock(&p->rlock);
			if(p->dohup){
				qhangup(p->iq, 0);
				qhangup(p->oq, 0);
			}
			p->dohup = 0;
			iunlock(&p->rlock);
		}

		/* this adds hysteresis to hardware/software flow control */
		if(p->ctsbackoff){
			ilock(&p->tlock);
			if(p->ctsbackoff){
				if(--(p->ctsbackoff) == 0)
					(*p->phys->kick)(p);
			}
			iunlock(&p->tlock);
		}
	}
}

/*
 *  configure a uart port as a console or a mouse
 */
void
uartspecial(Uart *p, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int))
{
	uartenable(p);
	if(baud)
		(*p->phys->baud)(p, baud);
	p->putc = putc;
	if(in)
		*in = p->iq;
	if(out)
		*out = p->oq;
	p->opens++;
.
402a
 *  restart input if it's off
 */
static void
uartflow(void *v)
{
	Uart *p;

	p = v;
	if(p->modem){
		(*p->phys->rts)(p, 1);
		ilock(&p->rlock);
		p->haveinput = 1;
		iunlock(&p->rlock);
	}
}

/*
.
178c
			uartdisable(p);
.
150c
			uartenable(p);
.
111a

	addclock0link(uartclock);
.
69a
uartenable(Uart *p)
{
	Uart **l;

	p->hup_dsr = p->hup_dcd = 0;
	p->dsr = p->dcd = 0;

	/* assume we can send */
	p->cts = 1;

	(*p->phys->enable)(p, 1);

	lock(&uartalloc);
	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
		if(*l == p)
			break;
	}
	if(*l == 0){
		p->elist = uartalloc.elist;
		uartalloc.elist = p;
	}
	p->enabled = 1;
	unlock(&uartalloc);
}
static void
uartdisable(Uart *p)
{
	Uart **l;

	(*p->phys->disable)(p);

	lock(&uartalloc);
	for(l = &uartalloc.elist; *l; l = &(*l)->elist){
		if(*l == p){
			*l = p->elist;
			break;
		}
	}
	p->enabled = 0;
	unlock(&uartalloc);
}

static void
.
68a
/*
 *  enable/diable uart and add/remove to list of enabled uarts
 */
.
57,58c
	p->iq = qopen(4*1024, 0, uartflow, p);
	p->oq = qopen(4*1024, 0, uartkick, p);
.
25a
static void	uartenable(Uart*);
static void	uartdisable(Uart*);
static void	uartclock(void);
static void	uartflow(void*);
.
22a
struct Uartalloc {
	Lock;
	Uart *elist;	/* list of enabled interfaces */
} uartalloc;

.
## diffname bitsy/devuart.c 2000/1019
## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1019/sys/src/9/bitsy/devuart.c
578d
572,576c
			qhangup(p->iq, 0);
			qhangup(p->oq, 0);
.
570a

		/* hang up if requested */
.
569d
567c
			} else {
				if(qproduce(p->iq, p->ir, iw-p->ir) < 0)
					(*p->phys->rts)(p, 0);
				p->ir = iw;
.
564,565c
					p->ir = iw;
.
555,562c
		if(p->iw != p->ir){
			iw = p->iw;
			if(iw < p->ir){
				if(qproduce(p->iq, p->ir, p->ie-p->ir) < 0){
					(*p->phys->rts)(p, 0);
					p->ir = p->istage;
				} else {
					if(qproduce(p->iq, p->istage, iw-p->istage) < 0)
.
550a
	uchar *iw;
.
549d
537,544d
526,530c
		next = p->iw + 1;
		if(next == p->ie)
			next = p->istage;
		if(next != p->ir){
			*p->iw = ch;
			p->iw = next;
		}
.
511a
	uchar *next;

.
470,473d
468c
	if(p->modem)
.
238c
			p->ir = p->iw = p->istage;
.
71c
	p->ir = p->istage;
	p->iw = p->istage;
.
47a
	memset(p, 0, sizeof(*p));
.
## diffname bitsy/devuart.c 2000/1020
## diff -e /n/emeliedump/2000/1019/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1020/sys/src/9/bitsy/devuart.c
564a
			if(qproduce(p->iq, p->ir, iw-p->ir) < 0)
				(*p->phys->rts)(p, 0);
			p->ir = iw;
.
554,563c
				p->ir = p->istage;
.
552c
				if(qproduce(p->iq, p->ir, p->ie-p->ir) < 0)
.
## diffname bitsy/devuart.c 2000/1121
## diff -e /n/emeliedump/2000/1020/sys/src/9/bitsy/devuart.c /n/emeliedump/2000/1121/sys/src/9/bitsy/devuart.c
10a
enum
{
	Nuart = 4,

	/* soft flow control chars */
	CTLS= 023,
	CTLQ= 021,
};
.
## diffname bitsy/devuart.c 2001/0529 # deleted
## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/devuart.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devuart.c
1,603d

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].