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