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

1995/0205/power/devduart.c (diff list | history)

1991/0607/sys/src/9/power/devduart.c:466,4711991/0727/sys/src/9/power/devduart.c:466,472 (short | long)
1991/0607    
duartspecial(int port, IOQ *oq, IOQ *iq, int baud) 
{ 
	Duartport *dp = &duartport[port]; 
1991/0727    
	IOQ *zq; 
1991/0607    
 
	dp->nostream = 1; 
	if(oq){ 
1991/0607/sys/src/9/power/devduart.c:476,4811991/0727/sys/src/9/power/devduart.c:477,489
1991/0607    
	if(iq){ 
		dp->iq = iq; 
		dp->iq->ptr = dp; 
1991/0727    
 
		/* 
		 *  Stupid HACK to undo a stupid hack 
		 */  
		zq = &kbdq; 
		if(iq == zq) 
			kbdq.putc = kbdcr2nl; 
1991/0607    
	} 
	duartenable(dp); 
	duartbaud(dp, baud); 
1991/0727/sys/src/9/power/devduart.c:841,8441991/1113/sys/src/9/power/devduart.c:841,844 (short | long)
Whitespace edit.
rsc Mon Mar 7 10:32:51 2005
1991/0607    
	for(i = 0; i < nduartport; i++) 
		if(duartport[i].printing) 
			return 1; 
	return 0;                                                                         } 
1991/1113    
	return 0;                                                             } 
1991/1113/sys/src/9/power/devduart.c:696,7031991/1115/sys/src/9/power/devduart.c:696,703 (short | long)
1991/0607    
	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); 
1991/1115    
		sprint(duartdir[2*i].name, "eia%d", i); 
		sprint(duartdir[2*i+1].name, "eia%dctl", i); 
1991/0607    
		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); 
1991/1113/sys/src/9/power/devduart.c:745,7511991/1115/sys/src/9/power/devduart.c:745,751
1991/0607    
{ 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
		streamstat(c, dp, "tty0"); 
1991/1115    
		streamstat(c, dp, "eia0"); 
1991/0607    
		break; 
	default: 
		devstat(c, dp, duartdir, 2*nduartport, devgen); 
1991/1113/sys/src/9/power/devduart.c:779,7851991/1115/sys/src/9/power/devduart.c:779,785
1991/0607    
void 
duartcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	errors("only God can create a tty"); 
1991/1115    
	errors(Eperm); 
1991/0607    
} 
 
void 
1991/1115/sys/src/9/power/devduart.c:4,91991/1120/sys/src/9/power/devduart.c:4,10 (short | long)
1991/0607    
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
1991/1120    
#include	"errno.h" 
1991/0607    
 
int	duartacr; 
int	duartimr; 
1991/1115/sys/src/9/power/devduart.c:779,7851991/1120/sys/src/9/power/devduart.c:780,786
1991/0607    
void 
duartcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	errors(Eperm); 
1991/1120    
	error(Eperm); 
1991/0607    
} 
 
void 
1991/1120/sys/src/9/power/devduart.c:780,7851991/1214/sys/src/9/power/devduart.c:780,786 (short | long)
1991/0607    
void 
duartcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1214    
	USED(c); 
1991/1120    
	error(Eperm); 
1991/0607    
} 
 
1991/1120/sys/src/9/power/devduart.c:825,8301991/1214/sys/src/9/power/devduart.c:826,832
1991/0607    
void 
duartremove(Chan *c) 
{ 
1991/1214    
	USED(c); 
1991/0607    
	errors("can't remove a duart"); 
} 
 
1991/1120/sys/src/9/power/devduart.c:831,8361991/1214/sys/src/9/power/devduart.c:833,839
1991/0607    
void 
duartwstat(Chan *c, char *dp) 
{ 
1991/1214    
	USED(c); 
1991/0607    
	errors("can't write a duart"); 
} 
 
1991/1120/sys/src/9/power/devduart.c:842,8451991/1214/sys/src/9/power/devduart.c:845,849
1991/0607    
	for(i = 0; i < nduartport; i++) 
		if(duartport[i].printing) 
			return 1; 
1991/1113    
	return 0;                                                             } 
1991/1214    
	return 0; 
} 
1991/1214/sys/src/9/power/devduart.c:4,101992/0111/sys/src/9/power/devduart.c:4,10 (short | long)
1991/0607    
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
1991/1120    
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1991/0607    
 
int	duartacr; 
int	duartimr; 
1992/0111/sys/src/9/power/devduart.c:232,2381992/0114/sys/src/9/power/devduart.c:232,238 (short | long)
1991/0607    
		x = BD300; 
		break; 
	default: 
		errors("bad baud rate"); 
1992/0114    
		error(Ebadarg); 
1991/0607    
	} 
	if(x & 0x0100) 
		dp->duart->ipc_acr = duartacr |= 0x80; 
1992/0111/sys/src/9/power/devduart.c:770,7761992/0114/sys/src/9/power/devduart.c:770,776
1991/0607    
	} 
 
	if(dp && dp->nostream) 
		errors("in use"); 
1992/0114    
		error(Einuse); 
1991/0607    
 
	if((c->qid.path & CHDIR) == 0) 
		streamopen(c, &duartinfo); 
1992/0111/sys/src/9/power/devduart.c:814,8201992/0114/sys/src/9/power/devduart.c:814,820
1991/0607    
		return 1; 
	} 
 
	errors("no such duart type"); 
1992/0114    
	error(Egreg); 
1991/0607    
} 
 
long 
1992/0111/sys/src/9/power/devduart.c:827,8331992/0114/sys/src/9/power/devduart.c:827,833
1991/0607    
duartremove(Chan *c) 
{ 
1991/1214    
	USED(c); 
1991/0607    
	errors("can't remove a duart"); 
1992/0114    
	error(Eperm); 
1991/0607    
} 
 
void 
1992/0111/sys/src/9/power/devduart.c:834,8401992/0114/sys/src/9/power/devduart.c:834,840
1991/0607    
duartwstat(Chan *c, char *dp) 
{ 
1991/1214    
	USED(c); 
1991/0607    
	errors("can't write a duart"); 
1992/0114    
	error(Eperm); 
1991/0607    
} 
 
int 
1992/0114/sys/src/9/power/devduart.c:1,51992/0321/sys/src/9/power/devduart.c:1,5 (short | long)
1991/0607    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0607    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/power/devduart.c:335,3411992/0325/sys/src/9/power/devduart.c:335,341 (short | long)
1991/0607    
{ 
	Duart *duart; 
	IOQ *cq; 
	char ch; 
1992/0325    
	int ch; 
1991/0607    
 
	cq = dp->oq; 
	lock(cq); 
1992/0325/sys/src/9/power/devduart.c:232,2381992/0516/sys/src/9/power/devduart.c:232,238 (short | long)
1991/0607    
		x = BD300; 
		break; 
	default: 
1992/0114    
		error(Ebadarg); 
1992/0516    
		return; 
1991/0607    
	} 
	if(x & 0x0100) 
		dp->duart->ipc_acr = duartacr |= 0x80; 
1992/0516/sys/src/9/power/devduart.c:137,1461992/0519/sys/src/9/power/devduart.c:137,143 (short | long)
1991/0607    
	/* 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 */ 
 
1992/0516/sys/src/9/power/devduart.c:207,2131992/0519/sys/src/9/power/devduart.c:204,210
1991/0607    
void 
duartbaud(Duartport *dp, int b) 
{ 
	int x = 0; 
1992/0519    
	int x; 
1991/0607    
 
	switch(b){ 
	case 38400: 
1992/0516/sys/src/9/power/devduart.c:235,2431992/0519/sys/src/9/power/devduart.c:232,241
1992/0516    
		return; 
1991/0607    
	} 
	if(x & 0x0100) 
		dp->duart->ipc_acr = duartacr |= 0x80; 
1992/0519    
		duartacr |= 0x80; 
1991/0607    
	else 
		dp->duart->ipc_acr = duartacr &= ~0x80; 
1992/0519    
		duartacr &= ~0x80; 
	dp->duart->ipc_acr = duartacr; 
1991/0607    
	dp->duart->sr_csr = x; 
} 
 
1992/0516/sys/src/9/power/devduart.c:257,2671992/0519/sys/src/9/power/devduart.c:255,267
1991/0607    
 
	duart = dp->duart; 
	if (val){ 
		duart->is_imr = duartimr &= ~IM_XRDYB; 
1992/0519    
		duartimr &= ~IM_XRDYB; 
		duart->is_imr = duartimr; 
1991/0607    
		duart->cmnd = STRT_BRK|ENB_TX; 
	} else { 
		duart->cmnd = STOP_BRK|ENB_TX; 
		duart->is_imr = duartimr |= IM_XRDYB; 
1992/0519    
		duartimr |= IM_XRDYB; 
		duart->is_imr = duartimr; 
1991/0607    
	} 
} 
 
1992/0516/sys/src/9/power/devduart.c:273,2821992/0519/sys/src/9/power/devduart.c:273,282
1991/0607    
{ 
	switch(dp->op){ 
	case Ddtr: 
		duartbaud(dp, dp->val); 
1992/0519    
		duartdtr(dp, dp->val); 
1991/0607    
		break; 
	case Dbaud: 
		duartdtr(dp, dp->val); 
1992/0519    
		duartbaud(dp, dp->val); 
1991/0607    
		break; 
	case Dbreak: 
		duartbreak(dp, dp->val); 
1992/0516/sys/src/9/power/devduart.c:298,3131992/0519/sys/src/9/power/devduart.c:298,321
1991/0607    
void 
duartslave(void) 
{ 
1992/0519    
	IOQ *cq; 
1991/0607    
	Duartport *dp; 
 
	dp = &duartport[2*m->machno]; 
1992/0519    
	cq = dp->iq; 
	if(dp->wq && cangetc(cq)) 
		wakeup(&cq->r); 
1991/0607    
	if(dp->op != Dnone) 
		duartslave0(dp); 
	dp++; 
1992/0519    
	cq = dp->iq; 
	if(dp->wq && cangetc(cq)) 
		wakeup(&cq->r); 
1991/0607    
	if(dp->op != Dnone) 
		duartslave0(dp); 
} 
 
1992/0519    
void 
1991/0607    
duartrintr(Duartport *dp) 
{ 
	Duart *duart; 
1992/0516/sys/src/9/power/devduart.c:324,3361992/0519/sys/src/9/power/devduart.c:332,342
1991/0607    
	cq = dp->iq; 
	if(cq->putc) 
		(*cq->putc)(cq, ch); 
	else { 
1992/0519    
	else 
1991/0607    
		putc(cq, ch); 
		if(dp->delim[ch/8] & (1<<(ch&7)) ) 
			wakeup(&cq->r); 
	} 
} 
 
1992/0519    
void 
1991/0607    
duartxintr(Duartport *dp) 
{ 
	Duart *duart; 
1992/0516/sys/src/9/power/devduart.c:490,4961992/0519/sys/src/9/power/devduart.c:496,501
1991/0607    
	duartbaud(dp, baud); 
} 
 
static void	duarttimer(Alarm*); 
static int	duartputc(IOQ *, int); 
static void	duartstopen(Queue*, Stream*); 
static void	duartstclose(Queue*); 
1992/0516/sys/src/9/power/devduart.c:505,5401992/0519/sys/src/9/power/devduart.c:510,521
1991/0607    
	"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) 
1992/0519    
opdone(void *x) 
1991/0607    
{ 
	Duartport *dp = cq->ptr; int r; 
1992/0519    
	Duartport *dp = x; 
1991/0607    
 
	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; 
1992/0519    
	return dp->op == Dnone; 
1991/0607    
} 
 
static void 
1992/0516/sys/src/9/power/devduart.c:549,5661992/0519/sys/src/9/power/devduart.c:530,546
1991/0607    
	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); 
	} 
1992/0519    
 
	/* enable the port */ 
	dp->op = Dena; 
	sleep(&dp->opr, opdone, dp); 
1991/0607    
} 
 
static void 
1992/0516/sys/src/9/power/devduart.c:576,5881992/0519/sys/src/9/power/devduart.c:556,561
1991/0607    
	qunlock(dp); 
} 
 
static int 
opdone(void *x) 
{ 
	Duartport *dp = x; 
                 
	return dp->op == Dnone; 
} 
static void 
duartoput(Queue *q, Block *bp) 
{ 
1992/0516/sys/src/9/power/devduart.c:631,6411992/0519/sys/src/9/power/devduart.c:604,609
1991/0607    
		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){ 
1992/0516/sys/src/9/power/devduart.c:699,7061992/0519/sys/src/9/power/devduart.c:667,676
1991/0607    
	for(i = 0; i < nduartport; i++){ 
1991/1115    
		sprint(duartdir[2*i].name, "eia%d", i); 
		sprint(duartdir[2*i+1].name, "eia%dctl", i); 
1991/0607    
		duartdir[2*i].length = duartdir[2*i+1].length = 0; 
		duartdir[2*i].perm = duartdir[2*i+1].perm = 0666; 
1992/0519    
		duartdir[2*i].length = 0; 
		duartdir[2*i+1].length = 0; 
		duartdir[2*i].perm = 0666; 
		duartdir[2*i+1].perm = 0666; 
1991/0607    
		duartdir[2*i].qid.path = STREAMQID(i, Sdataqid); 
		duartdir[2*i+1].qid.path = STREAMQID(i, Sctlqid); 
	} 
1992/0516/sys/src/9/power/devduart.c:746,7521992/0519/sys/src/9/power/devduart.c:716,722
1991/0607    
{ 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
1991/1115    
		streamstat(c, dp, "eia0"); 
1992/0519    
		streamstat(c, dp, duartdir[2*STREAMID(c->qid.path)].name); 
1991/0607    
		break; 
	default: 
		devstat(c, dp, duartdir, 2*nduartport, devgen); 
1992/0516/sys/src/9/power/devduart.c:815,8201992/0519/sys/src/9/power/devduart.c:785,791
1991/0607    
	} 
 
1992/0114    
	error(Egreg); 
1992/0519    
	return 0;	/* not reached */ 
1991/0607    
} 
 
long 
1992/0519/sys/src/9/power/devduart.c:6,141992/0520/sys/src/9/power/devduart.c:6,11 (short | long)
1991/0607    
#include	"io.h" 
1992/0111    
#include	"../port/error.h" 
1991/0607    
 
int	duartacr; 
int	duartimr; 
                 
void	duartputs(IOQ*, char*, int); 
void	iprint(char*, ...); 
 
1992/0519/sys/src/9/power/devduart.c:15,231992/0520/sys/src/9/power/devduart.c:12,22
1991/0607    
#define	PAD	15	/* registers are well-spaced */ 
 
/* 
 * Register set for half the duart.  There are really two sets. 
1992/0520    
 *  Register set for half the duart.  There are really two sets in adjacent 
 *  memory locations. 
1991/0607    
 */ 
struct Duart{ 
1992/0520    
struct Duartreg 
{ 
1991/0607    
	uchar	mr1_2,		/* Mode Register Channels 1 & 2 */ 
		pad0[PAD]; 
	uchar	sr_csr,		/* Status Register/Clock Select Register */ 
1992/0519/sys/src/9/power/devduart.c:98,1041992/0520/sys/src/9/power/devduart.c:97,103
1991/0607    
	BD1200		=0x66|0x0000, 
	BD300		=0x44|0x0000, 
 
	Maxport		=8, 
1992/0520    
	Maxduart	=8, 
1991/0607    
}; 
 
/* 
1992/0519/sys/src/9/power/devduart.c:115,1451992/0520/sys/src/9/power/devduart.c:114,158
1991/0607    
}; 
 
/* 
 *  software info for a serial duart interface 
1992/0520    
 *  a duart 
1991/0607    
 */ 
typedef struct Duartport	Duartport; 
struct Duartport 
1992/0520    
typedef struct Duart	Duart; 
struct Duart 
1991/0607    
{ 
	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 */ 
1992/0520    
	Duartreg	*reg;		/* duart registers */ 
	uchar		imr;		/* sticky interrupt mask reg bits */ 
	uchar		acr;		/* sticky auxiliary reg bits */ 
	int		inited; 
}; 
Duart duart[Maxduart]; 
1991/0607    
 
1992/0520    
/* 
 *  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 */ 
 
1991/0607    
	/* console interface */ 
	int	nostream;	/* can't use the stream interface */ 
	IOQ	*iq;		/* input character queue */ 
	IOQ	*oq;		/* output character queue */ 
1992/0520    
	int		nostream;	/* can't use the stream interface */ 
	IOQ		*iq;		/* input character queue */ 
	IOQ		*oq;		/* output character queue */ 
1991/0607    
 
	/* stream interface */ 
	Queue	*wq;		/* write queue */ 
	Rendez	r;		/* kproc waiting for input */ 
 	int	kstarted;	/* kproc started */ 
1992/0520    
	Queue		*wq;		/* write queue */ 
	Rendez		r;		/* kproc waiting for input */ 
 	int		kstarted;	/* kproc started */ 
1991/0607    
}; 
Duartport	duartport[Maxport];	/* max possible */ 
1992/0520    
Port duartport[2*Maxduart]; 
1991/0607    
 
/* 
 *  configure a duart port, default is 9600 baud, 8 bits/char, 1 stop bit, 
1992/0519/sys/src/9/power/devduart.c:146,1691992/0520/sys/src/9/power/devduart.c:159,182
1991/0607    
 *  no parity 
 */ 
void 
duartsetup(Duartport *dp) 
1992/0520    
duartsetup(Port *p, Duart *d, int devno) 
1991/0607    
{ 
	Duart *duart; 
1992/0520    
	Duartreg *reg; 
1991/0607    
 
	duart = dp->duart; 
1992/0520    
	p->d = d; 
	reg = &d->reg[devno]; 
	p->reg = reg; 
1991/0607    
 
	duart->cmnd = RESET_RCV|DIS_TX|DIS_RX; 
	duart->cmnd = RESET_TRANS; 
	duart->cmnd = RESET_ERR; 
	duart->cmnd = STOP_BRK; 
1992/0520    
	reg->cmnd = RESET_RCV|DIS_TX|DIS_RX; 
	reg->cmnd = RESET_TRANS; 
	reg->cmnd = RESET_ERR; 
	reg->cmnd = STOP_BRK; 
1991/0607    
 
	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; 
1992/0520    
	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; 
1991/0607    
} 
 
/* 
1992/0519/sys/src/9/power/devduart.c:172,1891992/0520/sys/src/9/power/devduart.c:185,206
1991/0607    
void 
duartinit(void) 
{ 
	Duartport *dp; 
1992/0520    
	Port *p; 
	Duart *d; 
1991/0607    
 
	dp = &duartport[2*m->machno]; 
	if(dp->inited) 
1992/0520    
	d = &duart[m->machno]; 
	if(d->inited) 
1991/0607    
		return; 
	dp->inited = 1; 
1992/0520    
	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; 
1991/0607    
 
	dp->duart = DUARTREG; 
	duartsetup(dp); 
	dp++; 
	dp->duart = DUARTREG+1; 
	duartsetup(dp); 
1992/0520    
	p = &duartport[2*m->machno]; 
	duartsetup(p, d, 0); 
	p++; 
	duartsetup(p, d, 1); 
1991/0607    
} 
 
/* 
1992/0519/sys/src/9/power/devduart.c:190,1981992/0520/sys/src/9/power/devduart.c:207,215
1991/0607    
 *  enable a duart port 
 */ 
void 
duartenable(Duartport *dp) 
1992/0520    
duartenable(Port *p) 
1991/0607    
{ 
	dp->duart->cmnd = ENB_TX|ENB_RX; 
1992/0520    
	p->reg->cmnd = ENB_TX|ENB_RX; 
1991/0607    
} 
 
void 
1992/0519/sys/src/9/power/devduart.c:202,2081992/0520/sys/src/9/power/devduart.c:219,225
1991/0607    
} 
 
void 
duartbaud(Duartport *dp, int b) 
1992/0520    
duartbaud(Port *p, int b) 
1991/0607    
{ 
1992/0519    
	int x; 
1991/0607    
 
1992/0519/sys/src/9/power/devduart.c:232,2671992/0520/sys/src/9/power/devduart.c:249,284
1992/0516    
		return; 
1991/0607    
	} 
	if(x & 0x0100) 
1992/0519    
		duartacr |= 0x80; 
1992/0520    
		p->d->acr |= 0x80; 
1991/0607    
	else 
1992/0519    
		duartacr &= ~0x80; 
	dp->duart->ipc_acr = duartacr; 
1991/0607    
	dp->duart->sr_csr = x; 
1992/0520    
		p->d->acr &= ~0x80; 
	p->d->reg->ipc_acr = p->d->acr; 
	p->reg->sr_csr = x; 
1991/0607    
} 
 
void 
duartdtr(Duartport *dp, int val) 
1992/0520    
duartdtr(Port *p, int val) 
1991/0607    
{ 
	if (val) 
		dp->duart->ctlr=0x01; 
1992/0520    
		p->reg->ctlr = 0x01; 
1991/0607    
	else 
		dp->duart->ctur=0x01; 
1992/0520    
		p->reg->ctur = 0x01; 
1991/0607    
} 
 
void 
duartbreak(Duartport *dp, int val) 
1992/0520    
duartbreak(Port *p, int val) 
1991/0607    
{ 
	Duart *duart; 
1992/0520    
	Duartreg *reg; 
1991/0607    
 
	duart = dp->duart; 
1992/0520    
	reg = p->reg; 
1991/0607    
	if (val){ 
1992/0519    
		duartimr &= ~IM_XRDYB; 
		duart->is_imr = duartimr; 
1991/0607    
		duart->cmnd = STRT_BRK|ENB_TX; 
1992/0520    
		p->d->imr &= ~IM_XRDYB; 
		p->d->reg->is_imr = p->d->imr; 
		reg->cmnd = STRT_BRK|ENB_TX; 
1991/0607    
	} else { 
		duart->cmnd = STOP_BRK|ENB_TX; 
1992/0519    
		duartimr |= IM_XRDYB; 
		duart->is_imr = duartimr; 
1992/0520    
		reg->cmnd = STOP_BRK|ENB_TX; 
		p->d->imr |= IM_XRDYB; 
		p->d->reg->is_imr = p->d->imr; 
1991/0607    
	} 
} 
 
1992/0519/sys/src/9/power/devduart.c:269,3351992/0520/sys/src/9/power/devduart.c:286,352
1991/0607    
 *  do anything requested for this CPU's duarts 
 */ 
void 
duartslave0(Duartport *dp) 
1992/0520    
duartslave0(Port *p) 
1991/0607    
{ 
	switch(dp->op){ 
1992/0520    
	switch(p->op){ 
1991/0607    
	case Ddtr: 
1992/0519    
		duartdtr(dp, dp->val); 
1992/0520    
		duartdtr(p, p->val); 
1991/0607    
		break; 
	case Dbaud: 
1992/0519    
		duartbaud(dp, dp->val); 
1992/0520    
		duartbaud(p, p->val); 
1991/0607    
		break; 
	case Dbreak: 
		duartbreak(dp, dp->val); 
1992/0520    
		duartbreak(p, p->val); 
1991/0607    
		break; 
	case Dprint: 
		dp->duart->cmnd = ENB_TX; 
		dp->duart->data = dp->val; 
1992/0520    
		p->reg->cmnd = ENB_TX; 
		p->reg->data = p->val; 
1991/0607    
		break; 
	case Dena: 
		duartenable(dp); 
1992/0520    
		duartenable(p); 
1991/0607    
		break; 
	case Dstate: 
		dp->val = dp->duart->is_imr; 
1992/0520    
		p->val = p->reg->ppcr; 
1991/0607    
		break; 
	} 
	dp->op = Dnone; 
	wakeup(&dp->opr); 
1992/0520    
	p->op = Dnone; 
	wakeup(&p->opr); 
1991/0607    
} 
void 
duartslave(void) 
{ 
1992/0519    
	IOQ *cq; 
1991/0607    
	Duartport *dp; 
1992/0520    
	Port *p; 
1991/0607    
 
	dp = &duartport[2*m->machno]; 
1992/0519    
	cq = dp->iq; 
	if(dp->wq && cangetc(cq)) 
1992/0520    
	p = &duartport[2*m->machno]; 
	cq = p->iq; 
	if(p->wq && cangetc(cq)) 
1992/0519    
		wakeup(&cq->r); 
1991/0607    
	if(dp->op != Dnone) 
		duartslave0(dp); 
	dp++; 
1992/0519    
	cq = dp->iq; 
	if(dp->wq && cangetc(cq)) 
1992/0520    
	if(p->op != Dnone) 
		duartslave0(p); 
	p++; 
	cq = p->iq; 
	if(p->wq && cangetc(cq)) 
1992/0519    
		wakeup(&cq->r); 
1991/0607    
	if(dp->op != Dnone) 
		duartslave0(dp); 
1992/0520    
	if(p->op != Dnone) 
		duartslave0(p); 
1991/0607    
} 
 
1992/0519    
void 
1991/0607    
duartrintr(Duartport *dp) 
1992/0520    
duartrintr(Port *p) 
1991/0607    
{ 
	Duart *duart; 
1992/0520    
	Duartreg *reg; 
1991/0607    
	IOQ *cq; 
	int status; 
	char ch; 
 
	duart = dp->duart; 
	status = duart->sr_csr; 
	ch = duart->data; 
1992/0520    
	reg = p->reg; 
	status = reg->sr_csr; 
	ch = reg->data; 
1991/0607    
	if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) 
		duart->cmnd = RESET_ERR; 
1992/0520    
		reg->cmnd = RESET_ERR; 
1991/0607    
 
	cq = dp->iq; 
1992/0520    
	cq = p->iq; 
1991/0607    
	if(cq->putc) 
		(*cq->putc)(cq, ch); 
1992/0519    
	else 
1992/0519/sys/src/9/power/devduart.c:337,3581992/0520/sys/src/9/power/devduart.c:354,375
1991/0607    
} 
 
1992/0519    
void 
1991/0607    
duartxintr(Duartport *dp) 
1992/0520    
duartxintr(Port *p) 
1991/0607    
{ 
	Duart *duart; 
1992/0520    
	Duartreg *reg; 
1991/0607    
	IOQ *cq; 
1992/0325    
	int ch; 
1991/0607    
 
	cq = dp->oq; 
1992/0520    
	cq = p->oq; 
1991/0607    
	lock(cq); 
	ch = getc(cq); 
	duart = dp->duart; 
1992/0520    
	reg = p->reg; 
1991/0607    
	if(ch < 0){ 
		dp->printing = 0; 
1992/0520    
		p->printing = 0; 
1991/0607    
		wakeup(&cq->r); 
		duart->cmnd = DIS_TX; 
1992/0520    
		reg->cmnd = DIS_TX; 
1991/0607    
	} else 
		duart->data = ch; 
1992/0520    
		reg->data = ch; 
1991/0607    
	unlock(cq); 
} 
 
1992/0519/sys/src/9/power/devduart.c:360,3711992/0520/sys/src/9/power/devduart.c:377,389
1991/0607    
duartintr(void) 
{ 
	int cause, status, c; 
	Duart *duart; 
	Duartport *dp; 
1992/0520    
	Duartreg *reg; 
	Port *p; 
1991/0607    
 
	dp = &duartport[2*m->machno]; 
	duart = dp->duart; 
	cause = duart->is_imr; 
1992/0520    
	p = &duartport[2*m->machno]; 
	reg = p->reg; 
	cause = reg->is_imr; 
 
1991/0607    
	/* 
	 * I can guess your interrupt. 
	 */ 
1992/0519/sys/src/9/power/devduart.c:373,3941992/0520/sys/src/9/power/devduart.c:391,412
1991/0607    
	 * Is it 1? 
	 */ 
	if(cause & IM_RRDYA) 
		duartrintr(dp); 
1992/0520    
		duartrintr(p); 
1991/0607    
	/* 
	 * Is it 2? 
	 */ 
	if(cause & IM_XRDYA) 
		duartxintr(dp); 
1992/0520    
		duartxintr(p); 
1991/0607    
	/* 
	 * Is it 3? 
	 */ 
	if(cause & IM_RRDYB) 
		duartrintr(dp+1); 
1992/0520    
		duartrintr(p+1); 
1991/0607    
	/* 
	 * Is it 4? 
	 */ 
	if(cause & IM_XRDYB) 
		duartxintr(dp+1); 
1992/0520    
		duartxintr(p+1); 
1991/0607    
} 
 
/* 
1992/0519/sys/src/9/power/devduart.c:397,4181992/0520/sys/src/9/power/devduart.c:415,436
1991/0607    
int 
duartrawputc(int c) 
{ 
	Duart *duart; 
1992/0520    
	Duartreg *reg; 
1991/0607    
	int i; 
 
	duart = DUARTREG; 
1992/0520    
	reg = DUARTREG; 
1991/0607    
	if(c == '\n') 
		duartrawputc('\r'); 
	duart->cmnd = ENB_TX; 
1992/0520    
	reg->cmnd = ENB_TX; 
1991/0607    
	i = 0; 
	while((duart->sr_csr&XMT_RDY) == 0) 
1992/0520    
	while((reg->sr_csr&XMT_RDY) == 0) 
1991/0607    
		if(++i >= 1000000){ 
			duartsetup(&duartport[0]); 
1992/0520    
			duartsetup(&duartport[0], &duart[0], 0); 
1991/0607    
			for(i=0; i<100000; i++) 
				; 
			break; 
		} 
	duart->data = c; 
1992/0520    
	reg->data = c; 
1991/0607    
	if(c == '\n') 
		for(i=0; i<100000; i++) 
			; 
1992/0519/sys/src/9/power/devduart.c:447,4651992/0520/sys/src/9/power/devduart.c:465,483
1991/0607    
duartputs(IOQ *cq, char *s, int n) 
{ 
	int ch, x; 
	Duartport *dp; 
	Duart *duart; 
1992/0520    
	Port *p; 
	Duartreg *reg; 
1991/0607    
 
	x = splhi(); 
	lock(cq); 
	puts(cq, s, n); 
	dp = cq->ptr; 
	if(dp->printing == 0){ 
1992/0520    
	p = cq->ptr; 
	if(p->printing == 0){ 
1991/0607    
		ch = getc(cq); 
		if(ch >= 0){ 
			dp->printing = 1; 
			dp->val = ch; 
			dp->op = Dprint; 
1992/0520    
			p->printing = 1; 
			p->val = ch; 
			p->op = Dprint; 
1991/0607    
		} 
	} 
	unlock(cq); 
1992/0519/sys/src/9/power/devduart.c:472,4891992/0520/sys/src/9/power/devduart.c:490,507
1991/0607    
void 
duartspecial(int port, IOQ *oq, IOQ *iq, int baud) 
{ 
	Duartport *dp = &duartport[port]; 
1992/0520    
	Port *p = &duartport[port]; 
1991/0727    
	IOQ *zq; 
1991/0607    
 
	dp->nostream = 1; 
1992/0520    
	p->nostream = 1; 
1991/0607    
	if(oq){ 
		dp->oq = oq; 
		dp->oq->puts = duartputs; 
		dp->oq->ptr = dp; 
1992/0520    
		p->oq = oq; 
		p->oq->puts = duartputs; 
		p->oq->ptr = p; 
1991/0607    
	} 
	if(iq){ 
		dp->iq = iq; 
		dp->iq->ptr = dp; 
1992/0520    
		p->iq = iq; 
		p->iq->ptr = p; 
1991/0727    
 
		/* 
		 *  Stupid HACK to undo a stupid hack 
1992/0519/sys/src/9/power/devduart.c:492,4991992/0520/sys/src/9/power/devduart.c:510,517
1991/0727    
		if(iq == zq) 
			kbdq.putc = kbdcr2nl; 
1991/0607    
	} 
	duartenable(dp); 
	duartbaud(dp, baud); 
1992/0520    
	duartenable(p); 
	duartbaud(p, baud); 
1991/0607    
} 
 
static int	duartputc(IOQ *, int); 
1992/0519/sys/src/9/power/devduart.c:513,5791992/0520/sys/src/9/power/devduart.c:531,605
1991/0607    
static int 
1992/0519    
opdone(void *x) 
1991/0607    
{ 
1992/0519    
	Duartport *dp = x; 
1992/0520    
	Port *p = x; 
1991/0607    
 
1992/0519    
	return dp->op == Dnone; 
1992/0520    
	return p->op == Dnone; 
1991/0607    
} 
 
static void 
duartstopen(Queue *q, Stream *s) 
{ 
	Duartport *dp; 
1992/0520    
	Port *p; 
1991/0607    
	char name[NAMELEN]; 
 
	dp = &duartport[s->id]; 
1992/0520    
	p = &duartport[s->id]; 
1991/0607    
 
	qlock(dp); 
	dp->wq = WR(q); 
	WR(q)->ptr = dp; 
	RD(q)->ptr = dp; 
	qunlock(dp); 
1992/0520    
	qlock(p); 
	p->wq = WR(q); 
	WR(q)->ptr = p; 
	RD(q)->ptr = p; 
	qunlock(p); 
1991/0607    
 
	if(dp->kstarted == 0){ 
		dp->kstarted = 1; 
		sprint(name, "duart%d", s->id); 
		kproc(name, duartkproc, dp); 
1992/0520    
	if(p->kstarted == 0){ 
		p->kstarted = 1; 
		sprint(name, "duart%d", s->id+1); 
		kproc(name, duartkproc, p); 
1991/0607    
	} 
1992/0519    
 
	/* enable the port */ 
	dp->op = Dena; 
	sleep(&dp->opr, opdone, dp); 
1992/0520    
	qlock(p); 
	p->op = Dena; 
	sleep(&p->opr, opdone, p); 
	qunlock(p); 
1991/0607    
} 
 
static void 
duartstclose(Queue *q) 
{ 
	Duartport *dp = q->ptr; 
1992/0520    
	Port *p = q->ptr; 
1991/0607    
 
	qlock(dp); 
	dp->wq = 0; 
	dp->iq->putc = 0; 
1992/0520    
	qlock(p); 
	p->wq = 0; 
	p->iq->putc = 0; 
1991/0607    
	WR(q)->ptr = 0; 
	RD(q)->ptr = 0; 
	qunlock(dp); 
1992/0520    
	qunlock(p); 
1991/0607    
} 
 
static void 
duartoput(Queue *q, Block *bp) 
{ 
	Duartport *dp = q->ptr; 
1992/0520    
	Port *p = q->ptr; 
1991/0607    
	IOQ *cq; 
	int n, m; 
 
	if(dp == 0){ 
1992/0520    
	if(p == 0){ 
1991/0607    
		freeb(bp); 
		return; 
	} 
	cq = dp->oq; 
1992/0520    
	cq = p->oq; 
1991/0607    
	if(waserror()){ 
		freeb(bp); 
		nexterror(); 
	} 
	if(bp->type == M_CTL){ 
		qlock(dp); 
1992/0520    
		if(waserror()){ 
			qunlock(p); 
			qunlock(p->d); 
			nexterror(); 
		} 
		qlock(p); 
		qlock(p->d); 
1991/0607    
		while (cangetc(cq))	/* let output drain */ 
			sleep(&cq->r, cangetc, cq); 
		n = strtoul((char *)(bp->rptr+1), 0, 0); 
1992/0519/sys/src/9/power/devduart.c:580,6041992/0520/sys/src/9/power/devduart.c:606,633
1991/0607    
		switch(*bp->rptr){ 
		case 'B': 
		case 'b': 
			dp->val = n; 
			dp->op = Dbaud; 
			sleep(&dp->opr, opdone, dp); 
1992/0520    
			p->val = n; 
			p->op = Dbaud; 
			sleep(&p->opr, opdone, p); 
1991/0607    
			break; 
		case 'D': 
		case 'd': 
			dp->val = n; 
			dp->op = Ddtr; 
			sleep(&dp->opr, opdone, dp); 
1992/0520    
			p->val = n; 
			p->op = Ddtr; 
			sleep(&p->opr, opdone, p); 
1991/0607    
			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); 
1992/0520    
			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); 
1991/0607    
			break; 
		case 'R': 
		case 'r': 
1992/0519/sys/src/9/power/devduart.c:605,6111992/0520/sys/src/9/power/devduart.c:634,642
1991/0607    
			/* can't control? */ 
			break; 
		} 
		qunlock(dp); 
1992/0520    
		qunlock(p->d); 
		qunlock(p); 
		poperror(); 
1991/0607    
	}else while((m = BLEN(bp)) > 0){ 
		while ((n = canputc(cq)) == 0){ 
			kprint(" duartoput: sleeping\n"); 
1992/0519/sys/src/9/power/devduart.c:626,6331992/0520/sys/src/9/power/devduart.c:657,664
1991/0607    
static void 
duartkproc(void *a) 
{ 
	Duartport *dp = a; 
	IOQ *cq = dp->iq; 
1992/0520    
	Port *p = a; 
	IOQ *cq = p->iq; 
1991/0607    
	Block *bp; 
	int n; 
 
1992/0519/sys/src/9/power/devduart.c:634,6491992/0520/sys/src/9/power/devduart.c:665,680
1991/0607    
loop: 
	while ((n = cangetc(cq)) == 0) 
		sleep(&cq->r, cangetc, cq); 
	qlock(dp); 
	if(dp->wq == 0){ 
1992/0520    
	qlock(p); 
	if(p->wq == 0){ 
1991/0607    
		cq->out = cq->in; 
	}else{ 
		bp = allocb(n); 
		bp->flags |= S_DELIM; 
		bp->wptr += gets(cq, bp->wptr, n); 
		PUTNEXT(RD(dp->wq), bp); 
1992/0520    
		PUTNEXT(RD(p->wq), bp); 
1991/0607    
	} 
	qunlock(dp); 
1992/0520    
	qunlock(p); 
1991/0607    
	goto loop; 
} 
 
1992/0519/sys/src/9/power/devduart.c:656,6621992/0520/sys/src/9/power/devduart.c:687,693
1991/0607    
void 
duartreset(void) 
{ 
	Duartport *dp; 
1992/0520    
	Port *p; 
1991/0607    
	int i; 
 
	/* 
1992/0519/sys/src/9/power/devduart.c:665,6721992/0520/sys/src/9/power/devduart.c:696,703
1991/0607    
	nduartport = 2*conf.nmach; 
	duartdir = ialloc(nduartport*2*sizeof(Dirtab), 0); 
	for(i = 0; i < nduartport; i++){ 
1991/1115    
		sprint(duartdir[2*i].name, "eia%d", i); 
		sprint(duartdir[2*i+1].name, "eia%dctl", i); 
1992/0520    
		sprint(duartdir[2*i].name, "eia%d", i+1); 
		sprint(duartdir[2*i+1].name, "eia%dctl", i+1); 
1992/0519    
		duartdir[2*i].length = 0; 
		duartdir[2*i+1].length = 0; 
		duartdir[2*i].perm = 0666; 
1992/0519/sys/src/9/power/devduart.c:678,6951992/0520/sys/src/9/power/devduart.c:709,726
1991/0607    
	/* 
	 *  allocate queues for any stream interfaces 
	 */ 
	for(dp = duartport; dp < &duartport[nduartport]; dp++){ 
		if(dp->nostream) 
1992/0520    
	for(p = duartport; p < &duartport[nduartport]; p++){ 
		if(p->nostream) 
1991/0607    
			continue; 
 
		dp->iq = ialloc(sizeof(IOQ), 0); 
		initq(dp->iq); 
		dp->iq->ptr = dp; 
1992/0520    
		p->iq = ialloc(sizeof(IOQ), 0); 
		initq(p->iq); 
		p->iq->ptr = p; 
1991/0607    
 
		dp->oq = ialloc(sizeof(IOQ), 0); 
		initq(dp->oq); 
		dp->oq->ptr = dp; 
		dp->oq->puts = duartputs; 
1992/0520    
		p->oq = ialloc(sizeof(IOQ), 0); 
		initq(p->oq); 
		p->oq->ptr = p; 
		p->oq->puts = duartputs; 
1991/0607    
	} 
} 
 
1992/0519/sys/src/9/power/devduart.c:712,7251992/0520/sys/src/9/power/devduart.c:743,756
1991/0607    
} 
 
void 
duartstat(Chan *c, char *dp) 
1992/0520    
duartstat(Chan *c, char *p) 
1991/0607    
{ 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
1992/0519    
		streamstat(c, dp, duartdir[2*STREAMID(c->qid.path)].name); 
1992/0520    
		streamstat(c, p, duartdir[2*STREAMID(c->qid.path)].name); 
1991/0607    
		break; 
	default: 
		devstat(c, dp, duartdir, 2*nduartport, devgen); 
1992/0520    
		devstat(c, p, duartdir, 2*nduartport, devgen); 
1991/0607    
		break; 
	} 
} 
1992/0519/sys/src/9/power/devduart.c:727,7451992/0520/sys/src/9/power/devduart.c:758,776
1991/0607    
Chan* 
duartopen(Chan *c, int omode) 
{ 
	Duartport *dp; 
1992/0520    
	Port *p; 
1991/0607    
 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
	case Sctlqid: 
		dp = &duartport[STREAMID(c->qid.path)]; 
1992/0520    
		p = &duartport[STREAMID(c->qid.path)]; 
1991/0607    
		break; 
	default: 
		dp = 0; 
1992/0520    
		p = 0; 
1991/0607    
		break; 
	} 
 
	if(dp && dp->nostream) 
1992/0520    
	if(p && p->nostream) 
1992/0114    
		error(Einuse); 
1991/0607    
 
	if((c->qid.path & CHDIR) == 0) 
1992/0519/sys/src/9/power/devduart.c:764,7701992/0520/sys/src/9/power/devduart.c:795,801
1991/0607    
long 
duartread(Chan *c, void *buf, long n, ulong offset) 
{ 
	Duartport *dp; 
1992/0520    
	Port *p; 
1991/0607    
 
	if(c->qid.path&CHDIR) 
		return devdirread(c, buf, n, duartdir, 2*nduartport, devgen); 
1992/0519/sys/src/9/power/devduart.c:775,7861992/0520/sys/src/9/power/devduart.c:806,817
1991/0607    
	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); 
1992/0520    
		p = &duartport[STREAMID(c->qid.path)]; 
		qlock(p); 
		p->op = Dstate; 
		sleep(&p->opr, opdone, p); 
		*(uchar *)buf = p->val; 
		qunlock(p); 
1991/0607    
		return 1; 
	} 
 
1992/0519/sys/src/9/power/devduart.c:802,8081992/0520/sys/src/9/power/devduart.c:833,839
1991/0607    
} 
 
void 
duartwstat(Chan *c, char *dp) 
1992/0520    
duartwstat(Chan *c, char *p) 
1991/0607    
{ 
1991/1214    
	USED(c); 
1992/0114    
	error(Eperm); 
1992/0520/sys/src/9/power/devduart.c:201,2061992/0608/sys/src/9/power/devduart.c:201,207 (short | long)
1992/0520    
	duartsetup(p, d, 0); 
	p++; 
	duartsetup(p, d, 1); 
1992/0608    
	d->inited = 1; 
1991/0607    
} 
 
/* 
1992/0608/sys/src/9/power/devduart.c:695,7011992/0622/sys/src/9/power/devduart.c:695,701 (short | long)
1991/0607    
 	 *  allocate the directory and fill it in 
	 */ 
	nduartport = 2*conf.nmach; 
	duartdir = ialloc(nduartport*2*sizeof(Dirtab), 0); 
1992/0622    
	duartdir = xalloc(nduartport*2*sizeof(Dirtab)); 
1991/0607    
	for(i = 0; i < nduartport; i++){ 
1992/0520    
		sprint(duartdir[2*i].name, "eia%d", i+1); 
		sprint(duartdir[2*i+1].name, "eia%dctl", i+1); 
1992/0608/sys/src/9/power/devduart.c:714,7241992/0622/sys/src/9/power/devduart.c:714,724
1992/0520    
		if(p->nostream) 
1991/0607    
			continue; 
 
1992/0520    
		p->iq = ialloc(sizeof(IOQ), 0); 
1992/0622    
		p->iq = xalloc(sizeof(IOQ)); 
1992/0520    
		initq(p->iq); 
		p->iq->ptr = p; 
1991/0607    
 
1992/0520    
		p->oq = ialloc(sizeof(IOQ), 0); 
1992/0622    
		p->oq = xalloc(sizeof(IOQ)); 
1992/0520    
		initq(p->oq); 
		p->oq->ptr = p; 
		p->oq->puts = duartputs; 
1992/0622/sys/src/9/power/devduart.c:377,3831992/0711/sys/src/9/power/devduart.c:377,383 (short | long)
1991/0607    
void 
duartintr(void) 
{ 
	int cause, status, c; 
1992/0711    
	int cause; 
1992/0520    
	Duartreg *reg; 
	Port *p; 
1991/0607    
 
1992/0622/sys/src/9/power/devduart.c:467,4731992/0711/sys/src/9/power/devduart.c:467,472
1991/0607    
{ 
	int ch, x; 
1992/0520    
	Port *p; 
	Duartreg *reg; 
1991/0607    
 
	x = splhi(); 
	lock(cq); 
1992/0622/sys/src/9/power/devduart.c:783,7881992/0711/sys/src/9/power/devduart.c:782,790
1991/0607    
duartcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1214    
	USED(c); 
1992/0711    
	USED(name); 
	USED(omode); 
	USED(perm); 
1991/1120    
	error(Eperm); 
1991/0607    
} 
 
1992/0622/sys/src/9/power/devduart.c:823,8281992/0711/sys/src/9/power/devduart.c:825,831
1991/0607    
long 
duartwrite(Chan *c, void *va, long n, ulong offset) 
{ 
1992/0711    
	USED(offset); 
1991/0607    
	return streamwrite(c, va, n, 0); 
} 
 
1992/0622/sys/src/9/power/devduart.c:837,8421992/0711/sys/src/9/power/devduart.c:840,846
1992/0520    
duartwstat(Chan *c, char *p) 
1991/0607    
{ 
1991/1214    
	USED(c); 
1992/0711    
	USED(p); 
1992/0114    
	error(Eperm); 
1991/0607    
} 
 
1992/0711/sys/src/9/power/devduart.c:747,7531992/0826/sys/src/9/power/devduart.c:747,754 (short | long)
1991/0607    
{ 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
1992/0520    
		streamstat(c, p, duartdir[2*STREAMID(c->qid.path)].name); 
1992/0826    
		streamstat(c, p, duartdir[2*STREAMID(c->qid.path)].name, 
			duartdir[2*STREAMID(c->qid.path)].perm); 
1991/0607    
		break; 
	default: 
1992/0520    
		devstat(c, p, duartdir, 2*nduartport, devgen); 
1992/0826/sys/src/9/power/devduart.c:447,4601993/0501/sys/src/9/power/devduart.c:447,459 (short | long)
1991/0607    
	for(i=0; i < 1000000; i++) 
		; 
} 
1993/0501    
 
1991/0607    
void 
iprint(char *fmt, ...) 
{ 
	char buf[1024]; 
	long *arg; 
1993/0501    
	char buf[512]; 
1991/0607    
 
	arg = (long*)(&fmt+1); 
	sprint(buf, fmt, *arg, *(arg+1), *(arg+2), *(arg+3)); 
1993/0501    
	doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); 
1991/0607    
	duartrawputs(buf); 
} 
 
1993/0501/sys/src/9/power/devduart.c:6,1091993/0806/sys/src/9/power/devduart.c:6,108 (short | long)
1991/0607    
#include	"io.h" 
1992/0111    
#include	"../port/error.h" 
1991/0607    
 
void	duartputs(IOQ*, char*, int); 
void	iprint(char*, ...); 
1993/0806    
#include	"devtab.h" 
#include	"../port/netif.h" 
1991/0607    
 
#define	PAD	15	/* registers are well-spaced */ 
                 
/* 
1992/0520    
 *  Register set for half the duart.  There are really two sets in adjacent 
 *  memory locations. 
1993/0806    
 * Register set for half the duart.  
 * There are really two sets in adjacent memory locations. 
1991/0607    
 */ 
1992/0520    
struct Duartreg 
{ 
1991/0607    
	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]; 
1993/0806    
	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]; 
1991/0607    
}; 
#define	ppcr	is_imr		/* in the second register set */ 
1993/0806    
#define	ppcr	isimr		/* in the second register set */ 
1991/0607    
 
#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 
1993/0806    
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, 
1991/0607    
 
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, 
                 
1992/0520    
	Maxduart	=8, 
1993/0806    
	Maxduart	= 8, 
1991/0607    
}; 
 
/* 
 *  requests to perform on a duart 
 */ 
enum { 
1993/0806    
enum 
{ 
1991/0607    
	Dnone=	0, 
	Dbaud, 
	Dbreak, 
1993/0501/sys/src/9/power/devduart.c:130,1401993/0806/sys/src/9/power/devduart.c:129,138
1992/0520    
/* 
 *  values specific to a single duart port 
 */ 
typedef struct Port	Port; 
struct Port 
1993/0806    
typedef struct Uart	Uart; 
struct Uart 
1992/0520    
{ 
	QLock; 
	int		printing;	/* true if printing */ 
	Duart		*d;		/* device */ 
	Duartreg	*reg;		/* duart registers (for this port) */ 
	int		c;		/* character to restart output */ 
1993/0501/sys/src/9/power/devduart.c:142,1651993/0806/sys/src/9/power/devduart.c:140,164
1992/0520    
	int		val;		/* value of operation */ 
	Rendez		opr;		/* waiot here for op to complete */ 
 
1991/0607    
	/* console interface */ 
1992/0520    
	int		nostream;	/* can't use the stream interface */ 
	IOQ		*iq;		/* input character queue */ 
	IOQ		*oq;		/* output character queue */ 
1993/0806    
	int		printing;	/* need kick */ 
	int		opens; 
	Rendez		r; 
1991/0607    
 
	/* stream interface */ 
1992/0520    
	Queue		*wq;		/* write queue */ 
	Rendez		r;		/* kproc waiting for input */ 
 	int		kstarted;	/* kproc started */ 
1993/0806    
	/* buffers */ 
	int	(*putc)(Queue*, int); 
	Queue	*iq; 
	Queue	*oq; 
1991/0607    
}; 
1992/0520    
Port duartport[2*Maxduart]; 
1993/0806    
Uart uart[2*Maxduart]; 
1991/0607    
 
1993/0806    
void	duartkick(Uart*); 
 
1991/0607    
/* 
 *  configure a duart port, default is 9600 baud, 8 bits/char, 1 stop bit, 
 *  no parity 
 */ 
void 
1992/0520    
duartsetup(Port *p, Duart *d, int devno) 
1993/0806    
duartsetup(Uart *p, Duart *d, int devno) 
1991/0607    
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
 
1993/0501/sys/src/9/power/devduart.c:167,1821993/0806/sys/src/9/power/devduart.c:166,184
1992/0520    
	reg = &d->reg[devno]; 
	p->reg = reg; 
1991/0607    
 
1992/0520    
	reg->cmnd = RESET_RCV|DIS_TX|DIS_RX; 
	reg->cmnd = RESET_TRANS; 
	reg->cmnd = RESET_ERR; 
	reg->cmnd = STOP_BRK; 
1993/0806    
	reg->cmnd = RESETRCV|DISTX|DISRX; 
	reg->cmnd = RESETTRANS; 
	reg->cmnd = RESETERR; 
	reg->cmnd = STOPBRK; 
1991/0607    
 
1992/0520    
	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; 
1993/0806    
	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); 
1991/0607    
} 
 
/* 
1993/0501/sys/src/9/power/devduart.c:185,2031993/0806/sys/src/9/power/devduart.c:187,207
1991/0607    
void 
duartinit(void) 
{ 
1992/0520    
	Port *p; 
1993/0806    
	Uart *p; 
1992/0520    
	Duart *d; 
1991/0607    
 
1992/0520    
	d = &duart[m->machno]; 
	if(d->inited) 
1991/0607    
		return; 
1993/0806    
 
1992/0520    
	d->reg = DUARTREG; 
	d->imr = IM_RRDYA|IM_XRDYA|IM_RRDYB|IM_XRDYB; 
	d->reg->is_imr = d->imr; 
1993/0806    
	d->imr = IMRRDYA|IMXRDYA|IMRRDYB|IMXRDYB; 
	d->reg->isimr = d->imr; 
1992/0520    
	d->acr = 0x80;			/* baud rate set 2 */ 
	d->reg->ipc_acr = d->acr; 
1993/0806    
	d->reg->ipcacr = d->acr; 
1991/0607    
 
1992/0520    
	p = &duartport[2*m->machno]; 
1993/0806    
	p = &uart[2*m->machno]; 
 
1992/0520    
	duartsetup(p, d, 0); 
	p++; 
	duartsetup(p, d, 1); 
1993/0501/sys/src/9/power/devduart.c:208,2261993/0806/sys/src/9/power/devduart.c:212,230
1991/0607    
 *  enable a duart port 
 */ 
void 
1992/0520    
duartenable(Port *p) 
1993/0806    
duartenable(Uart *p) 
1991/0607    
{ 
1992/0520    
	p->reg->cmnd = ENB_TX|ENB_RX; 
1993/0806    
	p->reg->cmnd = ENBTX|ENBRX; 
1991/0607    
} 
 
void 
duartenable0(void) 
{ 
	DUARTREG->cmnd = ENB_TX|ENB_RX; 
1993/0806    
	DUARTREG->cmnd = ENBTX|ENBRX; 
1991/0607    
} 
 
void 
1992/0520    
duartbaud(Port *p, int b) 
1993/0806    
duartbaud(Uart *p, int b) 
1991/0607    
{ 
1992/0519    
	int x; 
1991/0607    
 
1993/0501/sys/src/9/power/devduart.c:253,2641993/0806/sys/src/9/power/devduart.c:257,268
1992/0520    
		p->d->acr |= 0x80; 
1991/0607    
	else 
1992/0520    
		p->d->acr &= ~0x80; 
	p->d->reg->ipc_acr = p->d->acr; 
	p->reg->sr_csr = x; 
1993/0806    
	p->d->reg->ipcacr = p->d->acr; 
	p->reg->srcsr = x; 
1991/0607    
} 
 
void 
1992/0520    
duartdtr(Port *p, int val) 
1993/0806    
duartdtr(Uart *p, int val) 
1991/0607    
{ 
	if (val) 
1992/0520    
		p->reg->ctlr = 0x01; 
1993/0501/sys/src/9/power/devduart.c:267,2851993/0806/sys/src/9/power/devduart.c:271,289
1991/0607    
} 
 
void 
1992/0520    
duartbreak(Port *p, int val) 
1993/0806    
duartbreak(Uart *p, int val) 
1991/0607    
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
 
1992/0520    
	reg = p->reg; 
1991/0607    
	if (val){ 
1992/0520    
		p->d->imr &= ~IM_XRDYB; 
		p->d->reg->is_imr = p->d->imr; 
		reg->cmnd = STRT_BRK|ENB_TX; 
1993/0806    
		p->d->imr &= ~IMXRDYB; 
		p->d->reg->isimr = p->d->imr; 
		reg->cmnd = STRTBRK|ENBTX; 
1991/0607    
	} else { 
1992/0520    
		reg->cmnd = STOP_BRK|ENB_TX; 
		p->d->imr |= IM_XRDYB; 
		p->d->reg->is_imr = p->d->imr; 
1993/0806    
		reg->cmnd = STOPBRK|ENBTX; 
		p->d->imr |= IMXRDYB; 
		p->d->reg->isimr = p->d->imr; 
1991/0607    
	} 
} 
 
1993/0501/sys/src/9/power/devduart.c:287,2931993/0806/sys/src/9/power/devduart.c:291,297
1991/0607    
 *  do anything requested for this CPU's duarts 
 */ 
void 
1992/0520    
duartslave0(Port *p) 
1993/0806    
duartslave0(Uart *p) 
1991/0607    
{ 
1992/0520    
	switch(p->op){ 
1991/0607    
	case Ddtr: 
1993/0501/sys/src/9/power/devduart.c:300,3071993/0806/sys/src/9/power/devduart.c:304,312
1992/0520    
		duartbreak(p, p->val); 
1991/0607    
		break; 
	case Dprint: 
1992/0520    
		p->reg->cmnd = ENB_TX; 
1993/0806    
		p->reg->cmnd = ENBTX; 
1992/0520    
		p->reg->data = p->val; 
1993/0806    
iprint("slave %c\n", p->val); 
1991/0607    
		break; 
	case Dena: 
1992/0520    
		duartenable(p); 
1993/0501/sys/src/9/power/devduart.c:316,3771993/0806/sys/src/9/power/devduart.c:321,395
1991/0607    
void 
duartslave(void) 
{ 
1992/0519    
	IOQ *cq; 
1992/0520    
	Port *p; 
1993/0806    
	Uart *p; 
1991/0607    
 
1992/0520    
	p = &duartport[2*m->machno]; 
	cq = p->iq; 
	if(p->wq && cangetc(cq)) 
1992/0519    
		wakeup(&cq->r); 
1993/0806    
	p = &uart[2*m->machno]; 
1992/0520    
	if(p->op != Dnone) 
		duartslave0(p); 
	p++; 
	cq = p->iq; 
	if(p->wq && cangetc(cq)) 
1992/0519    
		wakeup(&cq->r); 
1992/0520    
	if(p->op != Dnone) 
		duartslave0(p); 
1991/0607    
} 
 
1992/0519    
void 
1992/0520    
duartrintr(Port *p) 
1993/0806    
duartrintr(Uart *p) 
1991/0607    
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
	IOQ *cq; 
	int status; 
	char ch; 
1993/0806    
	int status; 
	Duartreg *reg; 
1991/0607    
 
1992/0520    
	reg = p->reg; 
	status = reg->sr_csr; 
1993/0806    
	status = reg->srcsr; 
1992/0520    
	ch = reg->data; 
1991/0607    
	if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) 
1992/0520    
		reg->cmnd = RESET_ERR; 
1993/0806    
	if(status & (FRMERR|OVRERR|PARERR)) 
		reg->cmnd = RESETERR; 
1991/0607    
 
1992/0520    
	cq = p->iq; 
1991/0607    
	if(cq->putc) 
		(*cq->putc)(cq, ch); 
1993/0806    
	if(p->putc) 
		(*p->putc)(p->iq, ch); 
1992/0519    
	else 
1991/0607    
		putc(cq, ch); 
1993/0806    
		qproduce(p->iq, &ch, 1); 
1991/0607    
} 
 
1993/0806    
/* 
 *  (re)start output 
 */ 
1992/0519    
void 
1992/0520    
duartxintr(Port *p) 
1993/0806    
duartkick(Uart *p) 
1991/0607    
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
	IOQ *cq; 
1993/0806    
	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) 
{ 
1992/0325    
	int ch; 
1993/0806    
	Duartreg *reg; 
1991/0607    
 
1992/0520    
	cq = p->oq; 
1991/0607    
	lock(cq); 
	ch = getc(cq); 
1992/0520    
	reg = p->reg; 
1991/0607    
	if(ch < 0){ 
1993/0806    
	if(qconsume(p->oq, &ch, 1) <= 0) { 
1992/0520    
		p->printing = 0; 
1991/0607    
		wakeup(&cq->r); 
1992/0520    
		reg->cmnd = DIS_TX; 
1991/0607    
	} else 
1993/0806    
		reg->cmnd = DISTX; 
	} 
	else 
1992/0520    
		reg->data = ch; 
1991/0607    
	unlock(cq); 
} 
 
void 
1993/0501/sys/src/9/power/devduart.c:379,4121993/0806/sys/src/9/power/devduart.c:397,418
1991/0607    
{ 
1992/0711    
	int cause; 
1992/0520    
	Duartreg *reg; 
	Port *p; 
1993/0806    
	Uart *p; 
1991/0607    
 
1992/0520    
	p = &duartport[2*m->machno]; 
1993/0806    
	p = &uart[2*m->machno]; 
1992/0520    
	reg = p->reg; 
	cause = reg->is_imr; 
1993/0806    
	cause = reg->isimr; 
1992/0520    
 
1991/0607    
	/* 
	 * I can guess your interrupt. 
	 */ 
	/* 
	 * Is it 1? 
	 */ 
	if(cause & IM_RRDYA) 
1993/0806    
	if(cause & IMRRDYA) 
1992/0520    
		duartrintr(p); 
1991/0607    
	/* 
	 * Is it 2? 
	 */ 
	if(cause & IM_XRDYA) 
1993/0806    
 
	if(cause & IMXRDYA) 
1992/0520    
		duartxintr(p); 
1991/0607    
	/* 
	 * Is it 3? 
	 */ 
	if(cause & IM_RRDYB) 
1993/0806    
 
	if(cause & IMRRDYB) 
1992/0520    
		duartrintr(p+1); 
1991/0607    
	/* 
	 * Is it 4? 
	 */ 
	if(cause & IM_XRDYB) 
1993/0806    
 
	if(cause & IMXRDYB) 
1992/0520    
		duartxintr(p+1); 
1991/0607    
} 
 
1993/0501/sys/src/9/power/devduart.c:416,7251993/0806/sys/src/9/power/devduart.c:422,506
1991/0607    
int 
duartrawputc(int c) 
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
	int i; 
1993/0806    
	Duartreg *reg; 
1991/0607    
 
1992/0520    
	reg = DUARTREG; 
1991/0607    
	if(c == '\n') 
1993/0806    
	if(c == '\n') { 
1991/0607    
		duartrawputc('\r'); 
1992/0520    
	reg->cmnd = ENB_TX; 
1993/0806    
		delay(100); 
	} 
	reg->cmnd = ENBTX; 
1991/0607    
	i = 0; 
1992/0520    
	while((reg->sr_csr&XMT_RDY) == 0) 
1991/0607    
		if(++i >= 1000000){ 
1992/0520    
			duartsetup(&duartport[0], &duart[0], 0); 
1991/0607    
			for(i=0; i<100000; i++) 
				; 
			break; 
		} 
1993/0806    
	while((reg->srcsr&XMTRDY) == 0 && i++ < 100000) 
		; 
1992/0520    
	reg->data = c; 
1991/0607    
	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++) 
		; 
} 
1993/0501    
 
1991/0607    
void 
1993/0806    
int 
1991/0607    
iprint(char *fmt, ...) 
{ 
1993/0806    
	int n, i; 
1993/0501    
	char buf[512]; 
1991/0607    
 
1993/0501    
	doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); 
1991/0607    
	duartrawputs(buf); 
1993/0806    
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
	for(i = 0; i < n; i++) 
		duartrawputc(buf[i]); 
	return n; 
1991/0607    
} 
 
/* 
 *  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) 
1993/0806    
duartspecial(int port, int s, Queue **in, Queue **out, int (*putc)(Queue*, int)) 
1991/0607    
{ 
	int ch, x; 
1992/0520    
	Port *p; 
1993/0806    
	Uart *p; 
1991/0607    
 
	x = splhi(); 
	lock(cq); 
	puts(cq, s, n); 
1992/0520    
	p = cq->ptr; 
	if(p->printing == 0){ 
1991/0607    
		ch = getc(cq); 
		if(ch >= 0){ 
1992/0520    
			p->printing = 1; 
			p->val = ch; 
			p->op = Dprint; 
1991/0607    
		} 
	} 
	unlock(cq); 
	splx(x); 
} 
1993/0806    
	p = &uart[port]; 
1991/0607    
 
/* 
 *  set up an duart port as something other than a stream 
 */ 
void 
duartspecial(int port, IOQ *oq, IOQ *iq, int baud) 
{ 
1992/0520    
	Port *p = &duartport[port]; 
1991/0727    
	IOQ *zq; 
1993/0806    
	duartenable(p); 
	if(s) 
		duartbaud(p, s); 
1991/0607    
 
1992/0520    
	p->nostream = 1; 
1991/0607    
	if(oq){ 
1992/0520    
		p->oq = oq; 
		p->oq->puts = duartputs; 
		p->oq->ptr = p; 
1991/0607    
	} 
	if(iq){ 
1992/0520    
		p->iq = iq; 
		p->iq->ptr = p; 
1993/0806    
	p->putc = putc; 
	if(in) 
		*in = p->iq; 
	if(out) 
		*out = p->oq; 
1991/0727    
 
		/* 
		 *  Stupid HACK to undo a stupid hack 
		 */  
		zq = &kbdq; 
		if(iq == zq) 
			kbdq.putc = kbdcr2nl; 
1991/0607    
	} 
1992/0520    
	duartenable(p); 
	duartbaud(p, baud); 
1993/0806    
	p->opens++; 
1991/0607    
} 
 
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" 
}; 
                 
static int 
1992/0519    
opdone(void *x) 
1991/0607    
{ 
1992/0520    
	Port *p = x; 
1993/0806    
	Uart *p = x; 
1991/0607    
 
1992/0520    
	return p->op == Dnone; 
1991/0607    
} 
 
static void 
duartstopen(Queue *q, Stream *s) 
{ 
1992/0520    
	Port *p; 
1991/0607    
	char name[NAMELEN]; 
                 
1992/0520    
	p = &duartport[s->id]; 
1991/0607    
                 
1992/0520    
	qlock(p); 
	p->wq = WR(q); 
	WR(q)->ptr = p; 
	RD(q)->ptr = p; 
	qunlock(p); 
1991/0607    
                 
1992/0520    
	if(p->kstarted == 0){ 
		p->kstarted = 1; 
		sprint(name, "duart%d", s->id+1); 
		kproc(name, duartkproc, p); 
1991/0607    
	} 
1992/0519    
                 
	/* enable the port */ 
1992/0520    
	qlock(p); 
	p->op = Dena; 
	sleep(&p->opr, opdone, p); 
	qunlock(p); 
1991/0607    
} 
                 
static void 
duartstclose(Queue *q) 
{ 
1992/0520    
	Port *p = q->ptr; 
1991/0607    
                 
1992/0520    
	qlock(p); 
	p->wq = 0; 
	p->iq->putc = 0; 
1991/0607    
	WR(q)->ptr = 0; 
	RD(q)->ptr = 0; 
1992/0520    
	qunlock(p); 
1991/0607    
} 
                 
static void 
duartoput(Queue *q, Block *bp) 
{ 
1992/0520    
	Port *p = q->ptr; 
1991/0607    
	IOQ *cq; 
	int n, m; 
                 
1992/0520    
	if(p == 0){ 
1991/0607    
		freeb(bp); 
		return; 
	} 
1992/0520    
	cq = p->oq; 
1991/0607    
	if(waserror()){ 
		freeb(bp); 
		nexterror(); 
	} 
	if(bp->type == M_CTL){ 
1992/0520    
		if(waserror()){ 
			qunlock(p); 
			qunlock(p->d); 
			nexterror(); 
		} 
		qlock(p); 
		qlock(p->d); 
1991/0607    
		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': 
1992/0520    
			p->val = n; 
			p->op = Dbaud; 
			sleep(&p->opr, opdone, p); 
1991/0607    
			break; 
		case 'D': 
		case 'd': 
1992/0520    
			p->val = n; 
			p->op = Ddtr; 
			sleep(&p->opr, opdone, p); 
1991/0607    
			break; 
		case 'K': 
		case 'k': 
1992/0520    
			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); 
1991/0607    
			break; 
		case 'R': 
		case 'r': 
			/* can't control? */ 
			break; 
		} 
1992/0520    
		qunlock(p->d); 
		qunlock(p); 
		poperror(); 
1991/0607    
	}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) 
{ 
1992/0520    
	Port *p = a; 
	IOQ *cq = p->iq; 
1991/0607    
	Block *bp; 
	int n; 
                 
loop: 
	while ((n = cangetc(cq)) == 0) 
		sleep(&cq->r, cangetc, cq); 
1992/0520    
	qlock(p); 
	if(p->wq == 0){ 
1991/0607    
		cq->out = cq->in; 
	}else{ 
		bp = allocb(n); 
		bp->flags |= S_DELIM; 
		bp->wptr += gets(cq, bp->wptr, n); 
1992/0520    
		PUTNEXT(RD(p->wq), bp); 
1991/0607    
	} 
1992/0520    
	qunlock(p); 
1991/0607    
	goto loop; 
} 
                 
Dirtab *duartdir; 
int nduartport; 
1993/0806    
int nuart; 
1991/0607    
 
/* 
 *  allocate the queues if no one else has 
 */ 
void 
duartreset(void) 
{ 
1992/0520    
	Port *p; 
1991/0607    
	int i; 
1993/0806    
	Dirtab *dp; 
1991/0607    
 
	/* 
 	 *  allocate the directory and fill it in 
	 */ 
	nduartport = 2*conf.nmach; 
1992/0622    
	duartdir = xalloc(nduartport*2*sizeof(Dirtab)); 
1991/0607    
	for(i = 0; i < nduartport; i++){ 
1992/0520    
		sprint(duartdir[2*i].name, "eia%d", i+1); 
		sprint(duartdir[2*i+1].name, "eia%dctl", i+1); 
1992/0519    
		duartdir[2*i].length = 0; 
		duartdir[2*i+1].length = 0; 
		duartdir[2*i].perm = 0666; 
		duartdir[2*i+1].perm = 0666; 
1991/0607    
		duartdir[2*i].qid.path = STREAMQID(i, Sdataqid); 
		duartdir[2*i+1].qid.path = STREAMQID(i, Sctlqid); 
	} 
1993/0806    
	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++; 
1991/0607    
 
	/* 
	 *  allocate queues for any stream interfaces 
	 */ 
1992/0520    
	for(p = duartport; p < &duartport[nduartport]; p++){ 
		if(p->nostream) 
1991/0607    
			continue; 
                 
1992/0622    
		p->iq = xalloc(sizeof(IOQ)); 
1992/0520    
		initq(p->iq); 
		p->iq->ptr = p; 
1991/0607    
                 
1992/0622    
		p->oq = xalloc(sizeof(IOQ)); 
1992/0520    
		initq(p->oq); 
		p->oq->ptr = p; 
		p->oq->puts = duartputs; 
1993/0806    
		print(dp->name, "eia%dctl", i); 
		dp->qid.path = NETQID(i, Nctlqid); 
		dp->perm = 0666; 
		dp++; 
1991/0607    
	} 
} 
 
1993/0501/sys/src/9/power/devduart.c:738,7561993/0806/sys/src/9/power/devduart.c:519,543
1991/0607    
int 
duartwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, duartdir, 2*nduartport, devgen); 
1993/0806    
	return devwalk(c, name, duartdir, 2*nuart, devgen); 
1991/0607    
} 
 
void 
1992/0520    
duartstat(Chan *c, char *p) 
1993/0806    
duartstat(Chan *c, char *dp) 
1991/0607    
{ 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
1992/0826    
		streamstat(c, p, duartdir[2*STREAMID(c->qid.path)].name, 
			duartdir[2*STREAMID(c->qid.path)].perm); 
1993/0806    
	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); 
1991/0607    
		break; 
	default: 
1992/0520    
		devstat(c, p, duartdir, 2*nduartport, devgen); 
1993/0806    
		devstat(c, dp, duartdir, 2*nuart, devgen); 
1991/0607    
		break; 
	} 
} 
1993/0501/sys/src/9/power/devduart.c:758,7901993/0806/sys/src/9/power/devduart.c:545,581
1991/0607    
Chan* 
duartopen(Chan *c, int omode) 
{ 
1992/0520    
	Port *p; 
1993/0806    
	Uart *p; 
1991/0607    
 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
	case Sctlqid: 
1992/0520    
		p = &duartport[STREAMID(c->qid.path)]; 
1991/0607    
		break; 
	default: 
1992/0520    
		p = 0; 
1991/0607    
		break; 
1993/0806    
	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); 
1991/0607    
	} 
 
1992/0520    
	if(p && p->nostream) 
1992/0114    
		error(Einuse); 
1991/0607    
                 
	if((c->qid.path & CHDIR) == 0) 
		streamopen(c, &duartinfo); 
	return devopen(c, omode, duartdir, 2*nduartport, devgen); 
1993/0806    
	c->mode = omode&~OTRUNC; 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
1991/0607    
} 
 
void 
duartcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1214    
	USED(c); 
1992/0711    
	USED(name); 
	USED(omode); 
	USED(perm); 
1993/0806    
	USED(c, name, omode, perm); 
1991/1120    
	error(Eperm); 
1991/0607    
} 
 
1993/0501/sys/src/9/power/devduart.c:791,8321993/0806/sys/src/9/power/devduart.c:582,687
1991/0607    
void 
duartclose(Chan *c) 
{ 
	if(c->stream) 
		streamclose(c); 
1993/0806    
	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); 
1991/0607    
} 
 
long 
duartread(Chan *c, void *buf, long n, ulong offset) 
{ 
1992/0520    
	Port *p; 
1993/0806    
	Uart *p; 
1991/0607    
 
	if(c->qid.path&CHDIR) 
		return devdirread(c, buf, n, duartdir, 2*nduartport, devgen); 
1993/0806    
	if(c->qid.path & CHDIR) 
		return devdirread(c, buf, n, duartdir, 2*nuart, devgen); 
1991/0607    
 
	switch(STREAMTYPE(c->qid.path)){ 
	case Sdataqid: 
		return streamread(c, buf, n); 
	case Sctlqid: 
		if(offset) 
			return 0; 
1992/0520    
		p = &duartport[STREAMID(c->qid.path)]; 
		qlock(p); 
		p->op = Dstate; 
		sleep(&p->opr, opdone, p); 
		*(uchar *)buf = p->val; 
		qunlock(p); 
1991/0607    
		return 1; 
1993/0806    
	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); 
1991/0607    
	} 
 
1992/0114    
	error(Egreg); 
1992/0519    
	return 0;	/* not reached */ 
1993/0806    
	return 0; 
1991/0607    
} 
 
1993/0806    
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; 
	} 
} 
 
1991/0607    
long 
duartwrite(Chan *c, void *va, long n, ulong offset) 
{ 
1993/0806    
	Uart *p; 
	char cmd[32]; 
 
1992/0711    
	USED(offset); 
1991/0607    
	return streamwrite(c, va, n, 0); 
1993/0806    
 
	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; 
	} 
1991/0607    
} 
 
void 
1993/0501/sys/src/9/power/devduart.c:839,8561993/0806/sys/src/9/power/devduart.c:694,699
1991/0607    
void 
1992/0520    
duartwstat(Chan *c, char *p) 
1991/0607    
{ 
1991/1214    
	USED(c); 
1992/0711    
	USED(p); 
1993/0806    
	USED(c, p); 
1992/0114    
	error(Eperm); 
1991/0607    
} 
                 
int 
duartactive(void) 
{ 
	int i; 
                 
	for(i = 0; i < nduartport; i++) 
		if(duartport[i].printing) 
			return 1; 
1991/1214    
	return 0; 
} 
1993/0806/sys/src/9/power/devduart.c:306,3121993/0807/sys/src/9/power/devduart.c:306,311 (short | long)
1991/0607    
	case Dprint: 
1993/0806    
		p->reg->cmnd = ENBTX; 
1992/0520    
		p->reg->data = p->val; 
1993/0806    
iprint("slave %c\n", p->val); 
1991/0607    
		break; 
	case Dena: 
1992/0520    
		duartenable(p); 
1993/0806/sys/src/9/power/devduart.c:380,3861993/0807/sys/src/9/power/devduart.c:379,385
1993/0806    
void 
duartxintr(Uart *p) 
{ 
1992/0325    
	int ch; 
1993/0807    
	char ch; 
1993/0806    
	Duartreg *reg; 
1991/0607    
 
1992/0520    
	reg = p->reg; 
1993/0806/sys/src/9/power/devduart.c:462,4701993/0807/sys/src/9/power/devduart.c:461,469
1993/0806    
		duartbaud(p, s); 
1991/0607    
 
1993/0806    
	p->putc = putc; 
	if(in) 
1993/0807    
	if(in != 0) 
1993/0806    
		*in = p->iq; 
	if(out) 
1993/0807    
	if(out != 0) 
1993/0806    
		*out = p->oq; 
1991/0727    
 
1993/0806    
	p->opens++; 
1993/0807/sys/src/9/power/devduart.c:672,6781994/0902/sys/src/9/power/devduart.c:672,678 (short | long)
1993/0806    
	p = &uart[NETID(c->qid.path)]; 
	switch(NETTYPE(c->qid.path)){ 
	case Ndataqid: 
		return qwrite(p->oq, va, n, 0); 
1994/0902    
		return qwrite(p->oq, va, n); 
1993/0806    
	case Nctlqid: 
		if(n >= sizeof(cmd)) 
			n = sizeof(cmd)-1; 
1994/0902/sys/src/9/power/devduart.c:615,6201995/0108/sys/src/9/power/devduart.c:615,626 (short | long)
1993/0806    
	return 0; 
1991/0607    
} 
 
1995/0108    
Block* 
duartbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
1993/0806    
static void 
duartctl(Uart *p, char *cmd) 
{ 
1994/0902/sys/src/9/power/devduart.c:681,6861995/0108/sys/src/9/power/devduart.c:687,698
1993/0806    
		duartctl(p, cmd); 
		return n; 
	} 
1995/0108    
} 
 
long 
duartbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1991/0607    
} 
 
void 
1995/0108/sys/src/9/power/devduart.c:630,6351995/0205/sys/src/9/power/devduart.c:630,638 (short | long)
1993/0806    
	for(i = 0; i < 16 && qlen(p->oq); i++) 
		tsleep(&p->r, qlen, p->oq, 125); 
 
1995/0205    
	if(strncmp(cmd, "break", 5) == 0) 
		cmed += 4; 
 
1993/0806    
	n = atoi(cmd+1); 
	switch(cmd[0]){ 
	case 'B': 
1995/0205/sys/src/9/power/devduart.c:442,4491996/0214/sys/src/9/power/devduart.c:442,453 (short | long)
1991/0607    
{ 
1993/0806    
	int n, i; 
1993/0501    
	char buf[512]; 
1996/0214    
	va_list arg; 
1991/0607    
 
1993/0806    
	n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; 
1996/0214    
	va_start(arg, fmt); 
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; 
	va_end(arg); 
 
1993/0806    
	for(i = 0; i < n; i++) 
		duartrawputc(buf[i]); 
	return n; 
1995/0205/sys/src/9/power/devduart.c:630,6421996/0214/sys/src/9/power/devduart.c:634,645
1993/0806    
	for(i = 0; i < 16 && qlen(p->oq); i++) 
		tsleep(&p->r, qlen, p->oq, 125); 
 
1995/0205    
	if(strncmp(cmd, "break", 5) == 0) 
		cmed += 4; 
                 
1993/0806    
	n = atoi(cmd+1); 
	switch(cmd[0]){ 
	case 'B': 
	case 'b': 
1996/0214    
		if(strncmp(cmd+1, "reak", 4) == 0) 
			break; 
1993/0806    
		p->val = n; 
		p->op = Dbaud; 
		sleep(&p->opr, opdone, p); 
1996/0214/sys/src/9/power/devduart.c:6,121996/0223/sys/src/9/power/devduart.c:6,11 (short | long)
1991/0607    
#include	"io.h" 
1992/0111    
#include	"../port/error.h" 
1991/0607    
 
1993/0806    
#include	"devtab.h" 
#include	"../port/netif.h" 
1991/0607    
 
/* 
1996/0223/sys/src/9/power/devduart.c:1,7151997/0327/sys/src/9/power/devduart.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:32:51 2005
1991/0607    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0607    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
1992/0111    
#include	"../port/error.h" 
1991/0607    
                 
1993/0806    
#include	"../port/netif.h" 
1991/0607    
                 
/* 
1993/0806    
 * Register set for half the duart.  
 * There are really two sets in adjacent memory locations. 
1991/0607    
 */ 
1992/0520    
struct Duartreg 
{ 
1993/0806    
	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]; 
1991/0607    
}; 
1993/0806    
#define	ppcr	isimr		/* in the second register set */ 
1991/0607    
                 
1993/0806    
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, 
1991/0607    
                 
1993/0806    
	Maxduart	= 8, 
1991/0607    
}; 
                 
/* 
 *  requests to perform on a duart 
 */ 
1993/0806    
enum 
{ 
1991/0607    
	Dnone=	0, 
	Dbaud, 
	Dbreak, 
	Ddtr, 
	Dprint, 
	Dena, 
	Dstate, 
}; 
                 
/* 
1992/0520    
 *  a duart 
1991/0607    
 */ 
1992/0520    
typedef struct Duart	Duart; 
struct Duart 
1991/0607    
{ 
	QLock; 
1992/0520    
	Duartreg	*reg;		/* duart registers */ 
	uchar		imr;		/* sticky interrupt mask reg bits */ 
	uchar		acr;		/* sticky auxiliary reg bits */ 
	int		inited; 
}; 
Duart duart[Maxduart]; 
1991/0607    
                 
1992/0520    
/* 
 *  values specific to a single duart port 
 */ 
1993/0806    
typedef struct Uart	Uart; 
struct Uart 
1992/0520    
{ 
	QLock; 
	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 */ 
                 
1993/0806    
	int		printing;	/* need kick */ 
	int		opens; 
	Rendez		r; 
1991/0607    
                 
1993/0806    
	/* buffers */ 
	int	(*putc)(Queue*, int); 
	Queue	*iq; 
	Queue	*oq; 
1991/0607    
}; 
1993/0806    
Uart uart[2*Maxduart]; 
1991/0607    
                 
1993/0806    
void	duartkick(Uart*); 
                 
1991/0607    
/* 
 *  configure a duart port, default is 9600 baud, 8 bits/char, 1 stop bit, 
 *  no parity 
 */ 
void 
1993/0806    
duartsetup(Uart *p, Duart *d, int devno) 
1991/0607    
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
                 
1992/0520    
	p->d = d; 
	reg = &d->reg[devno]; 
	p->reg = reg; 
1991/0607    
                 
1993/0806    
	reg->cmnd = RESETRCV|DISTX|DISRX; 
	reg->cmnd = RESETTRANS; 
	reg->cmnd = RESETERR; 
	reg->cmnd = STOPBRK; 
1991/0607    
                 
1993/0806    
	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); 
1991/0607    
} 
                 
/* 
 *  init the duart on the current processor 
 */ 
void 
duartinit(void) 
{ 
1993/0806    
	Uart *p; 
1992/0520    
	Duart *d; 
1991/0607    
                 
1992/0520    
	d = &duart[m->machno]; 
	if(d->inited) 
1991/0607    
		return; 
1993/0806    
                 
1992/0520    
	d->reg = DUARTREG; 
1993/0806    
	d->imr = IMRRDYA|IMXRDYA|IMRRDYB|IMXRDYB; 
	d->reg->isimr = d->imr; 
1992/0520    
	d->acr = 0x80;			/* baud rate set 2 */ 
1993/0806    
	d->reg->ipcacr = d->acr; 
1991/0607    
                 
1993/0806    
	p = &uart[2*m->machno]; 
                 
1992/0520    
	duartsetup(p, d, 0); 
	p++; 
	duartsetup(p, d, 1); 
1992/0608    
	d->inited = 1; 
1991/0607    
} 
                 
/* 
 *  enable a duart port 
 */ 
void 
1993/0806    
duartenable(Uart *p) 
1991/0607    
{ 
1993/0806    
	p->reg->cmnd = ENBTX|ENBRX; 
1991/0607    
} 
                 
void 
duartenable0(void) 
{ 
1993/0806    
	DUARTREG->cmnd = ENBTX|ENBRX; 
1991/0607    
} 
                 
void 
1993/0806    
duartbaud(Uart *p, int b) 
1991/0607    
{ 
1992/0519    
	int x; 
1991/0607    
                 
	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: 
1992/0516    
		return; 
1991/0607    
	} 
	if(x & 0x0100) 
1992/0520    
		p->d->acr |= 0x80; 
1991/0607    
	else 
1992/0520    
		p->d->acr &= ~0x80; 
1993/0806    
	p->d->reg->ipcacr = p->d->acr; 
	p->reg->srcsr = x; 
1991/0607    
} 
                 
void 
1993/0806    
duartdtr(Uart *p, int val) 
1991/0607    
{ 
	if (val) 
1992/0520    
		p->reg->ctlr = 0x01; 
1991/0607    
	else 
1992/0520    
		p->reg->ctur = 0x01; 
1991/0607    
} 
                 
void 
1993/0806    
duartbreak(Uart *p, int val) 
1991/0607    
{ 
1992/0520    
	Duartreg *reg; 
1991/0607    
                 
1992/0520    
	reg = p->reg; 
1991/0607    
	if (val){ 
1993/0806    
		p->d->imr &= ~IMXRDYB; 
		p->d->reg->isimr = p->d->imr; 
		reg->cmnd = STRTBRK|ENBTX; 
1991/0607    
	} else { 
1993/0806    
		reg->cmnd = STOPBRK|ENBTX; 
		p->d->imr |= IMXRDYB; 
		p->d->reg->isimr = p->d->imr; 
1991/0607    
	} 
} 
                 
/* 
 *  do anything requested for this CPU's duarts 
 */ 
void 
1993/0806    
duartslave0(Uart *p) 
1991/0607    
{ 
1992/0520    
	switch(p->op){ 
1991/0607    
	case Ddtr: 
1992/0520    
		duartdtr(p, p->val); 
1991/0607    
		break; 
	case Dbaud: 
1992/0520    
		duartbaud(p, p->val); 
1991/0607    
		break; 
	case Dbreak: 
1992/0520    
		duartbreak(p, p->val); 
1991/0607    
		break; 
	case Dprint: 
1993/0806    
		p->reg->cmnd = ENBTX; 
1992/0520    
		p->reg->data = p->val; 
1991/0607    
		break; 
	case Dena: 
1992/0520    
		duartenable(p); 
1991/0607    
		break; 
	case Dstate: 
1992/0520    
		p->val = p->reg->ppcr; 
1991/0607    
		break; 
	} 
1992/0520    
	p->op = Dnone; 
	wakeup(&p->opr); 
1991/0607    
} 
void 
duartslave(void) 
{ 
1993/0806    
	Uart *p; 
1991/0607    
                 
1993/0806    
	p = &uart[2*m->machno]; 
1992/0520    
	if(p->op != Dnone) 
		duartslave0(p); 
	p++; 
	if(p->op != Dnone) 
		duartslave0(p); 
1991/0607    
} 
                 
1992/0519    
void 
1993/0806    
duartrintr(Uart *p) 
1991/0607    
{ 
	char ch; 
1993/0806    
	int status; 
	Duartreg *reg; 
1991/0607    
                 
1992/0520    
	reg = p->reg; 
1993/0806    
	status = reg->srcsr; 
1992/0520    
	ch = reg->data; 
1993/0806    
	if(status & (FRMERR|OVRERR|PARERR)) 
		reg->cmnd = RESETERR; 
1991/0607    
                 
1993/0806    
	if(p->putc) 
		(*p->putc)(p->iq, ch); 
1992/0519    
	else 
1993/0806    
		qproduce(p->iq, &ch, 1); 
1991/0607    
} 
                 
1993/0806    
/* 
 *  (re)start output 
 */ 
1992/0519    
void 
1993/0806    
duartkick(Uart *p) 
1991/0607    
{ 
1993/0806    
	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) 
{ 
1993/0807    
	char ch; 
1993/0806    
	Duartreg *reg; 
1991/0607    
                 
1992/0520    
	reg = p->reg; 
1993/0806    
	if(qconsume(p->oq, &ch, 1) <= 0) { 
1992/0520    
		p->printing = 0; 
1993/0806    
		reg->cmnd = DISTX; 
	} 
	else 
1992/0520    
		reg->data = ch; 
1991/0607    
} 
                 
void 
duartintr(void) 
{ 
1992/0711    
	int cause; 
1992/0520    
	Duartreg *reg; 
1993/0806    
	Uart *p; 
1991/0607    
                 
1993/0806    
	p = &uart[2*m->machno]; 
1992/0520    
	reg = p->reg; 
1993/0806    
	cause = reg->isimr; 
1992/0520    
                 
1993/0806    
	if(cause & IMRRDYA) 
1992/0520    
		duartrintr(p); 
1993/0806    
                 
	if(cause & IMXRDYA) 
1992/0520    
		duartxintr(p); 
1993/0806    
                 
	if(cause & IMRRDYB) 
1992/0520    
		duartrintr(p+1); 
1993/0806    
                 
	if(cause & IMXRDYB) 
1992/0520    
		duartxintr(p+1); 
1991/0607    
} 
                 
/* 
 *  processor 0 only 
 */ 
int 
duartrawputc(int c) 
{ 
	int i; 
1993/0806    
	Duartreg *reg; 
1991/0607    
                 
1992/0520    
	reg = DUARTREG; 
1993/0806    
	if(c == '\n') { 
1991/0607    
		duartrawputc('\r'); 
1993/0806    
		delay(100); 
	} 
	reg->cmnd = ENBTX; 
1991/0607    
	i = 0; 
1993/0806    
	while((reg->srcsr&XMTRDY) == 0 && i++ < 100000) 
		; 
1992/0520    
	reg->data = c; 
1991/0607    
	return c; 
} 
1993/0501    
                 
1993/0806    
int 
1991/0607    
iprint(char *fmt, ...) 
{ 
1993/0806    
	int n, i; 
1993/0501    
	char buf[512]; 
1996/0214    
	va_list arg; 
1991/0607    
                 
1996/0214    
	va_start(arg, fmt); 
	n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf; 
	va_end(arg); 
                 
1993/0806    
	for(i = 0; i < n; i++) 
		duartrawputc(buf[i]); 
	return n; 
1991/0607    
} 
                 
void 
1993/0806    
duartspecial(int port, int s, Queue **in, Queue **out, int (*putc)(Queue*, int)) 
1991/0607    
{ 
1993/0806    
	Uart *p; 
1991/0607    
                 
1993/0806    
	p = &uart[port]; 
1991/0607    
                 
1993/0806    
	duartenable(p); 
	if(s) 
		duartbaud(p, s); 
1991/0607    
                 
1993/0806    
	p->putc = putc; 
1993/0807    
	if(in != 0) 
1993/0806    
		*in = p->iq; 
1993/0807    
	if(out != 0) 
1993/0806    
		*out = p->oq; 
1991/0727    
                 
1993/0806    
	p->opens++; 
1991/0607    
} 
                 
static int 
1992/0519    
opdone(void *x) 
1991/0607    
{ 
1993/0806    
	Uart *p = x; 
1991/0607    
                 
1992/0520    
	return p->op == Dnone; 
1991/0607    
} 
                 
Dirtab *duartdir; 
1993/0806    
int nuart; 
1991/0607    
                 
void 
duartreset(void) 
{ 
	int i; 
1993/0806    
	Dirtab *dp; 
1991/0607    
                 
1993/0806    
	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++; 
1991/0607    
                 
1993/0806    
		print(dp->name, "eia%dctl", i); 
		dp->qid.path = NETQID(i, Nctlqid); 
		dp->perm = 0666; 
		dp++; 
1991/0607    
	} 
} 
                 
Chan* 
duartattach(char *spec) 
{ 
	return devattach('t', spec); 
} 
                 
Chan* 
duartclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
                 
int 
duartwalk(Chan *c, char *name) 
{ 
1993/0806    
	return devwalk(c, name, duartdir, 2*nuart, devgen); 
1991/0607    
} 
                 
void 
1993/0806    
duartstat(Chan *c, char *dp) 
1991/0607    
{ 
1993/0806    
	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); 
1991/0607    
		break; 
	default: 
1993/0806    
		devstat(c, dp, duartdir, 2*nuart, devgen); 
1991/0607    
		break; 
	} 
} 
                 
Chan* 
duartopen(Chan *c, int omode) 
{ 
1993/0806    
	Uart *p; 
1991/0607    
                 
1993/0806    
	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); 
1991/0607    
	} 
                 
1993/0806    
	c->mode = omode&~OTRUNC; 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
1991/0607    
} 
                 
void 
duartcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1993/0806    
	USED(c, name, omode, perm); 
1991/1120    
	error(Eperm); 
1991/0607    
} 
                 
void 
duartclose(Chan *c) 
{ 
1993/0806    
	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); 
1991/0607    
} 
                 
long 
duartread(Chan *c, void *buf, long n, ulong offset) 
{ 
1993/0806    
	Uart *p; 
1991/0607    
                 
1993/0806    
	if(c->qid.path & CHDIR) 
		return devdirread(c, buf, n, duartdir, 2*nuart, devgen); 
1991/0607    
                 
1993/0806    
	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); 
1991/0607    
	} 
                 
1993/0806    
	return 0; 
1991/0607    
} 
                 
1995/0108    
Block* 
duartbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
                 
1993/0806    
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': 
1996/0214    
		if(strncmp(cmd+1, "reak", 4) == 0) 
			break; 
1993/0806    
		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; 
	} 
} 
                 
1991/0607    
long 
duartwrite(Chan *c, void *va, long n, ulong offset) 
{ 
1993/0806    
	Uart *p; 
	char cmd[32]; 
                 
1992/0711    
	USED(offset); 
1993/0806    
                 
	if(c->qid.path & CHDIR) 
		error(Eperm); 
                 
	p = &uart[NETID(c->qid.path)]; 
	switch(NETTYPE(c->qid.path)){ 
	case Ndataqid: 
1994/0902    
		return qwrite(p->oq, va, n); 
1993/0806    
	case Nctlqid: 
		if(n >= sizeof(cmd)) 
			n = sizeof(cmd)-1; 
		memmove(cmd, va, n); 
		cmd[n] = 0; 
		duartctl(p, cmd); 
		return n; 
	} 
1995/0108    
} 
                 
long 
duartbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1991/0607    
} 
                 
void 
duartremove(Chan *c) 
{ 
1991/1214    
	USED(c); 
1992/0114    
	error(Eperm); 
1991/0607    
} 
                 
void 
1992/0520    
duartwstat(Chan *c, char *p) 
1991/0607    
{ 
1993/0806    
	USED(c, p); 
1992/0114    
	error(Eperm); 
1991/1214    
} 


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