diff options
| author | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
|---|---|---|
| committer | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
| commit | 78ee7d5717807e6ac779293d0d3c78341de6130a (patch) | |
| tree | a43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/pxa/devuart.c | |
| parent | bdaf46cf45bbb59261da245d548a179d95a42768 (diff) | |
Move existing boards into subdits split per arch
Diffstat (limited to 'os/pxa/devuart.c')
| -rw-r--r-- | os/pxa/devuart.c | 1073 |
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, -}; |
