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