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 Uart*
uartenable(Uart * p)40 uartenable(Uart *p)
41 {
42 Uart **l;
43
44 if(p->enabled)
45 return p;
46 if(p->iq == nil){
47 if((p->iq = qopen(8*1024, 0, uartflow, p)) == nil)
48 return nil;
49 }
50 else
51 qreopen(p->iq);
52 if(p->oq == nil){
53 if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
54 qfree(p->iq);
55 p->iq = nil;
56 return nil;
57 }
58 }
59 else
60 qreopen(p->oq);
61
62 p->ir = p->istage;
63 p->iw = p->istage;
64 p->ie = &p->istage[Stagesize];
65 p->op = p->ostage;
66 p->oe = p->ostage;
67
68 p->hup_dsr = p->hup_dcd = 0;
69 p->dsr = p->dcd = 0;
70
71 /* assume we can send */
72 p->cts = 1;
73 p->ctsbackoff = 0;
74
75 if(p->bits == 0)
76 uartctl(p, "l8");
77 if(p->stop == 0)
78 uartctl(p, "s1");
79 if(p->parity == 0)
80 uartctl(p, "pn");
81 if(p->baud == 0)
82 uartctl(p, "b9600");
83 (*p->phys->enable)(p, 1);
84
85 /*
86 * use ilock because uartclock can otherwise interrupt here
87 * and would hang on an attempt to lock uartalloc.
88 */
89 ilock(&uartalloc);
90 for(l = &uartalloc.elist; *l; l = &(*l)->elist){
91 if(*l == p)
92 break;
93 }
94 if(*l == 0){
95 p->elist = uartalloc.elist;
96 uartalloc.elist = p;
97 }
98 p->enabled = 1;
99 iunlock(&uartalloc);
100
101 return p;
102 }
103
104 static void
uartdisable(Uart * p)105 uartdisable(Uart *p)
106 {
107 Uart **l;
108
109 if(!p->enabled)
110 return;
111 (*p->phys->disable)(p);
112
113 ilock(&uartalloc);
114 for(l = &uartalloc.elist; *l; l = &(*l)->elist){
115 if(*l == p){
116 *l = p->elist;
117 break;
118 }
119 }
120 p->enabled = 0;
121 iunlock(&uartalloc);
122 }
123
124 void
uartmouse(Uart * p,int (* putc)(Queue *,int),int setb1200)125 uartmouse(Uart* p, int (*putc)(Queue*, int), int setb1200)
126 {
127 qlock(p);
128 if(p->opens++ == 0 && uartenable(p) == nil){
129 qunlock(p);
130 error(Enodev);
131 }
132 if(setb1200)
133 uartctl(p, "b1200");
134 p->putc = putc;
135 p->special = 1;
136 qunlock(p);
137 }
138
139 void
uartsetmouseputc(Uart * p,int (* putc)(Queue *,int))140 uartsetmouseputc(Uart* p, int (*putc)(Queue*, int))
141 {
142 qlock(p);
143 if(p->opens == 0 || p->special == 0){
144 qunlock(p);
145 error(Enodev);
146 }
147 p->putc = putc;
148 qunlock(p);
149 }
150
151 static void
setlength(int i)152 setlength(int i)
153 {
154 Uart *p;
155
156 if(i > 0){
157 p = uart[i];
158 if(p && p->opens && p->iq)
159 uartdir[1+3*i].length = qlen(p->iq);
160 } else for(i = 0; i < uartnuart; i++){
161 p = uart[i];
162 if(p && p->opens && p->iq)
163 uartdir[1+3*i].length = qlen(p->iq);
164 }
165 }
166
167 /*
168 * set up the '#t' directory
169 */
170 static void
uartreset(void)171 uartreset(void)
172 {
173 int i;
174 Dirtab *dp;
175 Uart *p, *tail;
176
177 tail = nil;
178 for(i = 0; physuart[i] != nil; i++){
179 if(physuart[i]->pnp == nil)
180 continue;
181 if((p = physuart[i]->pnp()) == nil)
182 continue;
183 if(uartlist != nil)
184 tail->next = p;
185 else
186 uartlist = p;
187 for(tail = p; tail->next != nil; tail = tail->next)
188 uartnuart++;
189 uartnuart++;
190 }
191
192 if(uartnuart) {
193 uart = xalloc(uartnuart*sizeof(Uart*));
194 if (uart == nil)
195 panic("uartreset: no memory");
196 }
197
198 uartndir = 1 + 3*uartnuart;
199 uartdir = xalloc(uartndir * sizeof(Dirtab));
200 if (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){
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)
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 if(cmd == nil)
520 error(Enomem);
521 memmove(cmd, buf, n);
522 cmd[n] = 0;
523 qlock(p);
524 if(waserror()){
525 qunlock(p);
526 free(cmd);
527 nexterror();
528 }
529
530 /* let output drain */
531 if(uartctl(p, cmd) < 0)
532 error(Ebadarg);
533
534 qunlock(p);
535 poperror();
536 free(cmd);
537 break;
538 }
539
540 return n;
541 }
542
543 static int
uartwstat(Chan * c,uchar * dp,int n)544 uartwstat(Chan *c, uchar *dp, int n)
545 {
546 Dir d;
547 Dirtab *dt;
548
549 if(!iseve())
550 error(Eperm);
551 if(QTDIR & c->qid.type)
552 error(Eperm);
553 if(NETTYPE(c->qid.path) == Nstatqid)
554 error(Eperm);
555
556 dt = &uartdir[1 + 3 * NETID(c->qid.path)];
557 n = convM2D(dp, n, &d, nil);
558 if(n == 0)
559 error(Eshortstat);
560 if(d.mode != ~0UL)
561 dt[0].perm = dt[1].perm = d.mode;
562 return n;
563 }
564
565 void
uartpower(int on)566 uartpower(int on)
567 {
568 Uart *p;
569
570 for(p = uartlist; p != nil; p = p->next) {
571 if(p->phys->power)
572 (*p->phys->power)(p, on);
573 }
574 }
575
576 Dev uartdevtab = {
577 't',
578 "uart",
579
580 uartreset,
581 devinit,
582 devshutdown,
583 uartattach,
584 uartwalk,
585 uartstat,
586 uartopen,
587 devcreate,
588 uartclose,
589 uartread,
590 devbread,
591 uartwrite,
592 devbwrite,
593 devremove,
594 uartwstat,
595 uartpower,
596 };
597
598 /*
599 * restart input if it's off
600 */
601 static void
uartflow(void * v)602 uartflow(void *v)
603 {
604 Uart *p;
605
606 p = v;
607 if(p->modem)
608 (*p->phys->rts)(p, 1);
609 }
610
611 /*
612 * put some bytes into the local queue to avoid calling
613 * qconsume for every character
614 */
615 int
uartstageoutput(Uart * p)616 uartstageoutput(Uart *p)
617 {
618 int n;
619
620 n = qconsume(p->oq, p->ostage, Stagesize);
621 if(n <= 0)
622 return 0;
623 p->op = p->ostage;
624 p->oe = p->ostage + n;
625 return n;
626 }
627
628 /*
629 * restart output
630 */
631 void
uartkick(void * v)632 uartkick(void *v)
633 {
634 Uart *p = v;
635
636 if(p->blocked)
637 return;
638
639 ilock(&p->tlock);
640 (*p->phys->kick)(p);
641 iunlock(&p->tlock);
642
643 if(p->drain && uartdrained(p)){
644 p->drain = 0;
645 wakeup(&p->r);
646 }
647 }
648
649 /*
650 * Move data from the interrupt staging area to
651 * the input Queue.
652 */
653 static void
uartstageinput(Uart * p)654 uartstageinput(Uart *p)
655 {
656 int n;
657 uchar *ir, *iw;
658
659 while(p->ir != p->iw){
660 ir = p->ir;
661 if(p->ir > p->iw){
662 iw = p->ie;
663 p->ir = p->istage;
664 }
665 else{
666 iw = p->iw;
667 p->ir = p->iw;
668 }
669 if((n = qproduce(p->iq, ir, iw - ir)) < 0){
670 p->serr++;
671 (*p->phys->rts)(p, 0);
672 }
673 else if(n == 0)
674 p->berr++;
675 }
676 }
677
678 /*
679 * receive a character at interrupt time
680 */
681 void
uartrecv(Uart * p,char ch)682 uartrecv(Uart *p, char ch)
683 {
684 uchar *next;
685
686 /* software flow control */
687 if(p->xonoff){
688 if(ch == CTLS){
689 p->blocked = 1;
690 }else if(ch == CTLQ){
691 p->blocked = 0;
692 p->ctsbackoff = 2; /* clock gets output going again */
693 }
694 }
695
696 /* receive the character */
697 if(p->putc)
698 p->putc(p->iq, ch);
699 else if (p->iw) { /* maybe the line isn't enabled yet */
700 ilock(&p->rlock);
701 next = p->iw + 1;
702 if(next == p->ie)
703 next = p->istage;
704 if(next == p->ir)
705 uartstageinput(p);
706 if(next != p->ir){
707 *p->iw = ch;
708 p->iw = next;
709 }
710 iunlock(&p->rlock);
711 }
712 }
713
714 /*
715 * we save up input characters till clock time to reduce
716 * per character interrupt overhead.
717 */
718 static void
uartclock(void)719 uartclock(void)
720 {
721 Uart *p;
722
723 ilock(&uartalloc);
724 for(p = uartalloc.elist; p; p = p->elist){
725
726 /* this hopefully amortizes cost of qproduce to many chars */
727 if(p->iw != p->ir){
728 ilock(&p->rlock);
729 uartstageinput(p);
730 iunlock(&p->rlock);
731 }
732
733 /* hang up if requested */
734 if(p->dohup){
735 qhangup(p->iq, 0);
736 qhangup(p->oq, 0);
737 p->dohup = 0;
738 }
739
740 /* this adds hysteresis to hardware/software flow control */
741 if(p->ctsbackoff){
742 ilock(&p->tlock);
743 if(p->ctsbackoff){
744 if(--(p->ctsbackoff) == 0)
745 (*p->phys->kick)(p);
746 }
747 iunlock(&p->tlock);
748 }
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 e = s+n;
792 for(; s<e; s++){
793 if(*s == '\n')
794 consuart->phys->putc(consuart, '\r');
795 consuart->phys->putc(consuart, *s);
796 }
797 }
798