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