Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/power/devduart.c

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


## diffname power/devduart.c 1991/0607
## diff -e /dev/null /n/bootesdump/1991/0607/sys/src/9/power/devduart.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

int	duartacr;
int	duartimr;

void	duartputs(IOQ*, char*, int);
void	iprint(char*, ...);

#define	PAD	15	/* registers are well-spaced */

/*
 * Register set for half the duart.  There are really two sets.
 */
struct Duart{
	uchar	mr1_2,		/* Mode Register Channels 1 & 2 */
		pad0[PAD];
	uchar	sr_csr,		/* Status Register/Clock Select Register */
		pad1[PAD];
	uchar	cmnd,		/* Command Register */
		pad2[PAD];
	uchar	data,		/* RX Holding / TX Holding Register */
		pad3[PAD];
	uchar	ipc_acr,	/* Input Port Change/Aux. Control Register */
		pad4[PAD];
	uchar	is_imr,		/* Interrupt Status/Interrupt Mask Register */
		pad5[PAD];
	uchar	ctur,		/* Counter/Timer Upper Register */
		pad6[PAD];
	uchar	ctlr,		/* Counter/Timer Lower Register */
		pad7[PAD];
};
#define	ppcr	is_imr		/* in the second register set */

#define DBD75		0
#define DBD110		1
#define DBD38400	2
#define DBD150		3
#define DBD300		4
#define DBD600		5
#define DBD1200		6
#define DBD2000		7
#define DBD2400		8
#define DBD4800		9
#define DBD1800		10
#define DBD9600		11
#define DBD19200	12

enum{
	CHAR_ERR	=0x00,	/* MR1x - Mode Register 1 */
	EVEN_PAR	=0x00,
	ODD_PAR		=0x04,
	NO_PAR		=0x10,
	CBITS8		=0x03,
	CBITS7		=0x02,
	CBITS6		=0x01,
	CBITS5		=0x00,
	NORM_OP		=0x00,	/* MR2x - Mode Register 2 */
	TWOSTOPB	=0x0F,
	ONESTOPB	=0x07,
	ENB_RX		=0x01,	/* CRx - Command Register */
	DIS_RX		=0x02,
	ENB_TX		=0x04,
	DIS_TX		=0x08,
	RESET_MR 	=0x10,
	RESET_RCV  	=0x20,
	RESET_TRANS  	=0x30,
	RESET_ERR  	=0x40,
	RESET_BCH	=0x50,
	STRT_BRK	=0x60,
	STOP_BRK	=0x70,
	RCV_RDY		=0x01,	/* SRx - Channel Status Register */
	FIFOFULL	=0x02,
	XMT_RDY		=0x04,
	XMT_EMT		=0x08,
	OVR_ERR		=0x10,
	PAR_ERR		=0x20,
	FRM_ERR		=0x40,
	RCVD_BRK	=0x80,
	IM_IPC		=0x80,	/* IMRx/ISRx - Interrupt Mask/Interrupt Status */
	IM_DBB		=0x40,
	IM_RRDYB	=0x20,
	IM_XRDYB	=0x10,
	IM_CRDY		=0x08,
	IM_DBA		=0x04,
	IM_RRDYA	=0x02,
	IM_XRDYA	=0x01,
	BD38400		=0xCC|0x0000,
	BD19200		=0xCC|0x0100,
	BD9600		=0xBB|0x0000,
	BD4800		=0x99|0x0000,
	BD2400		=0x88|0x0000,
	BD1200		=0x66|0x0000,
	BD300		=0x44|0x0000,

	Maxport		=8,
};

/*
 *  requests to perform on a duart
 */
enum {
	Dnone=	0,
	Dbaud,
	Dbreak,
	Ddtr,
	Dprint,
	Dena,
	Dstate,
};

/*
 *  software info for a serial duart interface
 */
typedef struct Duartport	Duartport;
struct Duartport
{
	QLock;
	int	printing;	/* true if printing */
	Duart	*duart;		/* device */
	int	inited;
	int	c;		/* character to restart output */
	int	op;		/* operation requested */
	int	val;		/* value of operation */
	Rendez	opr;		/* waiot here for op to complete */

	/* console interface */
	int	nostream;	/* can't use the stream interface */
	IOQ	*iq;		/* input character queue */
	IOQ	*oq;		/* output character queue */

	/* stream interface */
	Queue	*wq;		/* write queue */
	Rendez	r;		/* kproc waiting for input */
	Alarm	*a;		/* alarm for waking the kernel process */
	int	delay;		/* between character input and waking kproc */
 	int	kstarted;	/* kproc started */
	uchar	delim[256/8];	/* characters that act as delimiters */
};
Duartport	duartport[Maxport];	/* max possible */

/*
 *  configure a duart port, default is 9600 baud, 8 bits/char, 1 stop bit,
 *  no parity
 */
void
duartsetup(Duartport *dp)
{
	Duart *duart;

	duart = dp->duart;

	duart->cmnd = RESET_RCV|DIS_TX|DIS_RX;
	duart->cmnd = RESET_TRANS;
	duart->cmnd = RESET_ERR;
	duart->cmnd = STOP_BRK;

	duart->ipc_acr = 0x80;		/* baud-rate set 2 */
	duart->cmnd = RESET_MR;
	duart->mr1_2 = NO_PAR|CBITS8;
	duart->mr1_2 = ONESTOPB;
	duart->sr_csr = (DBD9600<<4)|DBD9600;
	duart->is_imr = IM_RRDYA|IM_XRDYA;
	duart->cmnd = ENB_TX|ENB_RX;
}

/*
 *  init the duart on the current processor
 */
void
duartinit(void)
{
	Duartport *dp;

	dp = &duartport[2*m->machno];
	if(dp->inited)
		return;
	dp->inited = 1;

	dp->duart = DUARTREG;
	duartsetup(dp);
	dp++;
	dp->duart = DUARTREG+1;
	duartsetup(dp);
}

/*
 *  enable a duart port
 */
void
duartenable(Duartport *dp)
{
	dp->duart->cmnd = ENB_TX|ENB_RX;
}

void
duartenable0(void)
{
	DUARTREG->cmnd = ENB_TX|ENB_RX;
}

void
duartbaud(Duartport *dp, int b)
{
	int x = 0;

	switch(b){
	case 38400:
		x = BD38400;
		break;
	case 19200:
		x = BD19200;
		break;
	case 9600:
		x = BD9600;
		break;
	case 4800:
		x = BD4800;
		break;
	case 2400:
		x = BD2400;
		break;
	case 1200:
		x = BD1200;
		break;
	case 300:
		x = BD300;
		break;
	default:
		errors("bad baud rate");
	}
	if(x & 0x0100)
		dp->duart->ipc_acr = duartacr |= 0x80;
	else
		dp->duart->ipc_acr = duartacr &= ~0x80;
	dp->duart->sr_csr = x;
}

void
duartdtr(Duartport *dp, int val)
{
	if (val)
		dp->duart->ctlr=0x01;
	else
		dp->duart->ctur=0x01;
}

void
duartbreak(Duartport *dp, int val)
{
	Duart *duart;

	duart = dp->duart;
	if (val){
		duart->is_imr = duartimr &= ~IM_XRDYB;
		duart->cmnd = STRT_BRK|ENB_TX;
	} else {
		duart->cmnd = STOP_BRK|ENB_TX;
		duart->is_imr = duartimr |= IM_XRDYB;
	}
}

/*
 *  do anything requested for this CPU's duarts
 */
void
duartslave0(Duartport *dp)
{
	switch(dp->op){
	case Ddtr:
		duartbaud(dp, dp->val);
		break;
	case Dbaud:
		duartdtr(dp, dp->val);
		break;
	case Dbreak:
		duartbreak(dp, dp->val);
		break;
	case Dprint:
		dp->duart->cmnd = ENB_TX;
		dp->duart->data = dp->val;
		break;
	case Dena:
		duartenable(dp);
		break;
	case Dstate:
		dp->val = dp->duart->is_imr;
		break;
	}
	dp->op = Dnone;
	wakeup(&dp->opr);
}
void
duartslave(void)
{
	Duartport *dp;

	dp = &duartport[2*m->machno];
	if(dp->op != Dnone)
		duartslave0(dp);
	dp++;
	if(dp->op != Dnone)
		duartslave0(dp);
}

duartrintr(Duartport *dp)
{
	Duart *duart;
	IOQ *cq;
	int status;
	char ch;

	duart = dp->duart;
	status = duart->sr_csr;
	ch = duart->data;
	if(status & (FRM_ERR|OVR_ERR|PAR_ERR))
		duart->cmnd = RESET_ERR;

	cq = dp->iq;
	if(cq->putc)
		(*cq->putc)(cq, ch);
	else {
		putc(cq, ch);
		if(dp->delim[ch/8] & (1<<(ch&7)) )
			wakeup(&cq->r);
	}
}

duartxintr(Duartport *dp)
{
	Duart *duart;
	IOQ *cq;
	char ch;

	cq = dp->oq;
	lock(cq);
	ch = getc(cq);
	duart = dp->duart;
	if(ch < 0){
		dp->printing = 0;
		wakeup(&cq->r);
		duart->cmnd = DIS_TX;
	} else
		duart->data = ch;
	unlock(cq);
}

void
duartintr(void)
{
	int cause, status, c;
	Duart *duart;
	Duartport *dp;

	dp = &duartport[2*m->machno];
	duart = dp->duart;
	cause = duart->is_imr;
	/*
	 * I can guess your interrupt.
	 */
	/*
	 * Is it 1?
	 */
	if(cause & IM_RRDYA)
		duartrintr(dp);
	/*
	 * Is it 2?
	 */
	if(cause & IM_XRDYA)
		duartxintr(dp);
	/*
	 * Is it 3?
	 */
	if(cause & IM_RRDYB)
		duartrintr(dp+1);
	/*
	 * Is it 4?
	 */
	if(cause & IM_XRDYB)
		duartxintr(dp+1);
}

/*
 *  processor 0 only
 */
int
duartrawputc(int c)
{
	Duart *duart;
	int i;

	duart = DUARTREG;
	if(c == '\n')
		duartrawputc('\r');
	duart->cmnd = ENB_TX;
	i = 0;
	while((duart->sr_csr&XMT_RDY) == 0)
		if(++i >= 1000000){
			duartsetup(&duartport[0]);
			for(i=0; i<100000; i++)
				;
			break;
		}
	duart->data = c;
	if(c == '\n')
		for(i=0; i<100000; i++)
			;
	return c;
}
void
duartrawputs(char *s)
{
	int i;
	while(*s){
		duartrawputc(*s++);
	}
	for(i=0; i < 1000000; i++)
		;
}
void
iprint(char *fmt, ...)
{
	char buf[1024];
	long *arg;

	arg = (long*)(&fmt+1);
	sprint(buf, fmt, *arg, *(arg+1), *(arg+2), *(arg+3));
	duartrawputs(buf);
}

/*
 *  Queue n characters for output; if queue is full, we lose characters.
 *  Get the output going if it isn't already.
 */
void
duartputs(IOQ *cq, char *s, int n)
{
	int ch, x;
	Duartport *dp;
	Duart *duart;

	x = splhi();
	lock(cq);
	puts(cq, s, n);
	dp = cq->ptr;
	if(dp->printing == 0){
		ch = getc(cq);
		if(ch >= 0){
			dp->printing = 1;
			dp->val = ch;
			dp->op = Dprint;
		}
	}
	unlock(cq);
	splx(x);
}

/*
 *  set up an duart port as something other than a stream
 */
void
duartspecial(int port, IOQ *oq, IOQ *iq, int baud)
{
	Duartport *dp = &duartport[port];

	dp->nostream = 1;
	if(oq){
		dp->oq = oq;
		dp->oq->puts = duartputs;
		dp->oq->ptr = dp;
	}
	if(iq){
		dp->iq = iq;
		dp->iq->ptr = dp;
	}
	duartenable(dp);
	duartbaud(dp, baud);
}

static void	duarttimer(Alarm*);
static int	duartputc(IOQ *, int);
static void	duartstopen(Queue*, Stream*);
static void	duartstclose(Queue*);
static void	duartoput(Queue*, Block*);
static void	duartkproc(void *);
Qinfo duartinfo =
{
	nullput,
	duartoput,
	duartstopen,
	duartstclose,
	"duart"
};

/*
 *  wakeup the helper process to do input
 */
static void
duarttimer(Alarm *a)
{
	Duartport *dp = a->arg;

	cancel(a);
	dp->a = 0;
	wakeup(&dp->iq->r);
}

static int
duartputc(IOQ *cq, int ch)
{
	Duartport *dp = cq->ptr; int r;

	r = putc(cq, ch);

	/*
	 *  pass upstream within dp->delay milliseconds
	 */
	if(dp->a==0){
		if(dp->delay == 0)
			wakeup(&cq->r);
		else
			dp->a = alarm(dp->delay, duarttimer, dp);
	}
	return r;
}

static void
duartstopen(Queue *q, Stream *s)
{
	Duartport *dp;
	char name[NAMELEN];

	dp = &duartport[s->id];

	qlock(dp);
	dp->wq = WR(q);
	WR(q)->ptr = dp;
	RD(q)->ptr = dp;
	dp->delay = 64;
	dp->iq->putc = duartputc;
	qunlock(dp);

	/* start with all characters as delimiters */
	memset(dp->delim, 1, sizeof(dp->delim));
	
	if(dp->kstarted == 0){
		dp->kstarted = 1;
		sprint(name, "duart%d", s->id);
		kproc(name, duartkproc, dp);
	}
}

static void
duartstclose(Queue *q)
{
	Duartport *dp = q->ptr;

	qlock(dp);
	dp->wq = 0;
	dp->iq->putc = 0;
	WR(q)->ptr = 0;
	RD(q)->ptr = 0;
	qunlock(dp);
}

static int
opdone(void *x)
{
	Duartport *dp = x;

	return dp->op == Dnone;
}
static void
duartoput(Queue *q, Block *bp)
{
	Duartport *dp = q->ptr;
	IOQ *cq;
	int n, m;

	if(dp == 0){
		freeb(bp);
		return;
	}
	cq = dp->oq;
	if(waserror()){
		freeb(bp);
		nexterror();
	}
	if(bp->type == M_CTL){
		qlock(dp);
		while (cangetc(cq))	/* let output drain */
			sleep(&cq->r, cangetc, cq);
		n = strtoul((char *)(bp->rptr+1), 0, 0);
		switch(*bp->rptr){
		case 'B':
		case 'b':
			dp->val = n;
			dp->op = Dbaud;
			sleep(&dp->opr, opdone, dp);
			break;
		case 'D':
		case 'd':
			dp->val = n;
			dp->op = Ddtr;
			sleep(&dp->opr, opdone, dp);
			break;
		case 'K':
		case 'k':
			dp->val = 1;
			dp->op = Dbreak;
			sleep(&dp->opr, opdone, dp);
			tsleep(&dp->opr, return0, 0, n);
			dp->val = 0;
			dp->op = Dbreak;
			sleep(&dp->opr, opdone, dp);
			break;
		case 'R':
		case 'r':
			/* can't control? */
			break;
		case 'W':
		case 'w':
			if(n>=0 && n<1000)
				dp->delay = n;
			break;
		}
		qunlock(dp);
	}else while((m = BLEN(bp)) > 0){
		while ((n = canputc(cq)) == 0){
			kprint(" duartoput: sleeping\n");
			sleep(&cq->r, canputc, cq);
		}
		if(n > m)
			n = m;
		(*cq->puts)(cq, bp->rptr, n);
		bp->rptr += n;
	}
	freeb(bp);
	poperror();
}

/*
 *  process to send bytes upstream for a port
 */
static void
duartkproc(void *a)
{
	Duartport *dp = a;
	IOQ *cq = dp->iq;
	Block *bp;
	int n;

loop:
	while ((n = cangetc(cq)) == 0)
		sleep(&cq->r, cangetc, cq);
	qlock(dp);
	if(dp->wq == 0){
		cq->out = cq->in;
	}else{
		bp = allocb(n);
		bp->flags |= S_DELIM;
		bp->wptr += gets(cq, bp->wptr, n);
		PUTNEXT(RD(dp->wq), bp);
	}
	qunlock(dp);
	goto loop;
}

Dirtab *duartdir;
int nduartport;

/*
 *  allocate the queues if no one else has
 */
void
duartreset(void)
{
	Duartport *dp;
	int i;

	/*
 	 *  allocate the directory and fill it in
	 */
	nduartport = 2*conf.nmach;
	duartdir = ialloc(nduartport*2*sizeof(Dirtab), 0);
	for(i = 0; i < nduartport; i++){
		sprint(duartdir[2*i].name, "tty%d", i);
		sprint(duartdir[2*i+1].name, "tty%dctl", i);
		duartdir[2*i].length = duartdir[2*i+1].length = 0;
		duartdir[2*i].perm = duartdir[2*i+1].perm = 0666;
		duartdir[2*i].qid.path = STREAMQID(i, Sdataqid);
		duartdir[2*i+1].qid.path = STREAMQID(i, Sctlqid);
	}

	/*
	 *  allocate queues for any stream interfaces
	 */
	for(dp = duartport; dp < &duartport[nduartport]; dp++){
		if(dp->nostream)
			continue;

		dp->iq = ialloc(sizeof(IOQ), 0);
		initq(dp->iq);
		dp->iq->ptr = dp;

		dp->oq = ialloc(sizeof(IOQ), 0);
		initq(dp->oq);
		dp->oq->ptr = dp;
		dp->oq->puts = duartputs;
	}
}

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

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

int
duartwalk(Chan *c, char *name)
{
	return devwalk(c, name, duartdir, 2*nduartport, devgen);
}

void
duartstat(Chan *c, char *dp)
{
	switch(STREAMTYPE(c->qid.path)){
	case Sdataqid:
		streamstat(c, dp, "tty0");
		break;
	default:
		devstat(c, dp, duartdir, 2*nduartport, devgen);
		break;
	}
}

Chan*
duartopen(Chan *c, int omode)
{
	Duartport *dp;

	switch(STREAMTYPE(c->qid.path)){
	case Sdataqid:
	case Sctlqid:
		dp = &duartport[STREAMID(c->qid.path)];
		break;
	default:
		dp = 0;
		break;
	}

	if(dp && dp->nostream)
		errors("in use");

	if((c->qid.path & CHDIR) == 0)
		streamopen(c, &duartinfo);
	return devopen(c, omode, duartdir, 2*nduartport, devgen);
}

void
duartcreate(Chan *c, char *name, int omode, ulong perm)
{
	errors("only God can create a tty");
}

void
duartclose(Chan *c)
{
	if(c->stream)
		streamclose(c);
}

long
duartread(Chan *c, void *buf, long n, ulong offset)
{
	Duartport *dp;

	if(c->qid.path&CHDIR)
		return devdirread(c, buf, n, duartdir, 2*nduartport, devgen);

	switch(STREAMTYPE(c->qid.path)){
	case Sdataqid:
		return streamread(c, buf, n);
	case Sctlqid:
		if(offset)
			return 0;
		dp = &duartport[STREAMID(c->qid.path)];
		qlock(dp);
		dp->op = Dstate;
		sleep(&dp->opr, opdone, dp);
		*(uchar *)buf = dp->val;
		qunlock(dp);
		return 1;
	}

	errors("no such duart type");
}

long
duartwrite(Chan *c, void *va, long n, ulong offset)
{
	return streamwrite(c, va, n, 0);
}

void
duartremove(Chan *c)
{
	errors("can't remove a duart");
}

void
duartwstat(Chan *c, char *dp)
{
	errors("can't write a duart");
}

int
duartactive(void)
{
	int i;

	for(i = 0; i < nduartport; i++)
		if(duartport[i].printing)
			return 1;
	return 0;                                                                         }
.
## diffname power/devduart.c 1991/0727
## diff -e /n/bootesdump/1991/0607/sys/src/9/power/devduart.c /n/bootesdump/1991/0727/sys/src/9/power/devduart.c
478a

		/*
		 *  Stupid HACK to undo a stupid hack
		 */ 
		zq = &kbdq;
		if(iq == zq)
			kbdq.putc = kbdcr2nl;
.
468a
	IOQ *zq;
.
## diffname power/devduart.c 1991/1113
## diff -e /n/bootesdump/1991/0727/sys/src/9/power/devduart.c /n/bootesdump/1991/1113/sys/src/9/power/devduart.c
844c
	return 0;                                                             }
.
## diffname power/devduart.c 1991/1115
## diff -e /n/bootesdump/1991/1113/sys/src/9/power/devduart.c /n/bootesdump/1991/1115/sys/src/9/power/devduart.c
782c
	errors(Eperm);
.
748c
		streamstat(c, dp, "eia0");
.
699,700c
		sprint(duartdir[2*i].name, "eia%d", i);
		sprint(duartdir[2*i+1].name, "eia%dctl", i);
.
## diffname power/devduart.c 1991/1120
## diff -e /n/bootesdump/1991/1115/sys/src/9/power/devduart.c /n/bootesdump/1991/1120/sys/src/9/power/devduart.c
782c
	error(Eperm);
.
6a
#include	"errno.h"
.
## diffname power/devduart.c 1991/1214
## diff -e /n/bootesdump/1991/1120/sys/src/9/power/devduart.c /n/bootesdump/1991/1214/sys/src/9/power/devduart.c
845c
	return 0;
}
.
833a
	USED(c);
.
827a
	USED(c);
.
782a
	USED(c);
.
## diffname power/devduart.c 1992/0111
## diff -e /n/bootesdump/1991/1214/sys/src/9/power/devduart.c /n/bootesdump/1992/0111/sys/src/9/power/devduart.c
7c
#include	"../port/error.h"
.
## diffname power/devduart.c 1992/0114
## diff -e /n/bootesdump/1992/0111/sys/src/9/power/devduart.c /n/bootesdump/1992/0114/sys/src/9/power/devduart.c
837c
	error(Eperm);
.
830c
	error(Eperm);
.
817c
	error(Egreg);
.
773c
		error(Einuse);
.
235c
		error(Ebadarg);
.
## diffname power/devduart.c 1992/0321
## diff -e /n/bootesdump/1992/0114/sys/src/9/power/devduart.c /n/bootesdump/1992/0321/sys/src/9/power/devduart.c
2c
#include	"../port/lib.h"
.
## diffname power/devduart.c 1992/0325
## diff -e /n/bootesdump/1992/0321/sys/src/9/power/devduart.c /n/bootesdump/1992/0325/sys/src/9/power/devduart.c
338c
	int ch;
.
## diffname power/devduart.c 1992/0516
## diff -e /n/bootesdump/1992/0325/sys/src/9/power/devduart.c /n/bootesdump/1992/0516/sys/src/9/power/devduart.c
235c
		return;
.
## diffname power/devduart.c 1992/0519
## diff -e /n/bootesdump/1992/0516/sys/src/9/power/devduart.c /n/bootesdump/1992/0519/sys/src/9/power/devduart.c
817a
	return 0;	/* not reached */
.
749c
		streamstat(c, dp, duartdir[2*STREAMID(c->qid.path)].name);
.
702,703c
		duartdir[2*i].length = 0;
		duartdir[2*i+1].length = 0;
		duartdir[2*i].perm = 0666;
		duartdir[2*i+1].perm = 0666;
.
634,638d
579,585d
563a

	/* enable the port */
	dp->op = Dena;
	sleep(&dp->opr, opdone, dp);
.
556,558d
552,553d
526,537c
	return dp->op == Dnone;
.
524c
	Duartport *dp = x;
.
522c
opdone(void *x)
.
508,520d
493d
333a
void
.
329,331d
327c
	else
.
310a
void
.
306a
	cq = dp->iq;
	if(dp->wq && cangetc(cq))
		wakeup(&cq->r);
.
303a
	cq = dp->iq;
	if(dp->wq && cangetc(cq))
		wakeup(&cq->r);
.
300a
	IOQ *cq;
.
279c
		duartbaud(dp, dp->val);
.
276c
		duartdtr(dp, dp->val);
.
264c
		duartimr |= IM_XRDYB;
		duart->is_imr = duartimr;
.
260c
		duartimr &= ~IM_XRDYB;
		duart->is_imr = duartimr;
.
240c
		duartacr &= ~0x80;
	dp->duart->ipc_acr = duartacr;
.
238c
		duartacr |= 0x80;
.
210c
	int x;
.
143d
140,141d
## diffname power/devduart.c 1992/0520
## diff -e /n/bootesdump/1992/0519/sys/src/9/power/devduart.c /n/bootesdump/1992/0520/sys/src/9/power/devduart.c
805c
duartwstat(Chan *c, char *p)
.
778,783c
		p = &duartport[STREAMID(c->qid.path)];
		qlock(p);
		p->op = Dstate;
		sleep(&p->opr, opdone, p);
		*(uchar *)buf = p->val;
		qunlock(p);
.
767c
	Port *p;
.
742c
	if(p && p->nostream)
.
738c
		p = 0;
.
735c
		p = &duartport[STREAMID(c->qid.path)];
.
730c
	Port *p;
.
722c
		devstat(c, p, duartdir, 2*nduartport, devgen);
.
719c
		streamstat(c, p, duartdir[2*STREAMID(c->qid.path)].name);
.
715c
duartstat(Chan *c, char *p)
.
689,692c
		p->oq = ialloc(sizeof(IOQ), 0);
		initq(p->oq);
		p->oq->ptr = p;
		p->oq->puts = duartputs;
.
685,687c
		p->iq = ialloc(sizeof(IOQ), 0);
		initq(p->iq);
		p->iq->ptr = p;
.
681,682c
	for(p = duartport; p < &duartport[nduartport]; p++){
		if(p->nostream)
.
668,669c
		sprint(duartdir[2*i].name, "eia%d", i+1);
		sprint(duartdir[2*i+1].name, "eia%dctl", i+1);
.
659c
	Port *p;
.
646c
	qunlock(p);
.
644c
		PUTNEXT(RD(p->wq), bp);
.
637,638c
	qlock(p);
	if(p->wq == 0){
.
629,630c
	Port *p = a;
	IOQ *cq = p->iq;
.
608c
		qunlock(p->d);
		qunlock(p);
		poperror();
.
595,601c
			p->val = 1;
			p->op = Dbreak;
			if(!waserror()){
				sleep(&p->opr, opdone, p);
				tsleep(&p->opr, return0, 0, n);
				poperror();
			}
			p->val = 0;
			p->op = Dbreak;
			sleep(&p->opr, opdone, p);
.
589,591c
			p->val = n;
			p->op = Ddtr;
			sleep(&p->opr, opdone, p);
.
583,585c
			p->val = n;
			p->op = Dbaud;
			sleep(&p->opr, opdone, p);
.
576c
		if(waserror()){
			qunlock(p);
			qunlock(p->d);
			nexterror();
		}
		qlock(p);
		qlock(p->d);
.
570c
	cq = p->oq;
.
566c
	if(p == 0){
.
562c
	Port *p = q->ptr;
.
556c
	qunlock(p);
.
551,553c
	qlock(p);
	p->wq = 0;
	p->iq->putc = 0;
.
549c
	Port *p = q->ptr;
.
542,543c
	qlock(p);
	p->op = Dena;
	sleep(&p->opr, opdone, p);
	qunlock(p);
.
535,538c
	if(p->kstarted == 0){
		p->kstarted = 1;
		sprint(name, "duart%d", s->id+1);
		kproc(name, duartkproc, p);
.
529,533c
	qlock(p);
	p->wq = WR(q);
	WR(q)->ptr = p;
	RD(q)->ptr = p;
	qunlock(p);
.
527c
	p = &duartport[s->id];
.
524c
	Port *p;
.
518c
	return p->op == Dnone;
.
516c
	Port *p = x;
.
495,496c
	duartenable(p);
	duartbaud(p, baud);
.
485,486c
		p->iq = iq;
		p->iq->ptr = p;
.
480,482c
		p->oq = oq;
		p->oq->puts = duartputs;
		p->oq->ptr = p;
.
478c
	p->nostream = 1;
.
475c
	Port *p = &duartport[port];
.
460,462c
			p->printing = 1;
			p->val = ch;
			p->op = Dprint;
.
456,457c
	p = cq->ptr;
	if(p->printing == 0){
.
450,451c
	Port *p;
	Duartreg *reg;
.
415c
	reg->data = c;
.
410c
			duartsetup(&duartport[0], &duart[0], 0);
.
408c
	while((reg->sr_csr&XMT_RDY) == 0)
.
406c
	reg->cmnd = ENB_TX;
.
403c
	reg = DUARTREG;
.
400c
	Duartreg *reg;
.
391c
		duartxintr(p+1);
.
386c
		duartrintr(p+1);
.
381c
		duartxintr(p);
.
376c
		duartrintr(p);
.
366,368c
	p = &duartport[2*m->machno];
	reg = p->reg;
	cause = reg->is_imr;

.
363,364c
	Duartreg *reg;
	Port *p;
.
355c
		reg->data = ch;
.
353c
		reg->cmnd = DIS_TX;
.
351c
		p->printing = 0;
.
349c
	reg = p->reg;
.
346c
	cq = p->oq;
.
342c
	Duartreg *reg;
.
340c
duartxintr(Port *p)
.
332c
	cq = p->iq;
.
330c
		reg->cmnd = RESET_ERR;
.
326,328c
	reg = p->reg;
	status = reg->sr_csr;
	ch = reg->data;
.
321c
	Duartreg *reg;
.
319c
duartrintr(Port *p)
.
314,315c
	if(p->op != Dnone)
		duartslave0(p);
.
308,312c
	if(p->op != Dnone)
		duartslave0(p);
	p++;
	cq = p->iq;
	if(p->wq && cangetc(cq))
.
304,306c
	p = &duartport[2*m->machno];
	cq = p->iq;
	if(p->wq && cangetc(cq))
.
302c
	Port *p;
.
295,296c
	p->op = Dnone;
	wakeup(&p->opr);
.
292c
		p->val = p->reg->ppcr;
.
289c
		duartenable(p);
.
285,286c
		p->reg->cmnd = ENB_TX;
		p->reg->data = p->val;
.
282c
		duartbreak(p, p->val);
.
279c
		duartbaud(p, p->val);
.
276c
		duartdtr(p, p->val);
.
274c
	switch(p->op){
.
272c
duartslave0(Port *p)
.
262,264c
		reg->cmnd = STOP_BRK|ENB_TX;
		p->d->imr |= IM_XRDYB;
		p->d->reg->is_imr = p->d->imr;
.
258,260c
		p->d->imr &= ~IM_XRDYB;
		p->d->reg->is_imr = p->d->imr;
		reg->cmnd = STRT_BRK|ENB_TX;
.
256c
	reg = p->reg;
.
254c
	Duartreg *reg;
.
252c
duartbreak(Port *p, int val)
.
248c
		p->reg->ctur = 0x01;
.
246c
		p->reg->ctlr = 0x01;
.
243c
duartdtr(Port *p, int val)
.
237,239c
		p->d->acr &= ~0x80;
	p->d->reg->ipc_acr = p->d->acr;
	p->reg->sr_csr = x;
.
235c
		p->d->acr |= 0x80;
.
205c
duartbaud(Port *p, int b)
.
195c
	p->reg->cmnd = ENB_TX|ENB_RX;
.
193c
duartenable(Port *p)
.
182,186c
	p = &duartport[2*m->machno];
	duartsetup(p, d, 0);
	p++;
	duartsetup(p, d, 1);
.
180c
	d->reg = DUARTREG;
	d->imr = IM_RRDYA|IM_XRDYA|IM_RRDYB|IM_XRDYB;
	d->reg->is_imr = d->imr;
	d->acr = 0x80;			/* baud rate set 2 */
	d->reg->ipc_acr = d->acr;
.
177,178c
	d = &duart[m->machno];
	if(d->inited)
.
175c
	Port *p;
	Duart *d;
.
160,166c
	reg->cmnd = RESET_MR;
	reg->mr1_2 = NO_PAR|CBITS8;
	reg->mr1_2 = ONESTOPB;
	reg->sr_csr = (DBD9600<<4)|DBD9600;
	reg->cmnd = ENB_TX|ENB_RX;
.
155,158c
	reg->cmnd = RESET_RCV|DIS_TX|DIS_RX;
	reg->cmnd = RESET_TRANS;
	reg->cmnd = RESET_ERR;
	reg->cmnd = STOP_BRK;
.
153c
	p->d = d;
	reg = &d->reg[devno];
	p->reg = reg;
.
151c
	Duartreg *reg;
.
149c
duartsetup(Port *p, Duart *d, int devno)
.
142c
Port duartport[2*Maxduart];
.
138,140c
	Queue		*wq;		/* write queue */
	Rendez		r;		/* kproc waiting for input */
 	int		kstarted;	/* kproc started */
.
133,135c
	int		nostream;	/* can't use the stream interface */
	IOQ		*iq;		/* input character queue */
	IOQ		*oq;		/* output character queue */
.
131a
/*
 *  values specific to a single duart port
 */
typedef struct Port	Port;
struct Port
{
	QLock;
	int		printing;	/* true if printing */
	Duart		*d;		/* device */
	Duartreg	*reg;		/* duart registers (for this port) */
	int		c;		/* character to restart output */
	int		op;		/* operation requested */
	int		val;		/* value of operation */
	Rendez		opr;		/* waiot here for op to complete */

.
124,130c
	Duartreg	*reg;		/* duart registers */
	uchar		imr;		/* sticky interrupt mask reg bits */
	uchar		acr;		/* sticky auxiliary reg bits */
	int		inited;
};
Duart duart[Maxduart];
.
120,121c
typedef struct Duart	Duart;
struct Duart
.
118c
 *  a duart
.
101c
	Maxduart	=8,
.
20c
struct Duartreg
{
.
18c
 *  Register set for half the duart.  There are really two sets in adjacent
 *  memory locations.
.
9,11d
## diffname power/devduart.c 1992/0608
## diff -e /n/bootesdump/1992/0520/sys/src/9/power/devduart.c /n/bootesdump/1992/0608/sys/src/9/power/devduart.c
203a
	d->inited = 1;
.
## diffname power/devduart.c 1992/0622
## diff -e /n/bootesdump/1992/0608/sys/src/9/power/devduart.c /n/bootesdump/1992/0622/sys/src/9/power/devduart.c
721c
		p->oq = xalloc(sizeof(IOQ));
.
717c
		p->iq = xalloc(sizeof(IOQ));
.
698c
	duartdir = xalloc(nduartport*2*sizeof(Dirtab));
.
## diffname power/devduart.c 1992/0711
## diff -e /n/bootesdump/1992/0622/sys/src/9/power/devduart.c /n/bootesdump/1992/0711/sys/src/9/power/devduart.c
839a
	USED(p);
.
825a
	USED(offset);
.
785a
	USED(name);
	USED(omode);
	USED(perm);
.
470d
380c
	int cause;
.
## diffname power/devduart.c 1992/0826
## diff -e /n/bootesdump/1992/0711/sys/src/9/power/devduart.c /n/bootesdump/1992/0826/sys/src/9/power/devduart.c
750c
		streamstat(c, p, duartdir[2*STREAMID(c->qid.path)].name,
			duartdir[2*STREAMID(c->qid.path)].perm);
.
## diffname power/devduart.c 1993/0501
## diff -e /n/bootesdump/1992/0826/sys/src/9/power/devduart.c /n/fornaxdump/1993/0501/sys/src/brazil/power/devduart.c
456,457c
	doprint(buf, buf+sizeof(buf), fmt, (&fmt+1));
.
453,454c
	char buf[512];
.
449a

.
## diffname power/devduart.c 1993/0806
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/power/devduart.c /n/fornaxdump/1993/0806/sys/src/brazil/power/devduart.c
845,855d
842,843c
	USED(c, p);
.
829c

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

	p = &uart[NETID(c->qid.path)];
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		return qwrite(p->oq, va, n, 0);
	case Nctlqid:
		if(n >= sizeof(cmd))
			n = sizeof(cmd)-1;
		memmove(cmd, va, n);
		cmd[n] = 0;
		duartctl(p, cmd);
		return n;
	}
.
827a
	Uart *p;
	char cmd[32];

.
824a
static void
duartctl(Uart *p, char *cmd)
{
	int n, i;

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

	n = atoi(cmd+1);
	switch(cmd[0]){
	case 'B':
	case 'b':
		p->val = n;
		p->op = Dbaud;
		sleep(&p->opr, opdone, p);
		break;
	case 'D':
	case 'd':
		p->val = n;
		p->op = Ddtr;
		sleep(&p->opr, opdone, p);
		break;
	case 'K':
	case 'k':
		p->val = 1;
		p->op = Dbreak;
		if(!waserror()){
			sleep(&p->opr, opdone, p);
			tsleep(&p->opr, return0, 0, n);
			poperror();
		}
		p->val = 0;
		p->op = Dbreak;
		sleep(&p->opr, opdone, p);
		break;
	case 'R':
	case 'r':
		/* can't control? */
		break;
	}
}

.
821,822c
	return 0;
.
806,818c
	p = &uart[NETID(c->qid.path)];
	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);
.
803,804c
	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, duartdir, 2*nuart, devgen);
.
801c
	Uart *p;
.
794,795c
	Uart *p;

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

	p = &uart[NETID(c->qid.path)];
	qlock(p);
	p->opens++;
	if(p->opens == 0){
		qclose(p->iq);
		qclose(p->oq);
	}
	qunlock(p);
.
784,787c
	USED(c, name, omode, perm);
.
773,778c
	c->mode = omode&~OTRUNC;
	c->flag |= COPEN;
	c->offset = 0;
	return c;
.
763,770c
	if(c->qid.path & CHDIR){
		if(omode != OREAD)
			error(Ebadarg);
	} 
	else {
		p = &uart[NETID(c->qid.path)];
		qlock(p);
		p->opens++;
		if(p->opens == 1) {
			/* enable the port */
			p->op = Dena;
			sleep(&p->opr, opdone, p);
		
			qreopen(p->iq);
			qreopen(p->oq);
		}
		qunlock(p);
.
761c
	Uart *p;
.
753c
		devstat(c, dp, duartdir, 2*nuart, devgen);
.
747,750c
	int i;
	Uart *p;
	Dir dir;

	i = NETID(c->qid.path);
	switch(NETTYPE(c->qid.path)){
	case Ndataqid:
		p = &uart[i];
		devdir(c, c->qid, duartdir[2*i].name, qlen(p->iq), eve, 0660, &dir);
		convD2M(&dir, dp);
.
745c
duartstat(Chan *c, char *dp)
.
741c
	return devwalk(c, name, duartdir, 2*nuart, devgen);
.
708,722c
		print(dp->name, "eia%dctl", i);
		dp->qid.path = NETQID(i, Nctlqid);
		dp->perm = 0666;
		dp++;
.
692,706c
	nuart = 2*conf.nmach;
	duartdir = xalloc(2 * nuart * sizeof(Dirtab));
	dp = duartdir;
	for(i = 0; i < nuart; i++){
		/* 2 directory entries per port */
		print(dp->name, "eia%d", i);
		dp->qid.path = NETQID(i, Ndataqid);
		dp->perm = 0666;
		dp++;
.
690a
	Dirtab *dp;
.
689d
683,685d
681c
int nuart;
.
538,679d
533c
	Uart *p = x;
.
516,529d
505,513c
	p->opens++;
.
495,503c
	p->putc = putc;
	if(in)
		*in = p->iq;
	if(out)
		*out = p->oq;
.
486,493c
	duartenable(p);
	if(s)
		duartbaud(p, s);
.
470,484c
	p = &uart[port];
.
467,468c
	Uart *p;
.
465c
duartspecial(int port, int s, Queue **in, Queue **out, int (*putc)(Queue*, int))
.
460,463d
456,457c
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
	for(i = 0; i < n; i++)
		duartrawputc(buf[i]);
	return n;
.
453a
	int n, i;
.
451c
int
.
440,449d
435,437d
427,433c
	while((reg->srcsr&XMTRDY) == 0 && i++ < 100000)
		;
.
425c
		delay(100);
	}
	reg->cmnd = ENBTX;
.
423c
	if(c == '\n') {
.
420a
	Duartreg *reg;
.
419d
406,409c

	if(cause & IMXRDYB)
.
401,404c

	if(cause & IMRRDYB)
.
396,399c

	if(cause & IMXRDYA)
.
388,394c
	if(cause & IMRRDYA)
.
386c
	cause = reg->isimr;
.
384c
	p = &uart[2*m->machno];
.
382c
	Uart *p;
.
374d
370,372c
		reg->cmnd = DISTX;
	}
	else
.
368c
	if(qconsume(p->oq, &ch, 1) <= 0) {
.
364,366d
362a
	Duartreg *reg;
.
360,361c
	char ch;
	int n, x;

	x = splhi();
	if(p->printing) {
		splx(x);
		return;
	}

	n = qconsume(p->oq, &ch, 1);
	if(n <= 0){
		splx(x);
		return;
	}

	p->printing = 1;
	p->val = ch;
	p->op = Dprint;
	splx(x);
}

void
duartxintr(Uart *p)
{
.
358c
duartkick(Uart *p)
.
356a
/*
 *  (re)start output
 */
.
354c
		qproduce(p->iq, &ch, 1);
.
350,352c
	if(p->putc)
		(*p->putc)(p->iq, ch);
.
347,348c
	if(status & (FRMERR|OVRERR|PARERR))
		reg->cmnd = RESETERR;
.
345c
	status = reg->srcsr;
.
342a
	int status;
	Duartreg *reg;
.
339,341d
337c
duartrintr(Uart *p)
.
329,331d
322,325c
	p = &uart[2*m->machno];
.
319,320c
	Uart *p;
.
304a
iprint("slave %c\n", p->val);
.
303c
		p->reg->cmnd = ENBTX;
.
290c
duartslave0(Uart *p)
.
280,282c
		reg->cmnd = STOPBRK|ENBTX;
		p->d->imr |= IMXRDYB;
		p->d->reg->isimr = p->d->imr;
.
276,278c
		p->d->imr &= ~IMXRDYB;
		p->d->reg->isimr = p->d->imr;
		reg->cmnd = STRTBRK|ENBTX;
.
270c
duartbreak(Uart *p, int val)
.
261c
duartdtr(Uart *p, int val)
.
256,257c
	p->d->reg->ipcacr = p->d->acr;
	p->reg->srcsr = x;
.
223c
duartbaud(Uart *p, int b)
.
219c
	DUARTREG->cmnd = ENBTX|ENBRX;
.
213c
	p->reg->cmnd = ENBTX|ENBRX;
.
211c
duartenable(Uart *p)
.
200c
	p = &uart[2*m->machno];

.
198c
	d->reg->ipcacr = d->acr;
.
195,196c
	d->imr = IMRRDYA|IMXRDYA|IMRRDYB|IMXRDYB;
	d->reg->isimr = d->imr;
.
193a

.
188c
	Uart *p;
.
175,179c
	reg->cmnd = RESETMR;
	reg->mr12 = NOPAR|CBITS8;
	reg->mr12 = ONESTOPB;
	reg->srcsr = (DBD9600<<4)|DBD9600;
	reg->cmnd = ENBTX|ENBRX;

	p->iq = qopen(4*1024, 0, 0, 0);
	p->oq = qopen(4*1024, 0, duartkick, p);
.
170,173c
	reg->cmnd = RESETRCV|DISTX|DISRX;
	reg->cmnd = RESETTRANS;
	reg->cmnd = RESETERR;
	reg->cmnd = STOPBRK;
.
162c
duartsetup(Uart *p, Duart *d, int devno)
.
156a
void	duartkick(Uart*);

.
155c
Uart uart[2*Maxduart];
.
150,153c
	/* buffers */
	int	(*putc)(Queue*, int);
	Queue	*iq;
	Queue	*oq;
.
145,148c
	int		printing;	/* need kick */
	int		opens;
	Rendez		r;
.
137d
133,134c
typedef struct Uart	Uart;
struct Uart
.
106c
enum
{
.
53,100c
	Maxduart	= 8,
.
39,51c
enum
{
	DBD75		= 0,
	DBD110		= 1,
	DBD38400	= 2,
	DBD150		= 3,
	DBD300		= 4,
	DBD600		= 5,
	DBD1200		= 6,
	DBD2000		= 7,
	DBD2400		= 8,
	DBD4800		= 9,
	DBD1800		= 10,
	DBD9600		= 11,
	DBD19200	= 12,
	CHARERR		= 0x00,	/* MR1x - Mode Register 1 */
	EVENPAR		= 0x00,
	ODDPAR		= 0x04,
	NOPAR		= 0x10,
	CBITS8		= 0x03,
	CBITS7		= 0x02,
	CBITS6		= 0x01,
	CBITS5		= 0x00,
	NORMOP		= 0x00,	/* MR2x - Mode Register 2 */
	TWOSTOPB	= 0x0F,
	ONESTOPB	= 0x07,
	ENBRX		= 0x01,	/* CRx - Command Register */
	DISRX		= 0x02,
	ENBTX		= 0x04,
	DISTX		= 0x08,
	RESETMR 	= 0x10,
	RESETRCV  	= 0x20,
	RESETTRANS  	= 0x30,
	RESETERR  	= 0x40,
	RESETBCH	= 0x50,
	STRTBRK		= 0x60,
	STOPBRK		= 0x70,
	RCVRDY		= 0x01,	/* SRx - Channel Status Register */
	FIFOFULL	= 0x02,
	XMTRDY		= 0x04,
	XMTEMT		= 0x08,
	OVRERR		= 0x10,
	PARERR		= 0x20,
	FRMERR		= 0x40,
	RCVDBRK		= 0x80,
	IMIPC		= 0x80,	/* IMRx/ISRx - Int Mask/Interrupt Status */
	IMDBB		= 0x40,
	IMRRDYB		= 0x20,
	IMXRDYB		= 0x10,
	IMCRDY		= 0x08,
	IMDBA		= 0x04,
	IMRRDYA		= 0x02,
	IMXRDYA		= 0x01,
	BD38400		= 0xCC|0x0000,
	BD19200		= 0xCC|0x0100,
	BD9600		= 0xBB|0x0000,
	BD4800		= 0x99|0x0000,
	BD2400		= 0x88|0x0000,
	BD1200		= 0x66|0x0000,
	BD300		= 0x44|0x0000,
.
37c
#define	ppcr	isimr		/* in the second register set */
.
20,35c
	uchar	mr12;		/* Mode Register Channels 1 & 2 */
	uchar	pad0[15];
	uchar	srcsr;		/* Status Register/Clock Select Register */
	uchar	pad1[15];
	uchar	cmnd;		/* Command Register */
	uchar	pad2[15];
	uchar	data;		/* RX Holding / TX Holding Register */
	uchar	pad3[15];
	uchar	ipcacr;		/* Input Uart Change/Aux. Control Register */
	uchar	pad4[15];
	uchar	isimr;		/* Interrupt Status/Interrupt Mask Register */
	uchar	pad5[15];
	uchar	ctur;		/* Counter/Timer Upper Register */
	uchar	pad6[15];
	uchar	ctlr;		/* Counter/Timer Lower Register */
	uchar	pad7[15];
.
15,16c
 * Register set for half the duart. 
 * There are really two sets in adjacent memory locations.
.
12,13d
9,10c
#include	"devtab.h"
#include	"../port/netif.h"
.
## diffname power/devduart.c 1993/0807
## diff -e /n/fornaxdump/1993/0806/sys/src/brazil/power/devduart.c /n/fornaxdump/1993/0807/sys/src/brazil/power/devduart.c
467c
	if(out != 0)
.
465c
	if(in != 0)
.
383c
	char ch;
.
309d
## diffname power/devduart.c 1994/0902
## diff -e /n/fornaxdump/1993/0807/sys/src/brazil/power/devduart.c /n/fornaxdump/1994/0902/sys/src/brazil/power/devduart.c
675c
		return qwrite(p->oq, va, n);
.
## diffname power/devduart.c 1995/0108
## diff -e /n/fornaxdump/1994/0902/sys/src/brazil/power/devduart.c /n/fornaxdump/1995/0108/sys/src/brazil/power/devduart.c
683a
}

long
duartbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
617a
Block*
duartbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname power/devduart.c 1995/0205
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/power/devduart.c /n/fornaxdump/1995/0205/sys/src/brazil/power/devduart.c
632a
	if(strncmp(cmd, "break", 5) == 0)
		cmed += 4;

.
## diffname power/devduart.c 1996/0214
## diff -e /n/fornaxdump/1995/0205/sys/src/brazil/power/devduart.c /n/fornaxdump/1996/0214/sys/src/brazil/power/devduart.c
639a
		if(strncmp(cmd+1, "reak", 4) == 0)
			break;
.
633,635d
446c
	va_start(arg, fmt);
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
	va_end(arg);

.
444a
	va_list arg;
.
## diffname power/devduart.c 1996/0223
## diff -e /n/fornaxdump/1996/0214/sys/src/brazil/power/devduart.c /n/fornaxdump/1996/0223/sys/src/brazil/power/devduart.c
9d
## diffname power/devduart.c 1997/0327 # deleted
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/power/devduart.c /n/emeliedump/1997/0327/sys/src/brazil/power/devduart.c
1,715d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.