2 #include "../port/lib.h"
7 #include "../port/error.h"
9 #include "../port/netif.h"
13 /* soft flow control chars */
18 extern Dev uartdevtab;
19 extern PhysUart* physuart[];
21 static Uart* uartlist;
24 static Dirtab *uartdir;
26 static Timer *uarttimer;
30 Uart *elist; /* list of enabled interfaces */
33 static void uartclock(void);
34 static void uartflow(void*);
37 * enable/disable uart and add/remove to list of enabled uarts
47 if((p->iq = qopen(8*1024, Qcoalesce, uartflow, p)) == nil)
53 if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
64 p->ie = &p->istage[Stagesize];
68 p->hup_dsr = p->hup_dcd = 0;
71 /* assume we can send */
83 (*p->phys->enable)(p, 1);
86 * use ilock because uartclock can otherwise interrupt here
87 * and would hang on an attempt to lock uartalloc.
90 for(l = &uartalloc.elist; *l; l = &(*l)->elist){
95 p->elist = uartalloc.elist;
111 (*p->phys->disable)(p);
114 for(l = &uartalloc.elist; *l; l = &(*l)->elist){
125 uartport(char *which)
130 port = strtol(which, &p, 0);
133 if(port < 0 || port >= uartnuart || uart[port] == nil)
139 uartmouse(char *which, int (*putc)(Queue*, int), int setb1200)
145 if(p->opens++ == 0 && uartenable(p) == nil){
157 uartsetmouseputc(char *which, int (*putc)(Queue*, int))
163 if(p->opens == 0 || p->special == 0){
178 if(p && p->opens && p->iq)
179 uartdir[1+3*i].length = qlen(p->iq);
180 } else for(i = 0; i < uartnuart; i++){
182 if(p && p->opens && p->iq)
183 uartdir[1+3*i].length = qlen(p->iq);
188 * set up the '#t' directory
198 for(i = 0; physuart[i] != nil; i++){
199 if(physuart[i]->pnp == nil)
201 if((p = physuart[i]->pnp()) == nil)
207 for(tail = p; tail->next != nil; tail = tail->next)
213 uart = xalloc(uartnuart*sizeof(Uart*));
215 uartndir = 1 + 3*uartnuart;
216 uartdir = xalloc(uartndir * sizeof(Dirtab));
217 if(uartnuart && uart == nil || uartdir == nil)
218 panic("uartreset: no memory");
220 strcpy(dp->name, ".");
221 mkqid(&dp->qid, 0, 0, QTDIR);
223 dp->perm = DMDIR|0555;
226 for(i = 0; i < uartnuart; i++){
227 /* 3 directory entries per port */
228 snprint(dp->name, sizeof dp->name, "eia%d", i);
229 dp->qid.path = NETQID(i, Ndataqid);
232 snprint(dp->name, sizeof dp->name, "eia%dctl", i);
233 dp->qid.path = NETQID(i, Nctlqid);
236 snprint(dp->name, sizeof dp->name, "eia%dstatus", i);
237 dp->qid.path = NETQID(i, Nstatqid);
243 if(p->console || p->special){
244 if(uartenable(p) != nil){
256 * at 115200 baud, the 1024 char buffer takes 56 ms to process,
257 * processing it every 22 ms should be fine.
259 uarttimer = addclock0link(uartclock, 22);
265 uartattach(char *spec)
267 return devattach('t', spec);
271 uartwalk(Chan *c, Chan *nc, char **name, int nname)
273 return devwalk(c, nc, name, nname, uartdir, uartndir, devgen);
277 uartstat(Chan *c, uchar *dp, int n)
279 if(NETTYPE(c->qid.path) == Ndataqid)
280 setlength(NETID(c->qid.path));
281 return devstat(c, dp, n, uartdir, uartndir, devgen);
285 uartopen(Chan *c, int omode)
289 c = devopen(c, omode, uartdir, uartndir, devgen);
291 switch(NETTYPE(c->qid.path)){
294 p = uart[NETID(c->qid.path)];
296 if(p->opens++ == 0 && uartenable(p) == nil){
305 c->iounit = qiomaxatomic;
310 uartdrained(void* arg)
315 return qlen(p->oq) == 0 && p->op == p->oe;
319 uartdrainoutput(Uart *p)
321 if(!p->enabled || up == nil || !islo())
328 sleep(&p->r, uartdrained, p);
337 if(c->qid.type & QTDIR)
339 if((c->flag & COPEN) == 0)
341 switch(NETTYPE(c->qid.path)){
344 p = uart[NETID(c->qid.path)];
346 if(--(p->opens) == 0){
349 p->ir = p->iw = p->istage;
361 p->dcd = p->dsr = p->dohup = 0;
369 uartread(Chan *c, void *buf, long n, vlong off)
374 if(c->qid.type & QTDIR){
376 return devdirread(c, buf, n, uartdir, uartndir, devgen);
379 p = uart[NETID(c->qid.path)];
380 switch(NETTYPE(c->qid.path)){
382 return qread(p->iq, buf, n);
384 return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
386 return (*p->phys->status)(p, buf, n, offset);
393 uartctl(Uart *p, char *cmd)
398 nf = tokenize(cmd, f, nelem(f));
399 for(i = 0; i < nf; i++){
400 if(strncmp(f[i], "break", 5) == 0){
401 (*p->phys->dobreak)(p, 0);
410 if((*p->phys->baud)(p, n) < 0)
420 (*p->phys->dtr)(p, n);
441 (*p->phys->fifo)(p, n);
446 (*p->phys->dobreak)(p, n);
451 if((*p->phys->bits)(p, n) < 0)
457 (*p->phys->modemctl)(p, n);
467 if((*p->phys->parity)(p, *(f[i]+1)) < 0)
480 (*p->phys->rts)(p, n);
485 if((*p->phys->stop)(p, n) < 0)
490 if(uarttimer == nil || n < 1)
492 uarttimer->tns = (vlong)n * 100000LL;
507 uartwrite(Chan *c, void *buf, long n, vlong)
512 if(c->qid.type & QTDIR)
515 p = uart[NETID(c->qid.path)];
517 switch(NETTYPE(c->qid.path)){
525 n = qwrite(p->oq, buf, n);
532 memmove(cmd, buf, n);
541 /* let output drain */
542 if(uartctl(p, cmd) < 0)
555 uartwstat(Chan *c, uchar *dp, int n)
562 if(QTDIR & c->qid.type)
564 if(NETTYPE(c->qid.path) == Nstatqid)
567 dt = &uartdir[1 + 3 * NETID(c->qid.path)];
568 n = convM2D(dp, n, &d, nil);
572 dt[0].perm = dt[1].perm = d.mode;
581 for(p = uartlist; p != nil; p = p->next) {
583 (*p->phys->power)(p, on);
610 * restart input if it's off
619 (*p->phys->rts)(p, 1);
623 * put some bytes into the local queue to avoid calling
624 * qconsume for every character
627 uartstageoutput(Uart *p)
631 n = qconsume(p->oq, p->ostage, Stagesize);
635 p->oe = p->ostage + n;
647 if(!p->enabled || p->blocked)
654 if(p->drain && uartdrained(p)){
661 * Move data from the interrupt staging area to
665 uartstageinput(Uart *p)
670 while(p->ir != p->iw){
680 if((n = qproduce(p->iq, ir, iw - ir)) < 0){
682 (*p->phys->rts)(p, 0);
690 * receive a character at interrupt time
693 uartrecv(Uart *p, char ch)
697 /* software flow control */
701 }else if(ch == CTLQ){
703 p->ctsbackoff = 2; /* clock gets output going again */
707 /* receive the character */
710 else if (p->iw) { /* maybe the line isn't enabled yet */
726 * we save up input characters till clock time to reduce
727 * per character interrupt overhead.
735 for(p = uartalloc.elist; p; p = p->elist){
737 /* this hopefully amortizes cost of qproduce to many chars */
744 /* hang up if requested */
751 /* this adds hysteresis to hardware/software flow control */
755 if(--(p->ctsbackoff) == 0)
765 * polling console input, output
773 if(consuart == nil || consuart->phys->getc == nil)
775 return consuart->phys->getc(consuart);
781 if(consuart == nil || consuart->phys->putc == nil)
783 consuart->phys->putc(consuart, c);
787 uartputs(char *s, int n)
791 if(consuart == nil || consuart->phys->putc == nil)
797 consuart->phys->putc(consuart, '\r');
798 consuart->phys->putc(consuart, *s);