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