## diffname port/devns16552.c 1994/0902 ## diff -e /dev/null /n/fornaxdump/1994/0902/sys/src/brazil/port/devns16552.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "devtab.h" #include "../port/netif.h" /* * Driver for the ns16552. */ enum { /* * register numbers */ Data= 0, /* xmit/rcv buffer */ Iena= 1, /* interrupt enable */ Ircv= (1<<0), /* for char rcv'd */ Ixmt= (1<<1), /* for xmit buffer empty */ Irstat=(1<<2), /* for change in rcv'er status */ Imstat=(1<<3), /* for change in modem status */ Istat= 2, /* interrupt flag (read) */ Fenabd=(3<<6), /* on if fifo's enabled */ Fifoctl=2, /* fifo control (write) */ Fena= (1<<0), /* enable xmit/rcv fifos */ Ftrig= (1<<6), /* trigger after 4 input characters */ Fclear=(3<<1), /* clear xmit & rcv fifos */ Format= 3, /* byte format */ Bits8= (3<<0), /* 8 bits/byte */ Stop2= (1<<2), /* 2 stop bits */ Pena= (1<<3), /* generate parity */ Peven= (1<<4), /* even parity */ Pforce=(1<<5), /* force parity */ Break= (1<<6), /* generate a break */ Dra= (1<<7), /* address the divisor */ Mctl= 4, /* modem control */ Dtr= (1<<0), /* data terminal ready */ Rts= (1<<1), /* request to send */ Ri= (1<<2), /* ring */ Inton= (1<<3), /* turn on interrupts */ Loop= (1<<4), /* loop back */ Lstat= 5, /* line status */ Inready=(1<<0), /* receive buffer full */ Oerror=(1<<1), /* receiver overrun */ Perror=(1<<2), /* receiver parity error */ Ferror=(1<<3), /* rcv framing error */ Outready=(1<<5), /* output buffer full */ Mstat= 6, /* modem status */ Ctsc= (1<<0), /* clear to send changed */ Dsrc= (1<<1), /* data set ready changed */ Rire= (1<<2), /* rising edge of ring indicator */ Dcdc= (1<<3), /* data carrier detect changed */ Cts= (1<<4), /* complement of clear to send line */ Dsr= (1<<5), /* complement of data set ready line */ Ring= (1<<6), /* complement of ring indicator line */ Dcd= (1<<7), /* complement of data carrier detect line */ Scratch=7, /* scratchpad */ Dlsb= 0, /* divisor lsb */ Dmsb= 1, /* divisor msb */ CTLS= 023, CTLQ= 021, Stagesize= 1024, Nuart= 32, /* max per machine */ }; typedef struct Uart Uart; struct Uart { QLock; Uart *elist; /* next enabled interface */ uchar sticky[8]; /* sticky write register values */ ulong port; Lock plock; /* for printing variable */ int printing; /* true if printing */ ulong freq; /* clock frequency */ int opens; uchar mask; /* bits/char */ uchar istat; /* last istat read */ uchar fifoon; /* fifo's enabled */ uchar nofifo; /* earlier chip version with nofifo */ int enabled; int dev; int frame; int overrun; /* flow control */ int xonoff; /* software flow control on */ int blocked; int modem; /* hardware flow control on */ int cts; int ctsbackoff; Rendez r; /* buffers */ int (*putc)(Queue*, int); Queue *iq; Queue *oq; /* staging areas to avoid some of the per character costs */ uchar istage[Stagesize]; uchar *ip; uchar *ie; uchar ostage[Stagesize]; uchar *op; uchar *oe; }; static Uart *uart[Nuart]; static int nuart; static int haveinput; struct Uartalloc { Lock; Uart *elist; /* list of enabled interfaces */ } uartalloc; void ns16552intr(int); /* * pick up architecture specific routines and definitions */ #include "ns16552.h" /* * set the baud rate by calculating and setting the baudrate * generator constant. This will work with fairly non-standard * baud rates. */ static void ns16552setbaud(Uart *p, int rate) { ulong brconst; brconst = (p->freq+8*rate-1)/(16*rate); uartwrreg(p, Format, Dra); outb(p->port + Dmsb, (brconst>>8) & 0xff); outb(p->port + Dlsb, brconst & 0xff); uartwrreg(p, Format, 0); } static void ns16552parity(Uart *p, char type) { switch(type){ case 'e': p->sticky[Format] |= Pena|Peven; break; case 'o': p->sticky[Format] &= ~Peven; p->sticky[Format] |= Pena; break; default: p->sticky[Format] &= ~(Pena|Peven); break; } uartwrreg(p, Format, 0); } /* * set bits/character, default 8 */ void ns16552bits(Uart *p, int bits) { if(bits < 5 || bits > 8) error(Ebadarg); p->sticky[Format] &= ~3; p->sticky[Format] |= bits-5; uartwrreg(p, Format, 0); } /* * toggle DTR */ void ns16552dtr(Uart *p, int n) { if(n) p->sticky[Mctl] |= Dtr; else p->sticky[Mctl] &= ~Dtr; uartwrreg(p, Mctl, 0); } /* * toggle RTS */ void ns16552rts(Uart *p, int n) { if(n) p->sticky[Mctl] |= Rts; else p->sticky[Mctl] &= ~Rts; uartwrreg(p, Mctl, 0); } /* * send break */ void ns16552break(Uart *p, int ms) { if(ms == 0) ms = 200; uartwrreg(p, Format, Break); tsleep(&up->sleep, return0, 0, ms); uartwrreg(p, Format, 0); } void ns16552fifoon(Uart *p) { ulong i, x, c; if(p->nofifo) return; x = splhi(); /* empty buffer */ c = 0; /* c is to to avoid an unused warning */ for(i = 0; i < 16; i++) c = uartrdreg(p, Data); USED(c); ns16552intr(p->dev); /* turn on fifo */ p->fifoon = 1; uartwrreg(p, Fifoctl, Fena|Ftrig); ns16552intr(p->dev); USED(c); if((p->istat & Fenabd) == 0){ /* didn't work, must be an earlier chip type */ p->nofifo = 1; } splx(x); } /* * modem flow control on/off (rts/cts) */ void ns16552mflow(Uart *p, int n) { if(n){ p->sticky[Iena] |= Imstat; uartwrreg(p, Iena, 0); p->modem = 1; p->cts = uartrdreg(p, Mstat) & Cts; /* turn on fifo's */ ns16552fifoon(p); } else { p->sticky[Iena] &= ~Imstat; uartwrreg(p, Iena, 0); p->modem = 0; p->cts = 1; /* turn off fifo's */ p->fifoon = 0; uartwrreg(p, Fifoctl, 0); } } /* * turn on a port's interrupts. set DTR and RTS */ void ns16552enable(Uart *p) { Uart **l; if(p->enabled) return; uartpower(p->dev, 1); /* * turn on interrupts */ p->sticky[Iena] = Ircv | Ixmt | Irstat; uartwrreg(p, Iena, 0); /* * turn on DTR and RTS */ ns16552dtr(p, 1); ns16552rts(p, 1); /* * assume we can send */ p->cts = 1; p->blocked = 0; lock(&uartalloc); for(l = &uartalloc.elist; *l; l = &(*l)->elist){ if(*l == p) break; } if(*l == 0){ p->elist = uartalloc.elist; uartalloc.elist = p; } p->enabled = 1; unlock(&uartalloc); } /* * turn off a port's interrupts. reset DTR and RTS */ void ns16552disable(Uart *p) { Uart **l; /* * turn off interrpts */ p->sticky[Iena] = 0; uartwrreg(p, Iena, 0); /* * revert to default settings */ p->sticky[Format] = Bits8; uartwrreg(p, Format, 0); /* * turn off DTR, RTS, hardware flow control & fifo's */ ns16552dtr(p, 0); ns16552rts(p, 0); ns16552mflow(p, 0); p->xonoff = p->blocked = 0; uartpower(p->dev, 0); lock(&uartalloc); for(l = &uartalloc.elist; *l; l = &(*l)->elist){ if(*l == p){ *l = p->elist; break; } } p->enabled = 0; unlock(&uartalloc); } /* * put some bytes into the local queue to avoid calling * qconsume for every character */ static int stageoutput(Uart *p) { int n; n = qconsume(p->oq, p->ostage, Stagesize); if(n <= 0) return 0; p->op = p->ostage; p->oe = p->ostage + n; return n; } /* * (re)start output */ static void ns16552kick(Uart *p) { int x, n; x = splhi(); lock(&p->plock); if(p->printing == 0 || (uartrdreg(p, Lstat) & Outready)) if(p->cts && p->blocked == 0){ n = 0; while((uartrdreg(p, Lstat) & Outready) == 0){ if(++n > 10000){ print("stuck serial line\n"); break; } } do{ if(p->op >= p->oe && stageoutput(p) == 0) break; outb(p->port + Data, *(p->op++)); }while(uartrdreg(p, Lstat) & Outready); } unlock(&p->plock); splx(x); } /* * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts, * transmit and receive enabled, interrupts disabled. */ static void ns16552setup0(Uart *p) { memset(p->sticky, 0, sizeof(p->sticky)); /* * set rate to 9600 baud. * 8 bits/character. * 1 stop bit. * interrpts enabled. */ p->sticky[Format] = Bits8; uartwrreg(p, Format, 0); p->sticky[Mctl] |= Inton; uartwrreg(p, Mctl, 0x0); ns16552setbaud(p, 9600); p->iq = qopen(4*1024, 0, 0, 0); p->oq = qopen(4*1024, 0, ns16552kick, p); p->ip = p->istage; p->ie = &p->istage[Stagesize]; p->op = p->ostage; p->oe = p->ostage; } /* * called by main() to create a new duart */ void ns16552setup(ulong port, ulong freq) { Uart *p; if(nuart >= Nuart) return; p = xalloc(sizeof(Uart)); uart[nuart] = p; p->dev = nuart; nuart++; p->port = port; p->freq = freq; ns16552setup0(p); } /* * called by main() to configure a duart port as a console or a mouse */ void ns16552special(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int)) { Uart *p = uart[port]; ns16552enable(p); if(baud) ns16552setbaud(p, baud); p->putc = putc; if(in) *in = p->iq; if(out) *out = p->oq; p->opens++; } /* * handle an interrupt to a single uart */ void ns16552intr(int dev) { uchar ch; int s, l, loops; Uart *p = uart[dev]; for(loops = 0;; loops++){ if(loops > 100000) panic("ns16552intr"); p->istat = s = uartrdreg(p, Istat); switch(s&0x3f){ case 6: /* receiver line status */ l = uartrdreg(p, Lstat); if(l & Ferror) p->frame++; if(l & Oerror) p->overrun++; break; case 4: /* received data available */ case 12: ch = uartrdreg(p, Data) & 0xff; if(p->xonoff){ if(ch == CTLS){ p->blocked = 1; }else if (ch == CTLQ){ p->blocked = 0; /* clock gets output going again */ } } if(p->putc) (*p->putc)(p->iq, ch); else { if(p->ip < p->ie) *p->ip++ = ch; haveinput = 1; } break; case 2: /* transmitter not full */ lock(&p->plock); l = uartrdreg(p, Lstat) & Outready; if(l && p->cts && p->blocked == 0) if(p->op < p->oe || stageoutput(p)){ do{ outb(p->port + Data, *(p->op++)); if(p->op >= p->oe && stageoutput(p) == 0) break; l = uartrdreg(p, Lstat) & Outready; }while(l); } if(l) p->printing = 0; unlock(&p->plock); break; case 0: /* modem status */ ch = uartrdreg(p, Mstat); if(ch & Ctsc){ p->cts = ch & Cts; /* clock gets output going again */ p->ctsbackoff += 1; } break; default: if(s&1) return; print("weird modem interrupt #%2.2ux\n", s); break; } } } /* * we save up input characters till clock time * * There's also a bit of code to get a stalled print going. * It shouldn't happen, but it does. Obviously I don't * understand interrupts. -- presotto */ void uartclock(void) { int n; Uart *p; for(p = uartalloc.elist; p; p = p->elist){ ns16552intr(p->dev); if(haveinput){ n = p->ip - p->istage; if(n > 0 && p->iq){ if(n > Stagesize) panic("uartclock"); if(qproduce(p->iq, p->istage, n) != n) ; p->ip = p->istage; } } if(p->ctsbackoff-- < 0){ p->ctsbackoff = 0; ns16552kick(p); } } haveinput = 0; } Dirtab *ns16552dir; /* * all uarts must be ns16552setup() by this point or inside of ns16552install() */ void ns16552reset(void) { int i; Dirtab *dp; ns16552install(); /* architecture specific */ ns16552dir = xalloc(3 * nuart * sizeof(Dirtab)); dp = ns16552dir; for(i = 0; i < nuart; i++){ /* 3 directory entries per port */ sprint(dp->name, "eia%d", i); dp->qid.path = NETQID(i, Ndataqid); dp->perm = 0666; dp++; sprint(dp->name, "eia%dctl", i); dp->qid.path = NETQID(i, Nctlqid); dp->perm = 0666; dp++; sprint(dp->name, "eia%dstat", i); dp->qid.path = NETQID(i, Nstatqid); dp->perm = 0444; dp++; } } void ns16552init(void) { } Chan* ns16552attach(char *spec) { return devattach('t', spec); } Chan* ns16552clone(Chan *c, Chan *nc) { return devclone(c, nc); } int ns16552walk(Chan *c, char *name) { return devwalk(c, name, ns16552dir, 3*nuart, devgen); } void ns16552stat(Chan *c, char *dp) { 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, ns16552dir[3*i].name, qlen(p->iq), eve, 0660, &dir); convD2M(&dir, dp); break; default: devstat(c, dp, ns16552dir, 3*nuart, devgen); break; } } Chan* ns16552open(Chan *c, int omode) { Uart *p; if(c->qid.path & CHDIR){ if(omode != OREAD) error(Ebadarg); } else if(NETTYPE(c->qid.path) == Nstatqid){ ; } else { p = uart[NETID(c->qid.path)]; qlock(p); p->opens++; ns16552enable(p); qreopen(p->iq); qreopen(p->oq); qunlock(p); } c->mode = omode&~OTRUNC; c->flag |= COPEN; c->offset = 0; return c; } void ns16552create(Chan *c, char *name, int omode, ulong perm) { USED(c, name, omode, perm); error(Eperm); } void ns16552close(Chan *c) { Uart *p; if(c->qid.path & CHDIR) return; if(NETTYPE(c->qid.path) == Nstatqid) return; p = uart[NETID(c->qid.path)]; if(c->flag & COPEN){ qlock(p); p->opens--; if(p->opens == 0){ ns16552disable(p); qclose(p->iq); qclose(p->oq); p->ip = p->istage; } qunlock(p); } } static long uartstatus(Chan *c, Uart *p, void *buf, long n, long offset) { uchar mstat; uchar tstat; char str[256]; int i; str[0] = 0; tstat = p->sticky[Mctl]; mstat = uartrdreg(p, Mstat); i = sprint(str, "%d printing %d cts %d qlen %d/%d", NETID(c->qid.path), p->printing, p->cts, qlen(p->iq), qlen(p->oq)); sprint(str+i, " lstat %ux mstat %ux istat %ux ier %ux ferr %d oerr %d", uartrdreg(p, Lstat), mstat, uartrdreg(p, Istat), uartrdreg(p, Iena), p->frame, p->overrun); if(mstat & Cts) strcat(str, " cts"); if(mstat & Dsr) strcat(str, " dsr"); if(mstat & Ring) strcat(str, " ring"); if(mstat & Dcd) strcat(str, " dcd"); if(tstat & Dtr) strcat(str, " dtr"); if(tstat & Rts) strcat(str, " rts"); strcat(str, "\n"); return readstr(offset, buf, n, str); } long ns16552read(Chan *c, void *buf, long n, ulong offset) { Uart *p; if(c->qid.path & CHDIR) return devdirread(c, buf, n, ns16552dir, 3*nuart, devgen); 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); case Nstatqid: return uartstatus(c, p, buf, n, offset); } return 0; } static void ns16552ctl(Uart *p, char *cmd) { int i, n; /* let output drain for a while */ for(i = 0; i < 16 && qlen(p->oq); i++) tsleep(&p->r, qlen, p->oq, 125); if(strncmp(cmd, "break", 5) == 0){ ns16552break(p, 0); return; } n = atoi(cmd+1); switch(*cmd){ case 'B': case 'b': ns16552setbaud(p, n); break; case 'D': case 'd': ns16552dtr(p, n); break; case 'H': case 'h': qhangup(p->iq); qhangup(p->oq); break; case 'L': case 'l': ns16552bits(p, n); break; case 'm': case 'M': ns16552mflow(p, n); break; case 'n': case 'N': qnoblock(p->oq, n); break; case 'P': case 'p': ns16552parity(p, *(cmd+1)); break; case 'K': case 'k': ns16552break(p, n); break; case 'R': case 'r': ns16552rts(p, n); break; case 'Q': case 'q': qsetlimit(p->iq, n); qsetlimit(p->oq, n); break; case 'W': case 'w': /* obsolete */ break; case 'X': case 'x': p->xonoff = n; break; } } long ns16552write(Chan *c, void *buf, long n, ulong offset) { Uart *p; char cmd[32]; USED(offset); if(c->qid.path & CHDIR) error(Eperm); p = uart[NETID(c->qid.path)]; /* * The fifo's turn themselves off sometimes. * It must be something I don't understand. -- presotto */ if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0) ns16552fifoon(p); switch(NETTYPE(c->qid.path)){ case Ndataqid: return qwrite(p->oq, buf, n); case Nctlqid: if(n >= sizeof(cmd)) n = sizeof(cmd)-1; memmove(cmd, buf, n); cmd[n] = 0; ns16552ctl(p, cmd); return n; } } void ns16552remove(Chan *c) { USED(c); error(Eperm); } void ns16552wstat(Chan *c, char *dp) { USED(c, dp); error(Eperm); } . ## diffname port/devns16552.c 1994/0908 ## diff -e /n/fornaxdump/1994/0902/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/0908/sys/src/brazil/port/devns16552.c 498a if(loops > 50000){ if(shakes++ < 3){ /* try resetting the interface */ ns16552shake(p); continue; } print("lstat %ux mstat %ux istat %ux iena %ux ferr %d oerr %d", uartrdreg(p, Lstat), uartrdreg(p, Mstat), s, uartrdreg(p, Iena), p->frame, p->overrun); panic("ns16552intr"); } . 496,497d 494a shakes = 0; . 492c int s, l, loops, shakes; . 485a * reset the interface */ void ns16552shake(Uart *p) { int xonoff, modem; xonoff = p->xonoff; modem = p->modem; ns16552disable(p); ns16552enable(p); p->xonoff = xonoff; ns16552mflow(p, modem); } /* . 249,250d 244a /* empty buffer and interrupt conditions */ for(i = 0; i < 16; i++){ if(uartrdreg(p, Istat)) ; if(uartrdreg(p, Data)) ; } . 238,243c /* reset fifos */ uartwrreg(p, Fifoctl, Fclear); . 231c ulong i, x; . ## diffname port/devns16552.c 1994/0927 ## diff -e /n/fornaxdump/1994/0908/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/0927/sys/src/brazil/port/devns16552.c 832a case 'f': case 'F': qflush(p->oq); break; . ## diffname port/devns16552.c 1994/0929 ## diff -e /n/fornaxdump/1994/0927/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/0929/sys/src/brazil/port/devns16552.c 752a qunlock(p); . 742,751c qlock(p); p->opens--; if(p->opens == 0){ ns16552disable(p); qclose(p->iq); qclose(p->oq); p->ip = p->istage; . 739a if((c->flag & COPEN) == 0) return; . 610,611c qproduce(p->iq, p->istage, n); . 595c * understand something. Since it was there, I bundled a * restart after flow control with it to give some histeresis * to the hardware flow control. This makes compressing * modems happier but will probably bother something else. * -- presotto . 516c if(loops > 100000){ . ## diffname port/devns16552.c 1994/1017 ## diff -e /n/fornaxdump/1994/0929/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1017/sys/src/brazil/port/devns16552.c 928,929c Dir d; Dirtab *dt; if(!iseve()) error(Eperm); if(CHDIR & c->qid.path) error(Eperm); if(NETTYPE(c->qid.path) == Nstatqid) error(Eperm); dt = &ns16552dir[3 * NETID(c->qid.path)]; convM2D(dp, &d); d.mode &= 0x666; dt[0].perm = dt[1].perm = d.mode; . 795,796c if(c->qid.path & CHDIR){ setlength(-1); return devdirread(c, buf, n, ns16552dir, ndir, devgen); } . 721,723d 706,711c c = devopen(c, omode, ns16552dir, ndir, devgen); switch(NETTYPE(c->qid.path)){ case Nctlqid: case Ndataqid: . 684,698c if(NETTYPE(c->qid.path) == Ndataqid) setlength(NETID(c->qid.path)); devstat(c, dp, ns16552dir, ndir, devgen); . 678c return devwalk(c, name, ns16552dir, ndir, devgen); . 649c dp->perm = 0660; . 645c dp->perm = 0660; . 639c ndir = 3*nuart; ns16552dir = xalloc(ndir * sizeof(Dirtab)); . 627a static void setlength(int i) { Uart *p; if(i > 0){ p = uart[i]; if(p && p->opens && p->iq) ns16552dir[3*i].length = qlen(p->iq); } else for(i = 0; i < nuart; i++){ p = uart[i]; if(p && p->opens && p->iq) ns16552dir[3*i].length = qlen(p->iq); } } . 626a int ndir; . ## diffname port/devns16552.c 1994/1018 ## diff -e /n/fornaxdump/1994/1017/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1018/sys/src/brazil/port/devns16552.c 945c d.mode &= 0666; . ## diffname port/devns16552.c 1994/1025 ## diff -e /n/fornaxdump/1994/1018/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1025/sys/src/brazil/port/devns16552.c 403c if(++n > 100000){ . ## diffname port/devns16552.c 1994/1108 ## diff -e /n/fornaxdump/1994/1025/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1108/sys/src/brazil/port/devns16552.c 670c sprint(dp->name, "%sstat", uart[i]->name); . 666c sprint(dp->name, "%sctl", uart[i]->name); . 662c strcpy(dp->name, uart[i]->name); . 460a strcpy(p->name, name); . 452c ns16552setup(ulong port, ulong freq, char *name) . 77a char name[NAMELEN]; . ## diffname port/devns16552.c 1994/1117 ## diff -e /n/fornaxdump/1994/1108/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1117/sys/src/brazil/port/devns16552.c 616,617c if(qproduce(p->iq, p->istage, n) < 0) ns16552rts(p, 0); else p->ip = p->istage; . 440c p->iq = qopen(4*1024, 0, ns16552flow, p); . 419a * restart input if its off */ static void ns16552flow(Uart *p) { if(p->modem){ ns16552rts(p, 1); haveinput = 1; } } /* . 311a ns16552setbaud(p, 9600); . 212a p->rts = n; unlock(&p->plock); splx(x); . 206a int x; x = splhi(); lock(&p->plock); . 101a int rts; /* ... rts state */ . 100c int cts; /* ... cts state */ . ## diffname port/devns16552.c 1994/1118 ## diff -e /n/fornaxdump/1994/1117/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1118/sys/src/brazil/port/devns16552.c 785d 775,783c switch(NETTYPE(c->qid.path)){ case Ndataqid: case Nctlqid: p = uart[NETID(c->qid.path)]; qlock(p); if(--(p->opens) == 0){ ns16552disable(p); qclose(p->iq); qclose(p->oq); p->ip = p->istage; } qunlock(p); break; . 771,772d 751a break; . 747,750c if(p->opens++ == 0){ ns16552enable(p); qreopen(p->iq); qreopen(p->oq); } . 541,546c if(loops > 10000000){ . 538d 535c int s, l, loops; . 322d ## diffname port/devns16552.c 1994/1121 ## diff -e /n/fornaxdump/1994/1118/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1121/sys/src/brazil/port/devns16552.c 795,799c sprint(str, "ferr %d oerr %d baud %d", p->frame, p->overrun, p->baud); . 791a USED(c); . 790d 151a p->baud = rate; . 93,94c int frame; /* framing errors */ int overrun; /* rcvr overruns */ int baud; /* baud rate */ . ## diffname port/devns16552.c 1994/1122 ## diff -e /n/fornaxdump/1994/1121/sys/src/brazil/port/devns16552.c /n/fornaxdump/1994/1122/sys/src/brazil/port/devns16552.c 799c sprint(str, "opens %d ferr %d oerr %d baud %d", p->opens, p->frame, p->overrun, p->baud); . ## diffname port/devns16552.c 1995/0108 ## diff -e /n/fornaxdump/1994/1122/sys/src/brazil/port/devns16552.c /n/fornaxdump/1995/0108/sys/src/brazil/port/devns16552.c 944a } long ns16552bwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); . 839a Block* ns16552bread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } . ## diffname port/devns16552.c 1995/0205 ## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/port/devns16552.c /n/fornaxdump/1995/0205/sys/src/brazil/port/devns16552.c 146a if(rate <= 0) return; . ## diffname port/devns16552.c 1995/0329 ## diff -e /n/fornaxdump/1995/0205/sys/src/brazil/port/devns16552.c /n/fornaxdump/1995/0329/sys/src/brazil/port/devns16552.c 815a { int i, j; i = strlen(str); for(j = 0; j < 8; j++) i+=sprint(str+i, " %ux", uartrdreg(p, j)); } . 428d 425a outb(p->port + Data, *(p->op++)); . 417c if(p->cts && p->blocked == 0) if(p->op < p->oe || stageoutput(p)){ . ## diffname port/devns16552.c 1995/0330 ## diff -e /n/fornaxdump/1995/0329/sys/src/brazil/port/devns16552.c /n/fornaxdump/1995/0330/sys/src/brazil/port/devns16552.c 334a /* * set baud rate to the last used */ ns16552setbaud(p, p->baud); . ## diffname port/devns16552.c 1995/0804 ## diff -e /n/fornaxdump/1995/0330/sys/src/brazil/port/devns16552.c /n/fornaxdump/1995/0804/sys/src/brazil/port/devns16552.c 977d 975c ns16552remove(Chan*) . 941,942d 936c ns16552write(Chan *c, void *buf, long n, ulong) . 803,804d 797c uartstatus(Chan*, Uart *p, void *buf, long n, long offset) . 767d 765c ns16552create(Chan*, char*, int, ulong) . ## diffname port/devns16552.c 1996/0111 ## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/devns16552.c /n/fornaxdump/1996/0111/sys/src/brazil/port/devns16552.c 465c * interrupts enabled. . 362c * turn off interrupts . ## diffname port/devns16552.c 1996/0117 ## diff -e /n/fornaxdump/1996/0111/sys/src/brazil/port/devns16552.c /n/fornaxdump/1996/0117/sys/src/brazil/port/devns16552.c 442c * restart input if it's off . ## diffname port/devns16552.c 1996/01171 ## diff -e /n/fornaxdump/1996/0117/sys/src/brazil/port/devns16552.c /n/fornaxdump/1996/01171/sys/src/brazil/port/devns16552.c 650,652c /* this adds histeresis to hardware flow control */ if(p->ctsbackoff){ if(--(p->ctsbackoff) == 0) ns16552kick(p); . 638c /* this amortizes cost of qproduce to many chars */ . 606,607c l = p->cts; p->cts = ch & Cts; if(l == 0 && p->cts) p->ctsbackoff = 2; /* clock gets output going again */ . 598,599d 421c if((uartrdreg(p, Lstat) & Outready)) . 83d ## diffname port/devns16552.c 1996/0119 ## diff -e /n/fornaxdump/1996/01171/sys/src/brazil/port/devns16552.c /n/fornaxdump/1996/0119/sys/src/brazil/port/devns16552.c 650c /* this adds hysteresis to hardware flow control */ . 625c * restart after flow control with it to give some hysteresis . ## diffname port/devns16552.c 1996/0223 ## diff -e /n/fornaxdump/1996/0119/sys/src/brazil/port/devns16552.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devns16552.c 9d ## diffname port/devns16552.c 1996/0608 ## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devns16552.c /n/fornaxdump/1996/0608/sys/src/brazil/port/devns16552.c 948a unlock(&p->flock); . 946a lock(&p->flock); . 858c void . 795c long . 675d 655d 653a unlock(&p->tlock); . 652c ns16552kick0(p); . 649a lock(&p->tlock); . 647a unlock(&p->rlock); . 646a p->haveinput = 0; . 637c lock(&p->rlock); if(p->haveinput){ . 635a . 605a unlock(&p->tlock); . 601a lock(&p->tlock); . 585,596c ns16552kick(p); . 580c p->haveinput = 1; unlock(&p->rlock); . 577a lock(&p->rlock); . 574a unlock(&p->tlock); . 566a lock(&p->tlock); . 522,537d 447c ilock(&p->rlock); p->haveinput = 1; iunlock(&p->rlock); . 438a static void ns16552kick(Uart *p) { ilock(&p->tlock); ns16552kick0(p); iunlock(&p->tlock); } . 435,436d 415,433c if(p->cts == 0 || p->blocked) return; while(uartrdreg(p, Lstat) & Outready){ if(p->op >= p->oe && stageoutput(p) == 0) break; outb(p->port + Data, *(p->op++)); . 413c ns16552kick0(Uart *p) . 377c ilock(&p->tlock); p->blocked = 0; iunlock(&p->tlock); p->xonoff = 0; . 354c static void . 331a iunlock(&p->tlock); . 329a ilock(&p->tlock); . 305c static void . 299a iunlock(&p->flock); . 295a ilock(&p->flock); if(n) /* turn on fifo's */ ns16552fifoon(p); else { . 294a iunlock(&p->tlock); } iunlock(&p->tlock); . 287,289d 281a ilock(&p->tlock); . 279c static void . 243c static void . 232c static void . 223,226d 212,216d 122d 116a int modem; /* hardware flow control on */ int xonoff; /* software flow control on */ int blocked; int cts; int ctsbackoff; Rendez r; . 113a int haveinput; Lock tlock; /* transmit */ . 109c Lock flock; /* fifo */ uchar fifoon; /* fifo's enabled */ uchar nofifo; /* earlier chip version with nofifo */ Lock rlock; /* receive */ . 95,103d 91,93c uchar istat; /* last istat read */ int frame; /* framing errors */ int overrun; /* rcvr overruns */ . 89a int baud; /* baud rate */ . 81,88c ulong freq; /* clock frequency */ uchar mask; /* bits/char */ . 79c uchar sticky[8]; /* sticky write register values */ . 76c int enabled; Uart *elist; /* next enabled interface */ . 74a int opens; . ## diffname port/devns16552.c 1997/0327 ## diff -e /n/fornaxdump/1996/0608/sys/src/brazil/port/devns16552.c /n/emeliedump/1997/0327/sys/src/brazil/port/devns16552.c 977a Dev ns16552devtab = { ns16552reset, devinit, ns16552attach, devclone, ns16552walk, ns16552stat, ns16552open, devcreate, ns16552close, ns16552read, devbread, ns16552write, devbwrite, devremove, ns16552wstat, }; . 948,960c static void . 915c static long . 910a iunlock(&p->tlock); . 909a ilock(&p->tlock); . 872,873c qhangup(p->iq, 0); qhangup(p->oq, 0); . 835,841c static void . 812c static long . 778c static long . 747,753c static void . 723c static Chan* . 715c static void . 703,709c static int . 692,697c static Chan* . 664c static void . 562c p->putc(p->iq, ch); . 382d 380c p->xonoff = p->blocked = 0; . 286d ## diffname port/devns16552.c 1997/0408 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devns16552.c /n/emeliedump/1997/0408/sys/src/brazil/port/devns16552.c 944a 't', "ns16552", . ## diffname port/devns16552.c 1997/0814 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devns16552.c /n/emeliedump/1997/0814/sys/src/brazil/port/devns16552.c 636d 633,634c lock(&p->tlock); if(p->ctsbackoff){ if(--(p->ctsbackoff) == 0) ns16552kick0(p); } unlock(&p->tlock); . 631d 628d 626c unlock(&p->rlock); . 617,624c lock(&p->rlock); if(p->haveinput){ n = p->ip - p->istage; if(n > 0 && p->iq){ if(n > Stagesize) panic("uartclock"); if(qproduce(p->iq, p->istage, n) < 0) ns16552rts(p, 0); else p->ip = p->istage; } p->haveinput = 0; . 615d 420c /* * 128 here is an arbitrary limit to make sure * we don't stay in this loop too long. If the * chips output queue is longer than 128, too * bad -- presotto */ for(i = 0; i < 128; i++){ if(!(uartrdreg(p, Lstat) & Outready)) break; . 417a int i; . ## diffname port/devns16552.c 1997/1105 ## diff -e /n/emeliedump/1997/0814/sys/src/brazil/port/devns16552.c /n/emeliedump/1997/1105/sys/src/brazil/port/devns16552.c 482a if(p->iq == nil || p->oq == nil) panic("ns16552setup0"); . ## diffname port/devns16552.c 1998/0319 ## diff -e /n/emeliedump/1997/1105/sys/src/brazil/port/devns16552.c /n/emeliedump/1998/0319/sys/src/brazil/port/devns16552.c 910c ns16552write(Chan *c, void *buf, long n, vlong) . 813a ulong offset = off; . 811c ns16552read(Chan *c, void *buf, long n, vlong off) . ## diffname port/devns16552.c 1998/0331 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/devns16552.c /n/emeliedump/1998/0331/sys/src/brazil/port/devns16552.c 652c iunlock(&p->tlock); . 647c ilock(&p->tlock); . 642c iunlock(&p->rlock); . 629c ilock(&p->rlock); . 595c iunlock(&p->tlock); . 590c ilock(&p->tlock); . 579c iunlock(&p->rlock); . 575c ilock(&p->rlock); . 571c iunlock(&p->tlock); . 562c ilock(&p->tlock); . ## diffname port/devns16552.c 1998/0512 ## diff -e /n/emeliedump/1998/0331/sys/src/brazil/port/devns16552.c /n/emeliedump/1998/0512/sys/src/brazil/port/devns16552.c 847c . 598c . 586c . 582c . 558c . 265c . 256c . ## diffname port/devns16552.c 1999/0315 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0315/sys/src/brazil/port/devns16552.c 857a break; case 'E': case 'e': ns16552dsrhup(p, n); . 854a case 'C': case 'c': ns16552dcdhup(p, n); break; . 803,806c p->baud, p->hup_dcd, (tstat & Dtr) != 0, p->hup_dsr, (fstat & Bits8) + 5, (istat & Imstat) != 0, (fstat & Pena) ? ((fstat & Peven) ? 'e' : 'o') : 'n', (tstat & Rts) != 0, (fstat & Stop2) ? 2 : 1, p->dev, p->frame, p->overrun, p->fifoon ? " fifo" : "", (mstat & Cts) ? " cts" : "", (mstat & Dsr) ? " dsr" : "", (mstat & Dcd) ? " dcd" : "", (mstat & Ring) ? " ring" : "" ); . 786,801c istat = p->sticky[Iena]; fstat = p->sticky[Format]; snprint(str, sizeof str, "b%d c%d d%d e%d l%d m%d p%c r%d s%d\n" "%d %d %d%s%s%s%s%s\n", . 779,780c uchar mstat, fstat, istat, tstat; . 769a p->dcd = p->dsr = p->dohup = 0; . 643a if(p->dohup){ ilock(&p->rlock); if(p->dohup){ qhangup(p->iq, 0); qhangup(p->oq, 0); } p->dohup = 0; iunlock(&p->rlock); } . 596a if (ch & Dsrc) { l = ch & Dsr; if(p->hup_dsr && p->dsr && !l){ ilock(&p->rlock); p->dohup = 1; iunlock(&p->rlock); } p->dsr = l; } if (ch & Dcdc) { l = ch & Dcd; if(p->hup_dcd && p->dcd && !l){ ilock(&p->rlock); p->dohup = 1; iunlock(&p->rlock); } p->dcd = l; } . 313a p->hup_dsr = p->hup_dcd = 0; p->cts = p->dsr = p->dcd = 0; . 160a ns16552dsrhup(Uart *p, int n) { p->hup_dsr = n; } static void ns16552dcdhup(Uart *p, int n) { p->hup_dcd = n; } static void . 159a /* * decide if we should hangup when dsr or dcd drops. */ . 117a int hup_dsr, hup_dcd; /* send hangup upstream? */ int dohup; . 116c int cts, dsr, dcd; /* keep track of modem status */ . ## diffname port/devns16552.c 1999/0320 ## diff -e /n/emeliedump/1999/0315/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0320/sys/src/brazil/port/devns16552.c 892c tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125); . 471a Uart *p; p = v; . 470c ns16552flow(void *v) . 460a Uart *p; p = v; . 459c ns16552kick(void *v) . 439a p = v; . 438a Uart *p; . 436c ns16552kick0(void *v) . ## diffname port/devns16552.c 1999/0513 ## diff -e /n/emeliedump/1999/0320/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0513/sys/src/brazil/port/devns16552.c 993c if((p->istat & Fenabd) == 0 && p->fifoon && p->type < Ns550) . 537a p->type = type; . 524c ns16552setup(ulong port, ulong freq, char *name, int type) . 299,301c if(p->type == Ns650){ outb(p->port + Format, 0xbf); outb(p->port + Efr, Eena|Arts|Acts); uartwrreg(p, Format, 0); } else { p->sticky[Iena] &= ~Imstat; uartwrreg(p, Iena, 0); p->modem = 0; } . 294,297c print("mflow type %d\n", p->type); if(p->type == Ns650){ outb(p->port + Format, 0xbf); outb(p->port + Efr, Eena|Arts|Acts); uartwrreg(p, Format, 0); p->cts = 1; } else { p->sticky[Iena] |= Imstat; uartwrreg(p, Iena, 0); p->modem = 1; p->cts = uartrdreg(p, Mstat) & Cts; } . 291a . 280c p->type = Ns450; . 276c if(p->type == Ns650) uartwrreg(p, Fifoctl, Fena|Ftrig24); else uartwrreg(p, Fifoctl, Fena|Ftrig4); . 258c if(p->type < Ns550) . 210d 99c uchar type; /* chip version */ . 82c ulong port; /* io ports */ . 68a Ns450= 0, Ns550, Ns650, . 62a Efr= 2, /* enhanced features for 16C650 */ Eena= (1<<4), /* enable enhanced bits in normal registers */ Arts= (1<<6), /* auto rts */ Acts= (1<<7), /* auto cts */ . 44a Intsel=(1<<5), /* NO! open source interrupts; 16C650 */ Irda= (1<<6), /* infrared interface; 16C650 */ Cdiv= (1<<7), /* divide clock by four; 16C650 */ . 38a Ers= 0xbf, /* enable enhaced register set on 16C650 */ . 29c Ftrig4= (1<<6), /* trigger after 4 input characters */ Ftrig24= (2<<6), /* trigger after 24 input characters */ . 26a Irctsd=(1<<4), /* auto rts or cts changed state */ . 24a Isleep=(1<<4), /* put in sleep mode; 16C650 */ Ixoff= (1<<5), /* for xoff received; 16C650 */ Irts= (1<<6), /* for !rts asserted in auto mode; 16C650 */ Icts= (1<<7), /* for !cts asserted in auto mode; 16C650 */ . ## diffname port/devns16552.c 1999/0514 ## diff -e /n/emeliedump/1999/0513/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0514/sys/src/brazil/port/devns16552.c 316d ## diffname port/devns16552.c 1999/0601 ## diff -e /n/emeliedump/1999/0514/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0601/sys/src/brazil/port/devns16552.c 998a break; case 'T': case 't': ns16552dcdts(p, n); . 671a if(l == 0 && p->dcd != 0 && p->dcdts) savets(); . 256a * save dcd timestamps for gps clock */ static void ns16552dcdts(Uart *p, int n) { p->dcdts = n; } /* . 151a /* interrupt timestamps, l.s fills intrts each interupt */ uvlong intrts; static struct { Lock; int vno; /* vector to save timestamps for */ int n; /* number of valid timestamps in ts[] */ uvlong ts[128]; /* time stamps */ } tsalloc; /* called with interrupts off by interrupt routine */ static void savets(void) { lock(&tsalloc); if(tsalloc.n < nelem(tsalloc.ts)) tsalloc.ts[tsalloc.n++] = intrts; unlock(&tsalloc); } /* read interrupt timestamps */ long readintrts(void *buf, int n) { n /= sizeof(uvlong); if(n <= 0) return 0; ilock(&tsalloc); if(n > tsalloc.n) n = tsalloc.n; memmove(buf, tsalloc.ts, n*sizeof(uvlong)); tsalloc.n = 0; iunlock(&tsalloc); return n*sizeof(uvlong); } . 134c int cts, dsr, dcd, dcdts; /* keep track of modem status */ . ## diffname port/devns16552.c 1999/0701 ## diff -e /n/emeliedump/1999/0601/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0701/sys/src/brazil/port/devns16552.c 716,717c if(l == 0 && p->dcd != 0 && p->dcdts && saveintrts != nil) (*saveintrts)(); . 152,186d ## diffname port/devns16552.c 1999/0711 ## diff -e /n/emeliedump/1999/0701/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0711/sys/src/brazil/port/devns16552.c 747c /* this adds hysteresis to hardware/software flow control */ . 683,687c if(p->hup_dcd && p->dcd && !l) p->dohup = 1; /* clock peforms hangup */ . 672,676c if(p->hup_dsr && p->dsr && !l) p->dohup = 1; /* clock peforms hangup */ . 668d 663d 644d 641c p->ctsbackoff = 2; /* clock gets output going again */ . 635d ## diffname port/devns16552.c 1999/0820 ## diff -e /n/emeliedump/1999/0711/sys/src/brazil/port/devns16552.c /n/emeliedump/1999/0820/sys/src/brazil/port/devns16552.c 1089a /* * Polling I/O routines for kernel debugging helps. */ static void ns16552setuppoll(Uart *p, int rate) { ulong brconst; /* * 8 bits/character, 1 stop bit; * set rate to rate baud; * turn on Rts and Dtr. */ memmove(p->osticky, p->sticky, sizeof p->osticky); p->sticky[Format] = Bits8; uartwrreg(p, Format, 0); brconst = (UartFREQ+8*rate-1)/(16*rate); uartwrreg(p, Format, Dra); outb(p->port+Dmsb, (brconst>>8) & 0xff); outb(p->port+Dlsb, brconst & 0xff); uartwrreg(p, Format, 0); p->sticky[Mctl] = Rts|Dtr; uartwrreg(p, Mctl, 0); p->kinuse = 1; } /* * Restore serial state from before kernel took over. */ static void ns16552restore(Uart *p) { ulong brconst; memmove(p->sticky, p->osticky, sizeof p->sticky); uartwrreg(p, Format, 0); brconst = (UartFREQ+8*p->baud-1)/(16*p->baud); uartwrreg(p, Format, Dra); outb(p->port+Dmsb, (brconst>>8) & 0xff); outb(p->port+Dlsb, brconst & 0xff); uartwrreg(p, Format, 0); uartwrreg(p, Mctl, 0); p->kinuse = 0; } /* BUG should be configurable */ enum { WHICH = 0, RATE = 9600, }; int serialgetc(void) { Uart *p; int c; if((p=uart[WHICH]) == nil) return -1; if(!p->kinuse) ns16552setuppoll(p, RATE); while((uartrdreg(p, Lstat)&Inready) == 0) ; c = inb(p->port+Data) & 0xFF; return c; // there should be a restore here but i think it will slow things down too much. } static void serialputc(Uart *p, int c) { while((uartrdreg(p, Lstat)&Outready) == 0) ; outb(p->port+Data, c); while((uartrdreg(p, Lstat)&Outready) == 0) ; } void serialputs(char *s, int n) { Uart *p; if((p=uart[WHICH]) == nil) return; if(!p->kinuse) ns16552setuppoll(p, RATE); while(n-- > 0){ serialputc(p, *s); if(*s == '\n') serialputc(p, '\r'); s++; } ns16552restore(p); } . 1027a if(p->kinuse) error(Ekinuse); . 917a if(p->kinuse) error(Ekinuse); . 855a if(p->kinuse) error(Ekinuse); . 829a if(p->kinuse) error(Ekinuse); . 322d 152a * means the kernel is using this for debugging output */ static char Ekinuse[] = "device in use by kernel"; /* . 138a int kinuse; /* device in use by kernel */ . 99a uchar osticky[8]; /* kernel saved sticky write register values */ . ## diffname port/devns16552.c 2000/0614 ## diff -e /n/emeliedump/1999/0820/sys/src/brazil/port/devns16552.c /n/emeliedump/2000/0614/sys/src/9/port/devns16552.c 905a p->type, . 893c "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s%s\n", . 314a /* fix from Scott Schwartz */ p->istat = uartrdreg(p, Istat); . ## diffname port/devns16552.c 2000/0708 ## diff -e /n/emeliedump/2000/0614/sys/src/9/port/devns16552.c /n/emeliedump/2000/0708/sys/src/9/port/devns16552.c 1051,1054c if((p->istat & Fenabd) == 0 && p->fifoon && p->type < Ns550){ lock(&p->flock); if((p->istat & Fenabd) == 0 && p->fifoon && p->type < Ns550) ns16552fifo(p, 1); unlock(&p->flock); } . 987a case 'i': case 'I': lock(&p->flock); ns16552fifo(p, n); unlock(&p->flock); break; . 359,368c /* modem needs fifo */ lock(&p->flock); ns16552fifo(p, n); unlock(&p->flock); . 321d 296a if(n == 0){ /* turn off fifo's */ p->fifoon = 0; uartwrreg(p, Fifoctl, 0); splx(x); return; } . 290c ulong i; int x; . 288c ns16552fifo(Uart *p, int n) . 286a /* * always called under lock(&p->flock) */ . ## diffname port/devns16552.c 2000/0709 ## diff -e /n/emeliedump/2000/0708/sys/src/9/port/devns16552.c /n/emeliedump/2000/0709/sys/src/9/port/devns16552.c 966,1041c if(strncmp(f[i], "break", 5) == 0){ ns16552break(p, 0); continue; } n = atoi(f[i]+1); switch(*f[i]){ case 'B': case 'b': ns16552setbaud(p, n); break; case 'C': case 'c': ns16552dcdhup(p, n); break; case 'D': case 'd': ns16552dtr(p, n); break; case 'E': case 'e': ns16552dsrhup(p, n); break; case 'f': case 'F': qflush(p->oq); break; case 'H': case 'h': qhangup(p->iq, 0); qhangup(p->oq, 0); break; case 'i': case 'I': lock(&p->flock); ns16552fifo(p, n); unlock(&p->flock); break; case 'L': case 'l': ns16552bits(p, n); break; case 'm': case 'M': ns16552mflow(p, n); break; case 'n': case 'N': qnoblock(p->oq, n); break; case 'P': case 'p': ns16552parity(p, *(cmd+1)); break; case 'K': case 'k': ns16552break(p, n); break; case 'R': case 'r': ns16552rts(p, n); break; case 'Q': case 'q': qsetlimit(p->iq, n); qsetlimit(p->oq, n); break; case 'T': case 't': ns16552dcdts(p, n); break; case 'W': case 'w': /* obsolete */ break; case 'X': case 'x': ilock(&p->tlock); p->xonoff = n; iunlock(&p->tlock); break; } . 964a for(i = 0; i < nf; i++){ . 960,963c nf = getfields(cmd, f, nelem(f), 1, " \t\n"); . 954a char *f[32]; int nf; . 916d 910a p->fifoon, . 899,900c "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n" "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n", . ## diffname port/devns16552.c 2001/0518 ## diff -e /n/emeliedump/2000/0709/sys/src/9/port/devns16552.c /n/emeliedump/2001/0518/sys/src/9/port/devns16552.c 314,317c uartrdreg(p, Istat); uartrdreg(p, Data); . ## diffname port/devns16552.c 2001/0527 # deleted ## diff -e /n/emeliedump/2001/0518/sys/src/9/port/devns16552.c /n/emeliedump/2001/0527/sys/src/9/port/devns16552.c 1,1228d