## diffname pc/devuart.c 1991/0801 ## diff -e /dev/null /n/bootesdump/1991/0801/sys/src/9/safari/devuart.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "errno.h" #include "devtab.h" /* * Driver for an NS16450 serial port */ enum { /* * register numbers */ Data= 0, /* xmit/rcv buffer */ Iena= 1, /* interrupt enable */ Ircv= (1<<0), /* interrupt on receive */ Ixmt= (1<<1), /* interrupt on xmit */ Istat= 2, /* interrupt flag */ 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 */ Dcd= (1<<3), /* carrier */ Loop= (1<<4), /* loop bask */ Lstat= 5, /* line status */ Inready=(1<<0), /* receive buffer full */ Outbusy=(1<<5), /* output buffer full */ Mstat= 6, /* modem status */ Scratch=7, /* scratchpad */ Dlsb= 0, /* divisor lsb */ Dmsb= 1, /* divisor msb */ }; typedef struct Uart Uart; struct Uart { QLock; int port; ushort sticky[16]; /* sticky write register values */ int printing; /* true if printing */ /* 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 */ }; Uart uart[2]; #define UartFREQ 1846200 #define uartwrreg(u,r,v) outb(u->port + r, u->sticky[r] | v) #define uartrdreg(u,r) inb(u->port + r) void uartintr(Uart*); void uartintr0(Ureg*); void uartintr1(Ureg*); void uartsetup(void); /* * set the baud rate by calculating and setting the baudrate * generator constant. This will work with fairly non-standard * baud rates. */ void uartsetbaud(Uart *up, int rate) { ulong brconst; brconst = (UartFREQ+8*rate-1)/16*rate; uartwrreg(up, Format, Dra); uartwrreg(up, Dmsb, (brconst>>8) & 0xff); uartwrreg(up, Dlsb, brconst & 0xff); uartwrreg(up, Format, 0); } /* * toggle DTR */ void uartdtr(Uart *up, int n) { if(n) up->sticky[Mctl] |= Dtr; else up->sticky[Mctl] &= ~Dtr; uartwrreg(up, Mctl, 0); } /* * toggle RTS */ void uartrts(Uart *up, int n) { if(n) up->sticky[Mctl] |= Rts; else up->sticky[Mctl] &= ~Rts; uartwrreg(up, Mctl, 0); } /* * send break */ void uartbreak(Uart *up, int ms) { uartwrreg(up, Format, Break); tsleep(&u->p->sleep, return0, 0, ms); uartwrreg(up, Format, 0); } /* * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts, * transmit and receive enabled, interrupts disabled. */ void uartsetup(void) { Uart *up; static int already; if(already) return; already = 1; /* * get port addresses */ uart[0].port = 0x3F8; uart[1].port = 0x2F8; setvec(Uart0vec, uartintr0); setvec(Uart1vec, uartintr1); for(up = uart; up < &uart[2]; up++){ memset(up->sticky, 0, sizeof(up->sticky)); /* * set rate to 9600 baud. * 8 bits/character. * 1 stop bit. */ uartsetbaud(up, 9600); up->sticky[Format] = Bits8; uartwrreg(up, Format, 0); } } /* * Queue n characters for output; if queue is full, we lose characters. * Get the output going if it isn't already. */ void uartputs(IOQ *cq, char *s, int n) { Uart *up = cq->ptr; int st, ch, x; x = splhi(); lock(cq); puts(cq, s, n); if(up->printing == 0){ ch = getc(cq); print("", ch);/**/ if(ch >= 0){ up->printing = 1; while(uartrdreg(up, Lstat) & Outbusy) ; outb(up->port + Data, ch); } } unlock(cq); splx(x); } /* * a uart interrupt (a damn lot of work for one character) */ void uartintr(Uart *up) { int s; int ch; IOQ *cq; switch(uartrdreg(up, Istat)){ case 3: /* * get any input characters */ cq = up->iq; while(uartrdreg(up, Lstat) & Inready){ ch = uartrdreg(up, Data) & 0xff; if(cq->putc) (*cq->putc)(cq, ch); else { putc(cq, ch); if(up->delim[ch/8] & (1<<(ch&7)) ) wakeup(&cq->r); } } break; case 5: /* * send next output character */ if((s & Outbusy)==0){ cq = up->oq; lock(cq); ch = getc(cq); if(ch < 0){ up->printing = 0; wakeup(&cq->r); }else outb(up->port + Data, ch); unlock(cq); } break; } } void uartintr0(Ureg *ur) { uartintr(&uart[0]); } void uartintr1(Ureg *ur) { uartintr(&uart[1]); } /* * turn on a port's interrupts. set DTR and RTS */ void uartenable(Uart *up) { /* * set up i/o routines */ if(up->oq){ up->oq->puts = uartputs; up->oq->ptr = up; up->sticky[Iena] |= Ixmt; } if(up->iq){ up->iq->ptr = up; up->sticky[Iena] |= Ircv; } /* * turn on interrupts */ uartwrreg(up, Iena, 0); /* * turn on DTR and RTS */ uartdtr(up, 1); uartrts(up, 1); } /* * set up an uart port as something other than a stream */ void uartspecial(int port, IOQ *oq, IOQ *iq, int baud) { Uart *up = &uart[port]; uartsetup(); up->nostream = 1; up->oq = oq; up->iq = iq; uartenable(up); uartsetbaud(up, baud); if(iq){ /* * Stupid HACK to undo a stupid hack */ if(iq == &kbdq) kbdq.putc = kbdcr2nl; } } static void uarttimer(Alarm*); static int uartputc(IOQ *, int); static void uartstopen(Queue*, Stream*); static void uartstclose(Queue*); static void uartoput(Queue*, Block*); static void uartkproc(void *); Qinfo uartinfo = { nullput, uartoput, uartstopen, uartstclose, "uart" }; /* * create a helper process per port */ static void uarttimer(Alarm *a) { Uart *up = a->arg; cancel(a); up->a = 0; wakeup(&up->iq->r); } static int uartputc(IOQ *cq, int ch) { Uart *up = cq->ptr; int r; r = putc(cq, ch); /* * pass upstream within up->delay milliseconds */ if(up->a==0){ if(up->delay == 0) wakeup(&cq->r); else up->a = alarm(up->delay, uarttimer, up); } return r; } static void uartstopen(Queue *q, Stream *s) { Uart *up; char name[NAMELEN]; kprint("uartstopen: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n", q, s->inuse, s->type, s->dev, s->id); up = &uart[s->id]; qlock(up); up->wq = WR(q); WR(q)->ptr = up; RD(q)->ptr = up; up->delay = 64; up->iq->putc = uartputc; qunlock(up); /* start with all characters as delimiters */ memset(up->delim, 1, sizeof(up->delim)); if(up->kstarted == 0){ up->kstarted = 1; sprint(name, "uart%d", s->id); kproc(name, uartkproc, up); } } static void uartstclose(Queue *q) { Uart *up = q->ptr; qlock(up); kprint("uartstclose: q=0x%ux, id=%d\n", q, up-uart); up->wq = 0; up->iq->putc = 0; WR(q)->ptr = 0; RD(q)->ptr = 0; qunlock(up); } static void uartoput(Queue *q, Block *bp) { Uart *up = q->ptr; IOQ *cq; int n, m; if(up == 0){ freeb(bp); return; } cq = up->oq; if(waserror()){ freeb(bp); nexterror(); } if(bp->type == M_CTL){ 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': uartsetbaud(up, n); break; case 'D': case 'd': uartdtr(up, n); break; case 'K': case 'k': uartbreak(up, n); break; case 'R': case 'r': uartrts(up, n); break; case 'W': case 'w': if(n>=0 && n<1000) up->delay = n; break; } }else while((m = BLEN(bp)) > 0){ while ((n = canputc(cq)) == 0){ print("uartoput: 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 uartkproc(void *a) { Uart *up = a; IOQ *cq = up->iq; Block *bp; int n; loop: while ((n = cangetc(cq)) == 0){ print("uart0 sleeping/n"); sleep(&cq->r, cangetc, cq); } qlock(up); if(up->wq == 0){ cq->out = cq->in; }else{ bp = allocb(n); bp->flags |= S_DELIM; bp->wptr += gets(cq, bp->wptr, n); PUTNEXT(RD(up->wq), bp); } qunlock(up); goto loop; } enum{ Qdir= 0, Qtty0= STREAMQID(0, Sdataqid), Qtty0ctl= STREAMQID(0, Sctlqid), Qtty1= STREAMQID(1, Sdataqid), Qtty1ctl= STREAMQID(1, Sctlqid), }; Dirtab uartdir[]={ "tty0", {Qtty0}, 0, 0666, "tty0ctl", {Qtty0ctl}, 0, 0666, "tty1", {Qtty1}, 0, 0666, "tty1ctl", {Qtty1ctl}, 0, 0666, }; #define NUart (sizeof uartdir/sizeof(Dirtab)) /* * allocate the queues if no one else has */ void uartreset(void) { Uart *up; uartsetup(); for(up = uart; up < &uart[2]; up++){ if(up->nostream) continue; up->iq = ialloc(sizeof(IOQ), 0); initq(up->iq); up->oq = ialloc(sizeof(IOQ), 0); initq(up->oq); uartenable(up); } } void uartinit(void) { } Chan* uartattach(char *upec) { return devattach('t', upec); } Chan* uartclone(Chan *c, Chan *nc) { return devclone(c, nc); } int uartwalk(Chan *c, char *name) { return devwalk(c, name, uartdir, NUart, devgen); } void uartstat(Chan *c, char *dp) { switch(c->qid.path){ case Qtty0: streamstat(c, dp, "tty0"); break; case Qtty1: streamstat(c, dp, "tty1"); break; default: devstat(c, dp, uartdir, NUart, devgen); break; } } Chan* uartopen(Chan *c, int omode) { Uart *up; switch(c->qid.path){ case Qtty0: case Qtty0ctl: up = &uart[0]; break; case Qtty1: case Qtty1ctl: up = &uart[1]; break; default: up = 0; break; } if(up && up->nostream) errors("in use"); if((c->qid.path & CHDIR) == 0) streamopen(c, &uartinfo); return devopen(c, omode, uartdir, NUart, devgen); } void uartcreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void uartclose(Chan *c) { if(c->stream) streamclose(c); } long uartread(Chan *c, void *buf, long n, ulong offset) { switch(c->qid.path&~CHDIR){ case Qdir: return devdirread(c, buf, n, uartdir, NUart, devgen); case Qtty1ctl: case Qtty0ctl: return 0; } return streamread(c, buf, n); } long uartwrite(Chan *c, void *va, long n, ulong offset) { return streamwrite(c, va, n, 0); } void uartremove(Chan *c) { error(Eperm); } void uartwstat(Chan *c, char *dp) { error(Eperm); } . ## diffname pc/devuart.c 1991/0803 ## diff -e /n/bootesdump/1991/0801/sys/src/9/safari/devuart.c /n/bootesdump/1991/0803/sys/src/9/safari/devuart.c 507a if(serial(0) < 0) print("can't turn on power\n"); . 468d 272a up->sticky[Iena] |= (1<<2) | (1<<3); . 233a print("", ch);/**/ . 230c if(uartrdreg(up, Lstat)&Outready){ . 209c s = uartrdreg(up, Istat); print("uartintr %lux\n", s); switch(s){ . 207a int s; . 205d 190c for(tries = 0; tries<10000 && !(uartrdreg(up, Lstat)&Outready); tries++) . 180a int tries; . 91c brconst = (UartFREQ+8*rate-1)/(16*rate); . 40c Outready=(1<<5), /* output buffer full */ . ## diffname pc/devuart.c 1991/0804 ## diff -e /n/bootesdump/1991/0803/sys/src/9/safari/devuart.c /n/bootesdump/1991/0804/sys/src/9/safari/devuart.c 151c * set port addresses . 94,95c outb(up->port+Dmsb, (brconst>>8) & 0xff); outb(up->port+Dlsb, brconst & 0xff); . 73,74c #define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v)) #define uartrdreg(u,r) inb((u)->port + r) . 52c uchar sticky[8]; /* sticky write register values */ . ## diffname pc/devuart.c 1991/0806 ## diff -e /n/bootesdump/1991/0804/sys/src/9/safari/devuart.c /n/bootesdump/1991/0806/sys/src/9/safari/devuart.c 525d 514,516d 401a if(serial(1) < 0) print("can't turn off serial power\n"); . 371a uartenable(up); if(s->id==0 && serial(0)<0) print("can't turn on serial power\n"); . 370a . 369c print("uartstopen: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n", . 305a if(port == 0){ if(serial(0) < 0) print("can't turn on serial port power\n"); } . 289a /* * read interrupt status till there aren't any pending */ while(uartrdreg(up, Istat) != 1){ x = splhi(); uartintr(up); splx(x); } . 265a int x; . 247a /* * send next output character */ if(up->printing && (l&Outready)){ cq = up->oq; lock(cq); ch = getc(cq); print("", ch);/**/ if(ch < 0){ up->printing = 0; wakeup(&cq->r); }else outb(up->port + Data, ch); unlock(cq); } . 246c l = uartrdreg(up, Lstat); . 242,244d 212,240c cq = up->iq; while(l & Inready){ ch = uartrdreg(up, Data) & 0xff; print("", ch); if(cq->putc) (*cq->putc)(cq, ch); else { putc(cq, ch); if(up->delim[ch/8] & (1<<(ch&7)) ) . 210a l = uartrdreg(up, Lstat); . 209c int s, l; . ## diffname pc/devuart.c 1991/0807 ## diff -e /n/bootesdump/1991/0806/sys/src/9/safari/devuart.c /n/bootesdump/1991/0807/sys/src/9/safari/devuart.c 417,419d 409a uartdisable(up); . 384,385d 312,315d 291,294c up->sticky[Iena] = 0; uartwrreg(up, Iena, 0); /* * turn off DTR and RTS */ uartdtr(up, 0); uartrts(up, 0); up->enabled = 0; /* * turn off power */ if(up == &uart[0]){ if(serial(1) < 0) print("can't turn off serial power\n"); . 289c * turn off interrupts . 287a /* * turn off the uart */ uartdisable(Uart *up) { . 286a } . 274a up->enabled = 1; . 263a * turn on power to the port */ if(up == &uart[0]){ if(serial(0) < 0) print("can't turn on serial port power\n"); } /* . 247c if(uart[0].enabled) uartintr(&uart[0]); . 235d 217d 188d 53a int enabled; . ## diffname pc/devuart.c 1991/0808 ## diff -e /n/bootesdump/1991/0807/sys/src/9/safari/devuart.c /n/bootesdump/1991/0808/sys/src/9/safari/devuart.c 514,524d 512a qlock(up); if(up->wq == 0){ cq->out = cq->in; }else{ n = cangetc(cq); bp = allocb(n); bp->flags |= S_DELIM; bp->wptr += gets(cq, bp->wptr, n); PUTNEXT(RD(up->wq), bp); } qunlock(up); . 510,511c if(waserror()) print("uartkproc got an error\n"); for(;;){ . 487d 479,483d 470a case 'e': case 'E': /* * the characters in the block are the message * delimiters to use upstream */ memset(up->delim, 0, sizeof(up->delim)); while(++(bp->rptr) < bp->wptr){ m = *bp->rptr; up->delim[m/8] |= 1<<(m&7); } break; . 417c memset(up->delim, 0xff, sizeof(up->delim)); . 412,413d 405a up->iq->putc = 0; . 377,395d 322a /* * slow the clock down again */ clockinit(); . 319c if(up == &uart[Serial]){ . 294a print("uart enabled: Iena=%lux\n", uartrdreg(up, Iena)); . 288a uartwrreg(up, Tctl, 0x0); . 283c up->sticky[Iena] = 0xf; . 280d 276d 270a * speed up the clock to poll the uart */ fclockinit(); /* . 265c if(up == &uart[Serial]){ . 251c if(uart[1].enabled) uartintr(&uart[1]); . 65d 44a Serial= 0, Modem= 1, . 21,23c Istat= 2, /* interrupt flag (read) */ Tctl= 2, /* test control (write) */ . 1c #include "u.h" . ## diffname pc/devuart.c 1991/0810 ## diff -e /n/bootesdump/1991/0808/sys/src/9/safari/devuart.c /n/bootesdump/1991/0810/sys/src/9/safari/devuart.c 395,397d 301,302d 294d 292a up->sticky[Iena] = 0x7; . 288d 275a */ . 274d 252,253c uartintr(&uart[1]); . 246,247c uartintr(&uart[0]); . 227,241d 225d 223a }else outb(up->port + Data, ch); unlock(cq); break; case 0: /* modem status */ l = uartrdreg(up, Mstat); break; default: if(s&1) return; print("weird modem interrupt\n"); break; . 212,222c for(;;){ s = uartrdreg(up, Istat); switch(s){ case 6: /* receiver line status */ l = uartrdreg(up, Lstat); break; case 4: /* received data available */ cq = up->iq; ch = uartrdreg(up, Data) & 0xff; if(cq->putc) (*cq->putc)(cq, ch); else { putc(cq, ch); if(up->delim[ch/8] & (1<<(ch&7)) ) wakeup(&cq->r); } break; case 2: /* transmitter empty */ cq = up->oq; lock(cq); ch = getc(cq); if(ch < 0){ up->printing = 0; . 170a up->sticky[Mctl] |= Inton; uartwrreg(up, Mctl, 0x0); . 166a * interrupts enabled. . 35c Inton= (1<<3), /* turn on interrupts */ . ## diffname pc/devuart.c 1991/0822 ## diff -e /n/bootesdump/1991/0810/sys/src/9/safari/devuart.c /n/bootesdump/1991/0822/sys/src/9/safari/devuart.c 284,288d 231a l = uartrdreg(up, Lstat); if(l & Overrun) screenputc('!'); . 214a /* * the for loop takes care of multiple events per interrupt */ . 38a Overrun=(1<<1), /* we lost an input char */ . ## diffname pc/devuart.c 1991/0823 ## diff -e /n/bootesdump/1991/0822/sys/src/9/safari/devuart.c /n/bootesdump/1991/0823/sys/src/9/safari/devuart.c 533a if(up->frame != frame){ kprint("uart%d: %d framing\n", up-uart, up->frame); frame = up->frame; } if(up->overrun != overrun){ kprint("uart%d: %d overruns\n", up-uart, up->overrun); overrun = up->overrun; } . 516a ulong frame, overrun; . 307c up->sticky[Iena] = Ircv | Ixmt | Irstat; . 292a * speed up the clock to poll the uart fclockinit(); */ /* . 260c /* print("weird modem interrupt\n");/**/ . 236,238d 223a if(l & Ferror) up->frame++; if(l & Oerror) up->overrun++; . 216,218d 69a /* error statistics */ ulong frame; ulong overrun; . 39c Oerror=(1<<1), /* receiver overrun */ Perror=(1<<2), /* receiver parity error */ Ferror=(1<<3), /* rcv framing error */ . 20a 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 */ . 1c #include "u.h" . ## diffname pc/devuart.c 1991/0904 ## diff -e /n/bootesdump/1991/0823/sys/src/9/safari/devuart.c /n/bootesdump/1991/0904/sys/src/9/safari/devuart.c 530a frame = 0; overrun = 0; . 262c uartrdreg(up, Mstat); . ## diffname pc/devuart.c 1991/1001 ## diff -e /n/bootesdump/1991/0904/sys/src/9/safari/devuart.c /n/bootesdump/1991/1001/sys/src/9/safari/devuart.c 297a } else { if(modem(0) < 0) print("can't turn on modem speaker\n"); . ## diffname pc/devuart.c 1991/1113 ## diff -e /n/bootesdump/1991/1001/sys/src/9/safari/devuart.c /n/bootesdump/1991/1113/sys/src/9/safari/devuart.c 542a if((ints++ & 0x1f) == 0) owl(ints>>5); . 533a static ulong ints; . 489,500d 434,436d 304,308d 283a void uartclock(void) { Uart *up; IOQ *cq; for(up = uart; up < &uart[2]; up++){ cq = up->iq; if(up->wq && cangetc(cq)) wakeup(&cq->r); } } . 244,246d 242c else . 75d ## diffname pc/devuart.c 1991/1115 ## diff -e /n/bootesdump/1991/1113/sys/src/9/safari/devuart.c /n/bootesdump/1991/1115/sys/src/9/safari/devuart.c 679,680c case Qeia1ctl: case Qeia0ctl: . 643,644c case Qeia1: case Qeia1ctl: . 639,640c case Qeia0: case Qeia0ctl: . 624,625c case Qeia1: streamstat(c, dp, "eia1"); . 621,622c case Qeia0: streamstat(c, dp, "eia0"); . 567,570c "eia0", {Qeia0}, 0, 0666, "eia0ctl", {Qeia0ctl}, 0, 0666, "eia1", {Qeia1}, 0, 0666, "eia1ctl", {Qeia1ctl}, 0, 0666, . 560,563c Qeia0= STREAMQID(0, Sdataqid), Qeia0ctl= STREAMQID(0, Sctlqid), Qeia1= STREAMQID(1, Sdataqid), Qeia1ctl= STREAMQID(1, Sctlqid), . ## diffname pc/devuart.c 1991/1210 ## diff -e /n/bootesdump/1991/1115/sys/src/9/safari/devuart.c /n/bootesdump/1991/1210/sys/src/9/safari/devuart.c 535c lights((ints>>5)&1); . 362a } else { if(modem(0) < 0) print("can't turn off modem speaker\n"); . 361c if(serial(0) < 0) . 309c if(modem(1) < 0) . 306c if(serial(1) < 0) . ## diffname pc/devuart.c 1992/0101 ## diff -e /n/bootesdump/1991/1210/sys/src/9/safari/devuart.c /n/bootesdump/1992/0101/sys/src/9/safari/devuart.c 142a if(ms == 0) ms = 200; . ## diffname pc/devuart.c 1992/0111 ## diff -e /n/bootesdump/1992/0101/sys/src/9/safari/devuart.c /n/bootesdump/1992/0111/sys/src/9/safari/devuart.c 7c #include "../port/error.h" . ## diffname pc/devuart.c 1992/0114 ## diff -e /n/bootesdump/1992/0111/sys/src/9/safari/devuart.c /n/bootesdump/1992/0114/sys/src/9/safari/devuart.c 658c error(Einuse); . ## diffname pc/devuart.c 1992/0321 ## diff -e /n/bootesdump/1992/0114/sys/src/9/safari/devuart.c /n/bootesdump/1992/0321/sys/src/9/safari/devuart.c 2c #include "../port/lib.h" . ## diffname pc/devuart.c 1992/0409 ## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devuart.c /n/bootesdump/1992/0409/sys/src/9/safari/devuart.c 266c print("weird modem interrupt\n"); . 248a if(cq == 0) break; . 240a cq = up->iq; if(cq == 0) break; . 239d ## diffname pc/devuart.c 1992/0602 ## diff -e /n/bootesdump/1992/0409/sys/src/9/safari/devuart.c /n/bootesdump/1992/0602/sys/src/9/safari/devuart.c 418,430d 404d 73d ## diffname pc/devuart.c 1992/0625 ## diff -e /n/bootesdump/1992/0602/sys/src/9/safari/devuart.c /n/bootesdump/1992/0625/sys/src/9/safari/devuart.c 583c up->oq = xalloc(sizeof(IOQ)); . 581c up->iq = xalloc(sizeof(IOQ)); . ## diffname pc/devuart.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devuart.c /n/bootesdump/1992/0711/sys/src/9/safari/devuart.c 694a USED(c, dp); . 688a USED(c); . 682a USED(offset); . 669a USED(offset); . 656a USED(c, name, omode, perm); . 345a void . 305,306d 281a USED(ur); . 276a USED(ur); . 196c int ch, x; . ## diffname pc/devuart.c 1992/0826 ## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devuart.c /n/bootesdump/1992/0826/sys/src/9/pc/devuart.c 620c streamstat(c, dp, uartdir[2].name, uartdir[2].perm); . 617c streamstat(c, dp, uartdir[0].name, uartdir[0].perm); . ## diffname pc/devuart.c 1992/1016 ## diff -e /n/bootesdump/1992/0826/sys/src/9/pc/devuart.c /n/bootesdump/1992/1016/sys/src/9/pc/devuart.c 492a break; case 'S': case 's': uartstop(up, n); . 489a case 'L': case 'l': uartbits(up, n); break; case 'P': case 'p': uartparity(up, *(bp->rptr+1)); break; . 360a */ . 358d 184a uartdtr(up, 1); uartrts(up, 1); . 149a * set bits/char */ void uartbits(Uart *up, int bits) { if(bits < 5 || bits > 8) error(Ebadarg); up->sticky[Format] &= ~3; up->sticky[Format] |= bits-5; uartwrreg(up, Format, 0); } /* * set parity */ void uartparity(Uart *up, int c) { switch(c&0xff){ case 'e': up->sticky[Format] |= Pena|Peven; break; case 'o': up->sticky[Format] &= ~Peven; up->sticky[Format] |= Pena; break; default: up->sticky[Format] &= ~(Pena|Peven); break; } uartwrreg(up, Format, 0); } /* * set stop bits */ void uartstop(Uart *up, int n) { switch(n){ case 1: up->sticky[Format] &= ~Stop2; break; case 2: default: up->sticky[Format] |= Stop2; break; } uartwrreg(up, Format, 0); } /* . 40c Loop= (1<<4), /* loop back */ . ## diffname pc/devuart.c 1992/1017 ## diff -e /n/bootesdump/1992/1016/sys/src/9/pc/devuart.c /n/bootesdump/1992/1017/sys/src/9/pc/devuart.c 714c if(up && up->special) . 647c if(up->special) . 500a if(up->special) return; . 448c if(baud) uartsetbaud(up, baud); . 444c up->special = 1; . 428,432d 415d 412a */ . 411a * revert to default settings */ up->sticky[Format] = Bits8; uartwrreg(up, Format, 0); /* . 237,239d 66c int special; /* can't use the stream interface */ . ## diffname pc/devuart.c 1992/1210 ## diff -e /n/bootesdump/1992/1017/sys/src/9/pc/devuart.c /n/bootesdump/1992/1210/sys/src/9/pc/devuart.c 549a break; case 'm': case 'M': uartmflow(up, n); . 392a /* * assume we can send */ up->cts = 1; . 315c ch = uartrdreg(up, Mstat); if(ch & Ctsc){ up->cts = ch & Cts; cq = up->oq; if(cq == 0) break; if(multiprocessor) lock(cq); if(up->cts && up->printing == 0){ ch = getc(cq); if(ch >= 0){ up->printing = 1; outb(up->port + Data, getc(cq)); } else wakeup(&cq->r); } if(multiprocessor) unlock(cq); } . 308,311c else { ch = getc(cq); if(ch < 0){ up->printing = 0; wakeup(&cq->r); }else outb(up->port + Data, ch); } if(multiprocessor) unlock(cq); . 304,306c if(multiprocessor) lock(cq); if(up->cts == 0) . 277a multiprocessor = active.machs > 1; . 276c int s, l, multiprocessor; . 264c if(multiprocessor) unlock(cq); . 252c if(multiprocessor) lock(cq); . 250a multiprocessor = active.machs > 1; . 248c int ch, x, multiprocessor; . 201a * modem flow control on/off (rts/cts) */ void uartmflow(Uart *up, int n) { if(n){ up->sticky[Iena] |= Imstat; uartwrreg(up, Iena, 0); up->cts = uartrdreg(up, Mstat) & Cts; } else { up->sticky[Iena] &= ~Imstat; uartwrreg(up, Iena, 0); up->cts = 1; } } /* . 63a int cts; . 47a 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 */ . ## diffname pc/devuart.c 1993/0326 ## diff -e /n/bootesdump/1992/1210/sys/src/9/pc/devuart.c /n/bootesdump/1993/0326/sys/src/9/pc/devuart.c 811c return uartstatus(&uart[0], buf, n, offset); . 809a return uartstatus(&uart[1], buf, n, offset); . 802a uartstatus(Uart *up, void *buf, long n, ulong offset) { uchar mstat; uchar tstat; char str[128]; str[0] = 0; tstat = up->sticky[Mctl]; mstat = uartrdreg(up, Mstat); 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 & Dtr) strcat(str, " rts"); return readstr(offset, buf, n, str); } long . ## diffname pc/devuart.c 1993/0915 ## diff -e /n/bootesdump/1993/0326/sys/src/9/pc/devuart.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devuart.c 859c USED(c, dir); . 857c uartwstat(Chan *c, char *dir) . 831,838c qpath = c->qid.path & ~CHDIR; if(qpath == Qdir) return devdirread(c, buf, n, uartdir, Nuart * 2, devgen); for(i=1; i < 2*Nuart; i += 2) if(qpath == uartdir[i].qid.path) return uartstatus(&uart[i/2], buf, n, offset); . 829a int i; long qpath; . 810,811c tstat = dp->sticky[Mctl]; mstat = uartrdreg(dp, Mstat); . 803c uartstatus(Uart *dp, void *buf, long n, ulong offset) . 785c return devopen(c, omode, uartdir, Nuart * 2, devgen); . 782d 780c if(dp && dp->special) . 766,778c dp = 0; for(i=0; i < 2*Nuart; ++i) if(c->qid.path == uartdir[i].qid.path) { dp = &uart[i/2]; break; } . 764c Uart *dp; int i; . 748,758c int i; for(i=0; i < 2*Nuart; i += 2) if(c->qid.path == uartdir[i].qid.path) { streamstat(c, dir, uartdir[i].name, uartdir[i].perm); return; } devstat(c, dir, uartdir, Nuart * 2, devgen); . 746c uartstat(Chan *c, char *dir) . 742c return devwalk(c, name, uartdir, Nuart * 2, devgen); . 730c return devattach('t', dpec); . 728c uartattach(char *dpec) . 724a int i; for(i=0; i < 2*Nuart; ++i) { if(i & 1 != 0) { sprint(uartdir[i].name, "eia%dctl", i/2); uartdir[i].qid.path = STREAMQID(i/2, Sctlqid); } else { sprint(uartdir[i].name, "eia%d", i/2); uartdir[i].qid.path = STREAMQID(i/2, Sdataqid); } uartdir[i].length = 0; uartdir[i].perm = 0666; } . 715,718c dp->iq = xalloc(sizeof(IOQ)); initq(dp->iq); dp->oq = xalloc(sizeof(IOQ)); initq(dp->oq); . 712,713c for(dp = uart; dp < &uart[Nuart]; dp++){ if(dp->special) . 709c Uart *dp; . 701,702d 694,699c Dirtab uartdir[2*nelem(uart)]; . 688,691d 679,681c if(dp->overrun != overrun){ kprint("uart%d: %d overruns\n", dp-uart, dp->overrun); overrun = dp->overrun; . 674,677c qunlock(dp); if(dp->frame != frame){ kprint("uart%d: %d framing\n", dp-uart, dp->frame); frame = dp->frame; . 672c PUTNEXT(RD(dp->wq), bp); . 664,665c qlock(dp); if(dp->wq == 0){ . 647,648c Uart *dp = a; IOQ *cq = dp->iq; . 642c * process to send bytes dpstream for a port . 625c uartstop(dp, n); . 621c uartrts(dp, n); . 617c uartparity(dp, *(bp->rptr+1)); . 613c uartmflow(dp, n); . 609c uartbits(dp, n); . 605c uartbreak(dp, n); . 601c uartdtr(dp, n); . 597c if(n <= 0) error(Ebadctl); uartsetbaud(dp, n); . 585c cq = dp->oq; . 581c if(dp == 0){ . 577c Uart *dp = q->ptr; . 571c qunlock(dp); . 565,568c qlock(dp); kprint("uartstclose: q=0x%ux, id=%d\n", q, dp-uart); dp->wq = 0; dp->iq->putc = 0; . 563c uartdisable(dp); . 560c if(dp->special) . 558c Uart *dp = q->ptr; . 551c kproc(name, uartkproc, dp); . 548,549c if(dp->kstarted == 0){ dp->kstarted = 1; . 542,546c qlock(dp); dp->wq = WR(q); WR(q)->ptr = dp; RD(q)->ptr = dp; qunlock(dp); . 538,540c dp = &uart[s->id]; dp->iq->putc = 0; uartenable(dp); . 535c Uart *dp; . 511c * Stdpid HACK to undo a stdpid hack . 507c uartsetbaud(dp, baud); . 502,505c dp->special = 1; dp->oq = oq; dp->iq = iq; uartenable(dp); . 499c Uart *dp = &uart[port]; . 494c * set dp an uart port as something other than a stream . 489a } else { if(serial(0) < 0) print("can't turn off serial power\n"); . 484,487c if(dp == &uart[Modem]){ . 477,479c uartdtr(dp, 0); uartrts(dp, 0); dp->enabled = 0; . 471,472c dp->sticky[Format] = Bits8; uartwrreg(dp, Format, 0); . 465,466c dp->sticky[Iena] = 0; uartwrreg(dp, Iena, 0); . 463c * turn off interrdpts . 459c uartdisable(Uart *dp) . 452c dp->cts = 1; . 446,447c uartdtr(dp, 1); uartrts(dp, 1); . 440,441c dp->sticky[Iena] = Ircv | Ixmt | Irstat; uartwrreg(dp, Iena, 0); . 438c * turn on interrdpts . 435c dp->enabled = 1; . 432,433c if(dp->iq){ dp->iq->ptr = dp; . 428,430c if(dp->oq){ dp->oq->puts = uartputs; dp->oq->ptr = dp; . 426c * set dp i/o routines . 422a } else { if(serial(1) < 0) print("can't turn on serial port power\n"); . 417,420c if(dp == &uart[Modem]){ . 412c uartenable(Uart *dp) . 409c * turn on a port's interrdpts. set DTR and RTS . 400,403c for(dp = uart; dp < &uart[Nuart]; dp++){ cq = dp->iq; if(dp->wq && cangetc(cq)) wakedp(&cq->r); . 397c Uart *dp; . 393a USED(ur); for(nuart=2, j = 0; j < Nscard; nuart += scard[j].size, j++) { n = ~inb(scard[j].port); if(n == 0) continue; for(i = 0; n; i++){ if(n & 1) uartintr(&uart[nuart + i]); n >>= 1; } } } . 392a void uartintr2(Ureg *ur) { uchar i, j, nuart, n; . 376c print("weird modem interrdpt #%2.2ux\n", s); . 366c wakedp(&cq->r); . 363,364c dp->printing = 1; outb(dp->port + Data, getc(cq)); . 360c if(dp->cts && dp->printing == 0){ . 354,355c dp->cts = ch & Cts; cq = dp->oq; . 352c ch = uartrdreg(dp, Mstat); . 345c outb(dp->port + Data, ch); . 342,343c dp->printing = 0; wakedp(&cq->r); . 337,338c if(dp->cts == 0) dp->printing = 0; . 332c cq = dp->oq; . 321,322c ch = uartrdreg(dp, Data) & 0xff; cq = dp->iq; . 317c dp->overrun++; . 315c dp->frame++; . 313c l = uartrdreg(dp, Lstat); . 310c s = uartrdreg(dp, Istat); . 302c uartintr(Uart *dp) . 299c * a uart interrdpt (a damn lot of work for one character) . 290c outb(dp->port + Data, ch); . 286,287c dp->printing = 1; for(tries = 0; tries<10000 && !(uartrdreg(dp, Lstat)&Outready); . 283c if(dp->printing == 0){ . 274c Uart *dp = cq->ptr; . 259,263c uartsetbaud(dp, 9600); dp->sticky[Format] = Bits8; uartwrreg(dp, Format, 0); dp->sticky[Mctl] |= Inton; uartwrreg(dp, Mctl, 0x0); . 257c * interrdpts enabled. . 253a * mem gives base port address for uarts * irq is interrdpt * port is the polling port * size is the number of serial ports on the same polling port */ setvec(Int0vec + scard[i].irq, uartintr2); baddr = scard[i].mem; for(j=0, dp = &uart[Nuart]; j < scard[i].size; baddr += 8, j++, dp++) dp->port = baddr; Nuart += scard[i].size; } Nscard = i; for(dp = uart; dp < &uart[Nuart]; dp++){ memset(dp->sticky, 0, sizeof(dp->sticky)); /* . 249,252c Nuart = 2; for(i = 0; isaconfig("serial", i, &scard[i]) && i < nelem(scard); i++) { . 235c Uart *dp; int i, j, baddr; . 229,230c * default is 9600 baud, 1 stop bit, 8 bit chars, no interrdpts, * transmit and receive enabled, interrdpts disabled. . 221,223c dp->sticky[Iena] &= ~Imstat; uartwrreg(dp, Iena, 0); dp->cts = 1; . 217,219c dp->sticky[Iena] |= Imstat; uartwrreg(dp, Iena, 0); dp->cts = uartrdreg(dp, Mstat) & Cts; . 214c uartmflow(Uart *dp, int n) . 207c uartwrreg(dp, Format, 0); . 204c dp->sticky[Format] |= Stop2; . 200c dp->sticky[Format] &= ~Stop2; . 196c uartstop(Uart *dp, int n) . 189c uartwrreg(dp, Format, 0); . 186c dp->sticky[Format] &= ~(Pena|Peven); . 182,183c dp->sticky[Format] &= ~Peven; dp->sticky[Format] |= Pena; . 179c dp->sticky[Format] |= Pena|Peven; . 175c uartparity(Uart *dp, int c) . 166,168c dp->sticky[Format] &= ~3; dp->sticky[Format] |= bits-5; uartwrreg(dp, Format, 0); . 162c uartbits(Uart *dp, int bits) . 153,155c uartwrreg(dp, Format, Break); tsleep(&dp->sleep, return0, 0, ms); uartwrreg(dp, Format, 0); . 149c uartbreak(Uart *dp, int ms) . 141,142c dp->sticky[Mctl] &= ~Rts; uartwrreg(dp, Mctl, 0); . 139c dp->sticky[Mctl] |= Rts; . 136c uartrts(Uart *dp, int n) . 128,129c dp->sticky[Mctl] &= ~Dtr; uartwrreg(dp, Mctl, 0); . 126c dp->sticky[Mctl] |= Dtr; . 123c uartdtr(Uart *dp, int n) . 113,116c uartwrreg(dp, Format, Dra); outb(dp->port+Dmsb, (brconst>>8) & 0xff); outb(dp->port+Dlsb, brconst & 0xff); uartwrreg(dp, Format, 0); . 107c uartsetbaud(Uart *dp, int rate) . 98a void uartintr2(Ureg*); . 91c #define UartFREQ 1843200 . 89c Uart uart[34]; int Nuart; /* total no of uarts in the machine */ int Nscard; /* number of serial cards */ ISAConf scard[5]; /* configs for the serial card */ . 39c Inton= (1<<3), /* turn on interrdpts */ . 25c Istat= 2, /* interrdpt flag (read) */ . 20c Iena= 1, /* interrdpt enable */ . 10c #define nelem(x) (sizeof(x)/sizeof(x[0])) . ## diffname pc/devuart.c 1993/1124 # deleted ## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devuart.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devuart.c 1,891d