summaryrefslogtreecommitdiff
path: root/os/pxa/devuart.c
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
commit78ee7d5717807e6ac779293d0d3c78341de6130a (patch)
treea43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/pxa/devuart.c
parentbdaf46cf45bbb59261da245d548a179d95a42768 (diff)
Move existing boards into subdits split per arch
Diffstat (limited to 'os/pxa/devuart.c')
-rw-r--r--os/pxa/devuart.c1073
1 files changed, 0 insertions, 1073 deletions
diff --git a/os/pxa/devuart.c b/os/pxa/devuart.c
deleted file mode 100644
index 13b2107a..00000000
--- a/os/pxa/devuart.c
+++ /dev/null
@@ -1,1073 +0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-#include "../port/netif.h"
-
-/*
- * Driver for the uart.
- * TO DO: replace by uartpxa.c
- */
-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 */
- Rtoie= 1<<4, /* character timeout indication */
- Nrze= 1<<5, /* NRZ encoding enabled */
- Uue= 1<<6, /* Uart unit enabled */
- Dmae= 1<<7, /* DMA requests enabled */
- Istat= 2, /* interrupt flag (read) */
- Ipend= 1, /* interrupt pending (not) */
- Fenabd=(3<<6), /* on if fifo's enabled */
- Fifoctl=2, /* fifo control (write) */
- Fena= (1<<0), /* enable xmit/rcv fifos */
- Fdma= (1<<3), /* dma on */
- 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 */
- Berror=(1<<4), /* break alarm */
- 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 */
- Ringl= (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= 4, /* max per machine */
-};
-
-typedef struct Uart Uart;
-struct Uart
-{
- QLock;
- int opens;
-
- int enabled;
- Uart *elist; /* next enabled interface */
- char name[KNAMELEN];
-
- ulong sticky[8]; /* sticky write register values */
- void* regs;
- ulong port;
- ulong freq; /* clock frequency */
- uchar mask; /* bits/char */
- int dev;
- int baud; /* baud rate */
-
- uchar istat; /* last istat read */
- int frame; /* framing errors */
- int overrun; /* rcvr overruns */
-
- /* buffers */
- int (*putc)(Queue*, int);
- Queue *iq;
- Queue *oq;
-
- Lock flock; /* fifo */
- uchar fifoon; /* fifo's enabled */
- uchar nofifo; /* earlier chip version with nofifo */
-
- Lock rlock; /* receive */
- uchar istage[Stagesize];
- uchar *ip;
- uchar *ie;
-
- int haveinput;
-
- Lock tlock; /* transmit */
- uchar ostage[Stagesize];
- uchar *op;
- uchar *oe;
-
- int modem; /* hardware flow control on */
- int xonoff; /* software flow control on */
- int blocked;
- int cts, dsr, dcd; /* keep track of modem status */
- int ctsbackoff;
- int hup_dsr, hup_dcd; /* send hangup upstream? */
- int dohup;
-
- Rendez r;
-};
-
-static Uart *uart[Nuart];
-static int nuart;
-
-struct Uartalloc {
- Lock;
- Uart *elist; /* list of enabled interfaces */
-} uartalloc;
-
-static void uartintr(Uart*);
-
-/*
- * pick up architecture specific routines and definitions
- */
-#include "uart.h"
-
-/*
- * set the baud rate by calculating and setting the baudrate
- * generator constant. This will work with fairly non-standard
- * baud rates.
- */
-static void
-uartsetbaud(Uart *p, int rate)
-{
- ulong brconst;
-
- if(rate <= 0)
- return;
-
- p->freq = archuartclock(p->port, rate);
- if(p->freq == 0)
- return;
-
- brconst = (p->freq+8*rate-1)/(16*rate);
-
- uartwrreg(p, Format, Dra);
- uartwr(p, Dmsb, (brconst>>8) & 0xff);
- uartwr(p, Dlsb, brconst & 0xff);
- uartwrreg(p, Format, 0);
-
- p->baud = rate;
-}
-
-/*
- * decide if we should hangup when dsr or dcd drops.
- */
-static void
-uartdsrhup(Uart *p, int n)
-{
- p->hup_dsr = n;
-}
-
-static void
-uartdcdhup(Uart *p, int n)
-{
- p->hup_dcd = n;
-}
-
-static void
-uartparity(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
-uartbits(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
-uartdtr(Uart *p, int n)
-{
- if(n)
- p->sticky[Mctl] |= Dtr;
- else
- p->sticky[Mctl] &= ~Dtr;
-
- uartwrreg(p, Mctl, 0);
-}
-
-/*
- * toggle RTS
- */
-void
-uartrts(Uart *p, int n)
-{
- if(n)
- p->sticky[Mctl] |= Rts;
- else
- p->sticky[Mctl] &= ~Rts;
-
- uartwrreg(p, Mctl, 0);
-}
-
-/*
- * send break
- */
-static void
-uartbreak(Uart *p, int ms)
-{
- if(ms == 0)
- ms = 200;
-
- uartwrreg(p, Format, Break);
- tsleep(&up->sleep, return0, 0, ms);
- uartwrreg(p, Format, 0);
-}
-
-static void
-uartfifoon(Uart *p)
-{
- ulong i, x;
-
- if(p->nofifo || uartrdreg(p, Istat) & Fenabd)
- return;
-
- x = splhi();
-
- /* reset fifos */
- p->sticky[Fifoctl] = 0;
- uartwrreg(p, Fifoctl, Fclear);
-
- /* empty buffer and interrupt conditions */
- for(i = 0; i < 16; i++){
- if(uartrdreg(p, Istat)){
- /* nothing to do */
- }
- if(uartrdreg(p, Data)){
- /* nothing to do */
- }
- }
-
- /* turn on fifo */
- p->fifoon = 1;
- p->sticky[Fifoctl] = Fena|Ftrig;
- uartwrreg(p, Fifoctl, 0);
- p->istat = uartrdreg(p, Istat);
- 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)
- */
-static void
-uartmflow(Uart *p, int n)
-{
- ilock(&p->tlock);
- if(n){
- p->sticky[Iena] |= Imstat;
- uartwrreg(p, Iena, 0);
- p->modem = 1;
- p->cts = uartrdreg(p, Mstat) & Cts;
- } else {
- p->sticky[Iena] &= ~Imstat;
- uartwrreg(p, Iena, 0);
- p->modem = 0;
- p->cts = 1;
- }
- iunlock(&p->tlock);
-
-// ilock(&p->flock);
-// if(1)
-// /* turn on fifo's */
-// uartfifoon(p);
-// else {
-// /* turn off fifo's */
-// p->fifoon = 0;
-// p->sticky[Fifoctl] = 0;
-// uartwrreg(p, Fifoctl, Fclear);
-// }
-// iunlock(&p->flock);
-}
-
-/*
- * turn on a port's interrupts. set DTR and RTS
- */
-static void
-uartenable(Uart *p)
-{
- Uart **l;
-
- if(p->enabled)
- return;
-
- uartportpower(p, 1);
-
- p->hup_dsr = p->hup_dcd = 0;
- p->cts = p->dsr = p->dcd = 0;
-
- /*
- * turn on interrupts
- */
- p->sticky[Iena] = Ircv | Ixmt | Irstat | Uue;
- uartwrreg(p, Iena, 0);
-
- /*
- * turn on DTR and RTS
- */
- uartdtr(p, 1);
- uartrts(p, 1);
-
- uartfifoon(p);
-
- /*
- * assume we can send
- */
- ilock(&p->tlock);
- p->cts = 1;
- p->blocked = 0;
- iunlock(&p->tlock);
-
- /*
- * set baud rate to the last used
- */
- uartsetbaud(p, p->baud);
-
- 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
- */
-static void
-uartdisable(Uart *p)
-{
- Uart **l;
-
- /*
- * turn off interrupts
- */
- p->sticky[Iena] = Uue;
- 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
- */
- uartdtr(p, 0);
- uartrts(p, 0);
- uartmflow(p, 0);
- ilock(&p->tlock);
- p->xonoff = p->blocked = 0;
- iunlock(&p->tlock);
-
- uartportpower(p, 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
-uartkick0(Uart *p)
-{
- int i;
- if((p->modem && (p->cts == 0)) || p->blocked)
- return;
-
- /*
- * 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;
- if(p->op >= p->oe && stageoutput(p) == 0)
- break;
- uartwr(p, Data, *p->op++);
- }
-}
-
-static void
-uartkick(void *v)
-{
- Uart *p;
-
- p = v;
- ilock(&p->tlock);
- uartkick0(p);
- iunlock(&p->tlock);
-}
-
-/*
- * restart input if it's off
- */
-static void
-uartflow(void *v)
-{
- Uart *p;
-
- p = v;
- if(p->modem)
- uartrts(p, 1);
- ilock(&p->rlock);
- p->haveinput = 1;
- iunlock(&p->rlock);
-}
-
-/*
- * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,
- * transmit and receive enabled, interrupts disabled.
- */
-static void
-uartsetup0(Uart *p)
-{
- memset(p->sticky, 0, sizeof(p->sticky));
- /*
- * set rate to 9600 baud.
- * 8 bits/character.
- * 1 stop bit.
- * interrupts enabled.
- */
- p->sticky[Format] = Bits8;
- uartwrreg(p, Format, 0);
- p->sticky[Mctl] |= Inton;
- uartwrreg(p, Mctl, 0x0);
-
-// uartsetbaud(p, 9600);
- uartsetbaud(p, 38400);
-
- p->iq = qopen(4*1024, 0, uartflow, p);
- p->oq = qopen(4*1024, 0, uartkick, p);
- if(p->iq == nil || p->oq == nil)
- panic("uartsetup0");
-
- p->ip = p->istage;
- p->ie = &p->istage[Stagesize];
- p->op = p->ostage;
- p->oe = p->ostage;
-}
-
-/*
- * called by uartinstall() to create a new duart
- */
-void
-uartsetup(ulong port, void *regs, ulong freq, char *name)
-{
- Uart *p;
-
- if(nuart >= Nuart)
- return;
-
- p = xalloc(sizeof(Uart));
- uart[nuart] = p;
- strcpy(p->name, name);
- p->dev = nuart;
- nuart++;
- p->port = port;
- p->regs = regs;
- p->freq = freq;
- uartsetup0(p);
-}
-
-/*
- * called by main() to configure a duart port as a console or a mouse
- */
-void
-uartspecial(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int))
-{
- Uart *p = uart[port];
- uartenable(p);
- if(baud)
- uartsetbaud(p, baud);
- p->putc = putc;
- if(in)
- *in = p->iq;
- if(out)
- *out = p->oq;
- p->opens++;
-}
-
-/*
- * handle an interrupt to a single uart
- */
-static void
-uartintr(Uart *p)
-{
- uchar ch;
- int s, l;
-
- for (s = uartrdreg(p, Istat); !(s&Ipend); s = uartrdreg(p, Istat)) {
- switch(s&0x3f){
- case 4: /* received data available */
- case 6: /* receiver line status (alarm or error) */
- case 12: /* character timeout indication */
- while ((l = uartrdreg(p, Lstat)) & Inready) {
- if(l & Ferror)
- p->frame++;
- if(l & Oerror)
- p->overrun++;
- ch = uartrdreg(p, Data) & 0xff;
- if (l & (Berror|Perror|Ferror)) {
- /* ch came with break, parity or framing error - consume */
- continue;
- }
- if (ch == CTLS || ch == CTLQ) {
- ilock(&p->tlock);
- if(p->xonoff){
- if(ch == CTLS)
- p->blocked = 1;
- else
- p->blocked = 0; /* clock gets output going again */
- }
- iunlock(&p->tlock);
- }
- if(p->putc)
- p->putc(p->iq, ch);
- else {
- ilock(&p->rlock);
- if(p->ip < p->ie)
- *p->ip++ = ch;
- else
- p->overrun++;
- p->haveinput = 1;
- iunlock(&p->rlock);
- }
- }
- break;
-
- case 2: /* transmitter not full */
- uartkick(p);
- break;
-
- case 0: /* modem status */
- ch = uartrdreg(p, Mstat);
- if(ch & Ctsc){
- ilock(&p->tlock);
- l = p->cts;
- p->cts = ch & Cts;
- if(l == 0 && p->cts)
- p->ctsbackoff = 2; /* clock gets output going again */
- iunlock(&p->tlock);
- }
- 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;
- }
- break;
-
- default:
- iprint("weird uart interrupt #%2.2ux\n", s);
- break;
- }
- }
- p->istat = s;
-}
-
-/*
- * 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 something. Since it was there, I bundled a
- * restart after flow control with it to give some hysteresis
- * to the hardware flow control. This makes compressing
- * modems happier but will probably bother something else.
- * -- presotto
- */
-void
-uartclock(void)
-{
- int n;
- Uart *p;
-
- for(p = uartalloc.elist; p; p = p->elist){
-
- /* this amortizes cost of qproduce to many chars */
- if(p->haveinput){
- ilock(&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)
- uartrts(p, 0);
- else
- p->ip = p->istage;
- }
- p->haveinput = 0;
- }
- iunlock(&p->rlock);
- }
- if(p->dohup){
- ilock(&p->rlock);
- if(p->dohup){
- qhangup(p->iq, 0);
- qhangup(p->oq, 0);
- }
- p->dohup = 0;
- iunlock(&p->rlock);
- }
-
- /* this adds hysteresis to hardware flow control */
- if(p->ctsbackoff){
- ilock(&p->tlock);
- if(p->ctsbackoff){
- if(--(p->ctsbackoff) == 0)
- uartkick0(p);
- }
- iunlock(&p->tlock);
- }
- }
-}
-
-Dirtab *uartdir;
-int ndir;
-
-static void
-setlength(int i)
-{
- Uart *p;
-
- if(i >= 0){
- p = uart[i];
- if(p && p->opens && p->iq)
- uartdir[1+3*i].length = qlen(p->iq);
- } else for(i = 0; i < nuart; i++){
- p = uart[i];
- if(p && p->opens && p->iq)
- uartdir[1+3*i].length = qlen(p->iq);
- }
-}
-
-/*
- * all uarts must be uartsetup() by this point or inside of uartinstall()
- */
-static void
-uartreset(void)
-{
- int i;
- Dirtab *dp;
- uartinstall(); /* architecture specific */
-
- ndir = 1+3*nuart;
- uartdir = xalloc(ndir * sizeof(Dirtab));
- dp = uartdir;
- strcpy(dp->name, ".");
- mkqid(&dp->qid, 0, 0, QTDIR);
- dp->length = 0;
- dp->perm = DMDIR|0555;
- dp++;
- for(i = 0; i < nuart; i++){
- /* 3 directory entries per port */
- strcpy(dp->name, uart[i]->name);
- dp->qid.path = NETQID(i, Ndataqid);
- dp->perm = 0666;
- dp++;
- sprint(dp->name, "%sctl", uart[i]->name);
- dp->qid.path = NETQID(i, Nctlqid);
- dp->perm = 0666;
- dp++;
- sprint(dp->name, "%sstatus", uart[i]->name);
- dp->qid.path = NETQID(i, Nstatqid);
- dp->perm = 0444;
- dp++;
- }
-}
-
-static Chan*
-uartattach(char *spec)
-{
- return devattach('t', spec);
-}
-
-static Walkqid*
-uartwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, uartdir, ndir, devgen);
-}
-
-static int
-uartstat(Chan *c, uchar *dp, int n)
-{
- if(NETTYPE(c->qid.path) == Ndataqid)
- setlength(NETID(c->qid.path));
- return devstat(c, dp, n, uartdir, ndir, devgen);
-}
-
-static Chan*
-uartopen(Chan *c, int omode)
-{
- Uart *p;
-
- c = devopen(c, omode, uartdir, ndir, devgen);
-
- switch(NETTYPE(c->qid.path)){
- case Nctlqid:
- case Ndataqid:
- p = uart[NETID(c->qid.path)];
- qlock(p);
- if(p->opens++ == 0){
- uartenable(p);
- qreopen(p->iq);
- qreopen(p->oq);
- }
- qunlock(p);
- break;
- }
-
- return c;
-}
-
-static void
-uartclose(Chan *c)
-{
- Uart *p;
-
- if(c->qid.type & QTDIR)
- return;
- if((c->flag & COPEN) == 0)
- return;
- switch(NETTYPE(c->qid.path)){
- case Ndataqid:
- case Nctlqid:
- p = uart[NETID(c->qid.path)];
- qlock(p);
- if(--(p->opens) == 0){
- uartdisable(p);
- qclose(p->iq);
- qclose(p->oq);
- p->ip = p->istage;
- p->dcd = p->dsr = p->dohup = 0;
- }
- qunlock(p);
- break;
- }
-}
-
-static long
-uartstatus(Chan*, Uart *p, void *buf, long n, long offset)
-{
- uchar mstat, fstat, istat, tstat;
- char str[256];
-
- str[0] = 0;
- tstat = p->sticky[Mctl];
- mstat = uartrdreg(p, Mstat);
- 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",
-
- 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,
- uartrdreg(p, Istat) & Fenabd ? " fifo" : "",
- (mstat & Cts) ? " cts" : "",
- (mstat & Dsr) ? " dsr" : "",
- (mstat & Dcd) ? " dcd" : "",
- (mstat & Ringl) ? " ring" : ""
- );
- return readstr(offset, buf, n, str);
-}
-
-static long
-uartread(Chan *c, void *buf, long n, vlong off)
-{
- Uart *p;
- ulong offset = off;
-
- if(c->qid.type & QTDIR){
- setlength(-1);
- return devdirread(c, buf, n, uartdir, ndir, 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
-uartctl(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, (int(*)(void*))qlen, p->oq, 125);
-
- if(strncmp(cmd, "break", 5) == 0){
- uartbreak(p, 0);
- return;
- }
-
-
- n = atoi(cmd+1);
- switch(*cmd){
- case 'B':
- case 'b':
- uartsetbaud(p, n);
- break;
- case 'C':
- case 'c':
- uartdcdhup(p, n);
- break;
- case 'D':
- case 'd':
- uartdtr(p, n);
- break;
- case 'E':
- case 'e':
- uartdsrhup(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 'L':
- case 'l':
- uartbits(p, n);
- break;
- case 'm':
- case 'M':
- uartmflow(p, n);
- break;
- case 'n':
- case 'N':
- qnoblock(p->oq, n);
- break;
- case 'P':
- case 'p':
- uartparity(p, *(cmd+1));
- break;
- case 'K':
- case 'k':
- uartbreak(p, n);
- break;
- case 'R':
- case 'r':
- uartrts(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':
- ilock(&p->tlock);
- p->xonoff = n;
- iunlock(&p->tlock);
- break;
- }
-}
-
-static long
-uartwrite(Chan *c, void *buf, long n, vlong)
-{
- Uart *p;
- char cmd[32];
-
- if(c->qid.type & QTDIR)
- error(Eperm);
-
- p = uart[NETID(c->qid.path)];
-
- /*
- * The fifo's turn themselves off sometimes.
- * It must be something I don't understand. -- presotto
- */
- lock(&p->flock);
- if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0)
- uartfifoon(p);
- unlock(&p->flock);
-
- 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;
- uartctl(p, cmd);
- return n;
- default:
- error(Egreg);
- return n;
- }
-}
-
-static int
-uartwstat(Chan *c, uchar *dp, int n)
-{
- Dir d;
- Dirtab *dt;
-
- if(!iseve())
- error(Eperm);
- if(c->qid.type & QTDIR)
- error(Eperm);
- if(NETTYPE(c->qid.path) == Nstatqid)
- error(Eperm);
-
- dt = &uartdir[1+3 * NETID(c->qid.path)];
- n = convM2D(dp, n, &d, nil);
- if(n == 0)
- error(Eshortstat);
- if(d.mode != ~0UL){
- d.mode &= 0666;
- dt[0].perm = dt[1].perm = d.mode;
- }
- return n;
-}
-
-Dev uartdevtab = {
- 't',
- "uart",
-
- uartreset,
- devinit,
- devshutdown,
- uartattach,
- uartwalk,
- uartstat,
- uartopen,
- devcreate,
- uartclose,
- uartread,
- devbread,
- uartwrite,
- devbwrite,
- devremove,
- uartwstat,
-};