1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8
9 #include "../port/netif.h"
10
11 enum
12 {
13 /* soft flow control chars */
14 CTLS= 023,
15 CTLQ= 021,
16 };
17
18 extern Dev uartdevtab;
19 extern PhysUart* physuart[];
20
21 static Uart* uartlist;
22 static Uart** uart;
23 static int uartnuart;
24 static Dirtab *uartdir;
25 static int uartndir;
26 static Timer *uarttimer;
27
28 struct Uartalloc {
29 Lock;
30 Uart *elist; /* list of enabled interfaces */
31 } uartalloc;
32
33 static void uartclock(void);
34 static void uartflow(void*);
35
36 /*
37 * enable/disable uart and add/remove to list of enabled uarts
38 */
39 //static
40 Uart*
uartenable(Uart * p)41 uartenable(Uart *p)
42 {
43 Uart **l;
44
45 if (up == nil)
46 return p; /* too soon; try again later */
47 // return nil;
48
49 if(p->iq == nil){
50 if((p->iq = qopen(8*1024, 0, uartflow, p)) == nil)
51 return nil;
52 }
53 else
54 qreopen(p->iq);
55 if(p->oq == nil){
56 if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
57 qfree(p->iq);
58 p->iq = nil;
59 return nil;
60 }
61 }
62 else
63 qreopen(p->oq);
64
65 p->ir = p->istage;
66 p->iw = p->istage;
67 p->ie = &p->istage[Stagesize];
68 p->op = p->ostage;
69 p->oe = p->ostage;
70
71 p->hup_dsr = p->hup_dcd = 0;
72 p->dsr = p->dcd = 0;
73
74 /* assume we can send */
75 p->cts = 1;
76 p->ctsbackoff = 0;
77
78 if (up) {
79 if(p->bits == 0)
80 uartctl(p, "l8");
81 if(p->stop == 0)
82 uartctl(p, "s1");
83 if(p->parity == 0)
84 uartctl(p, "pn");
85 if(p->baud == 0)
86 uartctl(p, "b9600");
87 (*p->phys->enable)(p, 1);
88 }
89
90 /*
91 * use ilock because uartclock can otherwise interrupt here
92 * and would hang on an attempt to lock uartalloc.
93 */
94 ilock(&uartalloc);
95 for(l = &uartalloc.elist; *l; l = &(*l)->elist){
96 if(*l == p)
97 break;
98 }
99 if(*l == 0){
100 p->elist = uartalloc.elist;
101 uartalloc.elist = p;
102 }
103 p->enabled = 1;
104 iunlock(&uartalloc);
105
106 return p;
107 }
108
109 static void
uartdisable(Uart * p)110 uartdisable(Uart *p)
111 {
112 Uart **l;
113
114 (*p->phys->disable)(p);
115
116 ilock(&uartalloc);
117 for(l = &uartalloc.elist; *l; l = &(*l)->elist){
118 if(*l == p){
119 *l = p->elist;
120 break;
121 }
122 }
123 p->enabled = 0;
124 iunlock(&uartalloc);
125 }
126
127 void
uartmouse(Uart * p,int (* putc)(Queue *,int),int setb1200)128 uartmouse(Uart* p, int (*putc)(Queue*, int), int setb1200)
129 {
130 qlock(p);
131 if(p->opens++ == 0 && uartenable(p) == nil){
132 qunlock(p);
133 error(Enodev);
134 }
135 if(setb1200)
136 uartctl(p, "b1200");
137 p->putc = putc;
138 p->special = 1;
139 qunlock(p);
140 }
141
142 void
uartsetmouseputc(Uart * p,int (* putc)(Queue *,int))143 uartsetmouseputc(Uart* p, int (*putc)(Queue*, int))
144 {
145 qlock(p);
146 if(p->opens == 0 || p->special == 0){
147 qunlock(p);
148 error(Enodev);
149 }
150 p->putc = putc;
151 qunlock(p);
152 }
153
154 static void
setlength(int i)155 setlength(int i)
156 {
157 Uart *p;
158
159 if(i > 0){
160 p = uart[i];
161 if(p && p->opens && p->iq)
162 uartdir[1+3*i].length = qlen(p->iq);
163 } else for(i = 0; i < uartnuart; i++){
164 p = uart[i];
165 if(p && p->opens && p->iq)
166 uartdir[1+3*i].length = qlen(p->iq);
167 }
168 }
169
170 /*
171 * set up the '#t' directory
172 */
173 static void
uartreset(void)174 uartreset(void)
175 {
176 int i;
177 Dirtab *dp;
178 Uart *p, *tail;
179
180 tail = nil;
181 for(i = 0; physuart[i] != nil; i++){
182 if(physuart[i]->pnp == nil)
183 continue;
184 if((p = physuart[i]->pnp()) == nil)
185 continue;
186 if(uartlist != nil)
187 tail->next = p;
188 else
189 uartlist = p;
190 for(tail = p; tail->next != nil; tail = tail->next)
191 uartnuart++;
192 uartnuart++;
193 }
194
195 if(uartnuart)
196 uart = xalloc(uartnuart*sizeof(Uart*));
197
198 uartndir = 1 + 3*uartnuart;
199 uartdir = xalloc(uartndir * sizeof(Dirtab));
200 if (uart == nil || uartdir == nil)
201 panic("uartreset: no memory");
202 dp = uartdir;
203 strcpy(dp->name, ".");
204 mkqid(&dp->qid, 0, 0, QTDIR);
205 dp->length = 0;
206 dp->perm = DMDIR|0555;
207 dp++;
208 p = uartlist;
209 for(i = 0; i < uartnuart; i++){
210 /* 3 directory entries per port */
211 snprint(dp->name, sizeof dp->name, "eia%d", i);
212 dp->qid.path = NETQID(i, Ndataqid);
213 dp->perm = 0660;
214 dp++;
215 snprint(dp->name, sizeof dp->name, "eia%dctl", i);
216 dp->qid.path = NETQID(i, Nctlqid);
217 dp->perm = 0660;
218 dp++;
219 snprint(dp->name, sizeof dp->name, "eia%dstatus", i);
220 dp->qid.path = NETQID(i, Nstatqid);
221 dp->perm = 0444;
222 dp++;
223
224 uart[i] = p;
225 p->dev = i;
226 if(p->console || p->special){
227 if(uartenable(p) != nil){
228 if(p->console && up){
229 kbdq = p->iq;
230 serialoq = p->oq;
231 p->putc = kbdcr2nl;
232 }
233 p->opens++;
234 }
235 }
236 p = p->next;
237 }
238
239 if(uartnuart){
240 /*
241 * at 115200 baud, the 1024 char buffer takes 56 ms to process,
242 * processing it every 22 ms should be fine.
243 */
244 uarttimer = addclock0link(uartclock, 22);
245 }
246 }
247
248
249 static Chan*
uartattach(char * spec)250 uartattach(char *spec)
251 {
252 return devattach('t', spec);
253 }
254
255 static Walkqid*
uartwalk(Chan * c,Chan * nc,char ** name,int nname)256 uartwalk(Chan *c, Chan *nc, char **name, int nname)
257 {
258 return devwalk(c, nc, name, nname, uartdir, uartndir, devgen);
259 }
260
261 static int
uartstat(Chan * c,uchar * dp,int n)262 uartstat(Chan *c, uchar *dp, int n)
263 {
264 if(NETTYPE(c->qid.path) == Ndataqid)
265 setlength(NETID(c->qid.path));
266 return devstat(c, dp, n, uartdir, uartndir, devgen);
267 }
268
269 static Chan*
uartopen(Chan * c,int omode)270 uartopen(Chan *c, int omode)
271 {
272 Uart *p;
273
274 c = devopen(c, omode, uartdir, uartndir, devgen);
275
276 switch(NETTYPE(c->qid.path)){
277 case Nctlqid:
278 case Ndataqid:
279 p = uart[NETID(c->qid.path)];
280 qlock(p);
281 if(p->opens++ == 0 && uartenable(p) == nil){
282 qunlock(p);
283 c->flag &= ~COPEN;
284 error(Enodev);
285 }
286 qunlock(p);
287 break;
288 }
289
290 c->iounit = qiomaxatomic;
291 return c;
292 }
293
294 static int
uartdrained(void * arg)295 uartdrained(void* arg)
296 {
297 Uart *p;
298
299 p = arg;
300 return qlen(p->oq) == 0 && p->op == p->oe;
301 }
302
303 static void
uartdrainoutput(Uart * p)304 uartdrainoutput(Uart *p)
305 {
306 if(!p->enabled || up == nil)
307 return;
308
309 p->drain = 1;
310 if(waserror()){
311 p->drain = 0;
312 nexterror();
313 }
314 sleep(&p->r, uartdrained, p);
315 poperror();
316 }
317
318 static void
uartclose(Chan * c)319 uartclose(Chan *c)
320 {
321 Uart *p;
322
323 if(c->qid.type & QTDIR)
324 return;
325 if((c->flag & COPEN) == 0)
326 return;
327 switch(NETTYPE(c->qid.path)){
328 case Ndataqid:
329 case Nctlqid:
330 p = uart[NETID(c->qid.path)];
331 qlock(p);
332 if(--(p->opens) == 0){
333 qclose(p->iq);
334 ilock(&p->rlock);
335 p->ir = p->iw = p->istage;
336 iunlock(&p->rlock);
337
338 /*
339 */
340 qhangup(p->oq, nil);
341 if(!waserror()){
342 uartdrainoutput(p);
343 poperror();
344 }
345 qclose(p->oq);
346 uartdisable(p);
347 p->dcd = p->dsr = p->dohup = 0;
348 }
349 qunlock(p);
350 break;
351 }
352 }
353
354 static long
uartread(Chan * c,void * buf,long n,vlong off)355 uartread(Chan *c, void *buf, long n, vlong off)
356 {
357 Uart *p;
358 ulong offset = off;
359
360 if(c->qid.type & QTDIR){
361 setlength(-1);
362 return devdirread(c, buf, n, uartdir, uartndir, devgen);
363 }
364
365 p = uart[NETID(c->qid.path)];
366 switch(NETTYPE(c->qid.path)){
367 case Ndataqid:
368 return qread(p->iq, buf, n);
369 case Nctlqid:
370 return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
371 case Nstatqid:
372 return (*p->phys->status)(p, buf, n, offset);
373 }
374
375 return 0;
376 }
377
378 int
uartctl(Uart * p,char * cmd)379 uartctl(Uart *p, char *cmd)
380 {
381 char *f[16];
382 int i, n, nf;
383
384 nf = tokenize(cmd, f, nelem(f));
385 for(i = 0; i < nf; i++){
386 if(strncmp(f[i], "break", 5) == 0){
387 (*p->phys->dobreak)(p, 0);
388 continue;
389 }
390
391 n = atoi(f[i]+1);
392 switch(*f[i]){
393 case 'B':
394 case 'b':
395 uartdrainoutput(p);
396 if((*p->phys->baud)(p, n) < 0)
397 return -1;
398 break;
399 case 'C':
400 case 'c':
401 p->hup_dcd = n;
402 break;
403 case 'D':
404 case 'd':
405 uartdrainoutput(p);
406 (*p->phys->dtr)(p, n);
407 break;
408 case 'E':
409 case 'e':
410 p->hup_dsr = n;
411 break;
412 case 'f':
413 case 'F':
414 if(p->oq != nil)
415 qflush(p->oq);
416 break;
417 case 'H':
418 case 'h':
419 if(p->iq != nil)
420 qhangup(p->iq, 0);
421 if(p->oq != nil)
422 qhangup(p->oq, 0);
423 break;
424 case 'i':
425 case 'I':
426 uartdrainoutput(p);
427 (*p->phys->fifo)(p, n);
428 break;
429 case 'K':
430 case 'k':
431 uartdrainoutput(p);
432 (*p->phys->dobreak)(p, n);
433 break;
434 case 'L':
435 case 'l':
436 uartdrainoutput(p);
437 if((*p->phys->bits)(p, n) < 0)
438 return -1;
439 break;
440 case 'm':
441 case 'M':
442 uartdrainoutput(p);
443 (*p->phys->modemctl)(p, n);
444 break;
445 case 'n':
446 case 'N':
447 if(p->oq != nil)
448 qnoblock(p->oq, n);
449 break;
450 case 'P':
451 case 'p':
452 uartdrainoutput(p);
453 if((*p->phys->parity)(p, *(f[i]+1)) < 0)
454 return -1;
455 break;
456 case 'Q':
457 case 'q':
458 if(p->iq != nil)
459 qsetlimit(p->iq, n);
460 if(p->oq != nil)
461 qsetlimit(p->oq, n);
462 break;
463 case 'R':
464 case 'r':
465 uartdrainoutput(p);
466 (*p->phys->rts)(p, n);
467 break;
468 case 'S':
469 case 's':
470 uartdrainoutput(p);
471 if((*p->phys->stop)(p, n) < 0)
472 return -1;
473 break;
474 case 'W':
475 case 'w':
476 if(uarttimer == nil || n < 1)
477 return -1;
478 uarttimer->tns = (vlong)n * 100000LL;
479 break;
480 case 'X':
481 case 'x':
482 if(p->enabled){
483 ilock(&p->tlock);
484 p->xonoff = n;
485 iunlock(&p->tlock);
486 }
487 break;
488 }
489 }
490 return 0;
491 }
492
493 static long
uartwrite(Chan * c,void * buf,long n,vlong)494 uartwrite(Chan *c, void *buf, long n, vlong)
495 {
496 Uart *p;
497 char *cmd;
498
499 if(c->qid.type & QTDIR)
500 error(Eperm);
501
502 p = uart[NETID(c->qid.path)];
503
504 switch(NETTYPE(c->qid.path)){
505 case Ndataqid:
506 qlock(p);
507 if(waserror()){
508 qunlock(p);
509 nexterror();
510 }
511
512 n = qwrite(p->oq, buf, n);
513
514 qunlock(p);
515 poperror();
516 break;
517 case Nctlqid:
518 cmd = malloc(n+1);
519 memmove(cmd, buf, n);
520 cmd[n] = 0;
521 qlock(p);
522 if(waserror()){
523 qunlock(p);
524 free(cmd);
525 nexterror();
526 }
527
528 /* let output drain */
529 if(uartctl(p, cmd) < 0)
530 error(Ebadarg);
531
532 qunlock(p);
533 poperror();
534 free(cmd);
535 break;
536 }
537
538 return n;
539 }
540
541 static int
uartwstat(Chan * c,uchar * dp,int n)542 uartwstat(Chan *c, uchar *dp, int n)
543 {
544 Dir d;
545 Dirtab *dt;
546
547 if(!iseve())
548 error(Eperm);
549 if(QTDIR & c->qid.type)
550 error(Eperm);
551 if(NETTYPE(c->qid.path) == Nstatqid)
552 error(Eperm);
553
554 dt = &uartdir[1 + 3 * NETID(c->qid.path)];
555 n = convM2D(dp, n, &d, nil);
556 if(n == 0)
557 error(Eshortstat);
558 if(d.mode != ~0UL)
559 dt[0].perm = dt[1].perm = d.mode;
560 return n;
561 }
562
563 void
uartpower(int on)564 uartpower(int on)
565 {
566 Uart *p;
567
568 for(p = uartlist; p != nil; p = p->next) {
569 if(p->phys->power)
570 (*p->phys->power)(p, on);
571 }
572 }
573
574 Dev uartdevtab = {
575 't',
576 "uart",
577
578 uartreset,
579 devinit,
580 devshutdown,
581 uartattach,
582 uartwalk,
583 uartstat,
584 uartopen,
585 devcreate,
586 uartclose,
587 uartread,
588 devbread,
589 uartwrite,
590 devbwrite,
591 devremove,
592 uartwstat,
593 uartpower,
594 };
595
596 /*
597 * restart input if it's off
598 */
599 static void
uartflow(void * v)600 uartflow(void *v)
601 {
602 Uart *p;
603
604 p = v;
605 if(p->modem)
606 (*p->phys->rts)(p, 1);
607 }
608
609 /*
610 * put some bytes into the local queue to avoid calling
611 * qconsume for every character
612 */
613 int
uartstageoutput(Uart * p)614 uartstageoutput(Uart *p)
615 {
616 int n;
617
618 n = qconsume(p->oq, p->ostage, Stagesize);
619 if(n <= 0)
620 // n = 0; /* experiment */
621 return 0;
622 p->op = p->ostage;
623 p->oe = p->ostage + n;
624 return n;
625 }
626
627 /*
628 * restart output
629 */
630 void
uartkick(void * v)631 uartkick(void *v)
632 {
633 Uart *p = v;
634
635 if(p->blocked)
636 return;
637
638 ilock(&p->tlock);
639 (*p->phys->kick)(p);
640 iunlock(&p->tlock);
641
642 if(p->drain && uartdrained(p)){
643 p->drain = 0;
644 wakeup(&p->r);
645 }
646 }
647
648 /*
649 * Move data from the interrupt staging area to
650 * the input Queue.
651 */
652 static void
uartstageinput(Uart * p)653 uartstageinput(Uart *p)
654 {
655 int n;
656 uchar *ir, *iw;
657
658 while(p->ir != p->iw){
659 ir = p->ir;
660 if(p->ir > p->iw){
661 iw = p->ie;
662 p->ir = p->istage;
663 }
664 else{
665 iw = p->iw;
666 p->ir = p->iw;
667 }
668 if((n = qproduce(p->iq, ir, iw - ir)) < 0){
669 p->serr++;
670 (*p->phys->rts)(p, 0);
671 }
672 else if(n == 0)
673 p->berr++;
674 }
675 }
676
677 /*
678 * receive a character at interrupt time
679 */
680 void
uartrecv(Uart * p,char ch)681 uartrecv(Uart *p, char ch)
682 {
683 uchar *next;
684
685 /* software flow control */
686 if(p->xonoff){
687 if(ch == CTLS){
688 p->blocked = 1;
689 }else if(ch == CTLQ){
690 p->blocked = 0;
691 p->ctsbackoff = 2; /* clock gets output going again */
692 }
693 }
694
695 /* receive the character */
696 if(p->putc)
697 p->putc(p->iq, ch);
698 else if (p->iw) { /* maybe the line isn't enabled yet */
699 ilock(&p->rlock);
700 next = p->iw + 1;
701 if(next == p->ie)
702 next = p->istage;
703 if(next == p->ir)
704 uartstageinput(p);
705 if(next != p->ir){
706 *p->iw = ch;
707 p->iw = next;
708 }
709 iunlock(&p->rlock);
710 }
711 }
712
713 /*
714 * we save up input characters till clock time to reduce
715 * per character interrupt overhead.
716 */
717 static void
uartclock(void)718 uartclock(void)
719 {
720 Uart *p;
721
722 ilock(&uartalloc);
723 for(p = uartalloc.elist; p; p = p->elist){
724
725 /* this hopefully amortizes cost of qproduce to many chars */
726 if(p->iw != p->ir){
727 ilock(&p->rlock);
728 uartstageinput(p);
729 iunlock(&p->rlock);
730 }
731
732 /* hang up if requested */
733 if(p->dohup){
734 qhangup(p->iq, 0);
735 qhangup(p->oq, 0);
736 p->dohup = 0;
737 }
738
739 /* this adds hysteresis to hardware/software flow control */
740 if(p->ctsbackoff){
741 ilock(&p->tlock);
742 if(p->ctsbackoff){
743 if(--(p->ctsbackoff) == 0)
744 (*p->phys->kick)(p);
745 }
746 iunlock(&p->tlock);
747 }
748 uartkick(p); /* keep it moving */
749 }
750 iunlock(&uartalloc);
751 }
752
753 /*
754 * polling console input, output
755 */
756
757 Uart* consuart;
758
759 int
uartgetc(void)760 uartgetc(void)
761 {
762 if(consuart == nil || consuart->phys->getc == nil)
763 return -1;
764 return consuart->phys->getc(consuart);
765 }
766
767 void
uartputc(int c)768 uartputc(int c)
769 {
770 char c2;
771
772 if(consuart == nil || consuart->phys->putc == nil) {
773 c2 = c;
774 if (lprint)
775 (*lprint)(&c2, 1);
776 return;
777 }
778 consuart->phys->putc(consuart, c);
779 }
780
781 void
uartputs(char * s,int n)782 uartputs(char *s, int n)
783 {
784 char *e;
785
786 if(consuart == nil || consuart->phys->putc == nil) {
787 if (lprint)
788 (*lprint)(s, n);
789 return;
790 }
791
792 e = s+n;
793 for(; s<e; s++){
794 if(*s == '\n')
795 consuart->phys->putc(consuart, '\r');
796 consuart->phys->putc(consuart, *s);
797 }
798 }
799