## 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 <schwartz@bio.cse.psu.edu> */
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
|