## 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
|