## 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("<start %2.2ux>", 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("<cont %2.2ux>", 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("<put %2.2ux>", 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("<get %2.2ux>", 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
|