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 'W': 462 case 'w': 463 if(uarttimer == nil || n < 1) 464 return -1; 465 uarttimer->tns = (vlong)n * 100000LL; 466 break; 467 case 'X': 468 case 'x': 469 if(p->enabled){ 470 ilock(&p->tlock); 471 p->xonoff = n; 472 iunlock(&p->tlock); 473 } 474 break; 475 } 476 } 477 return 0; 478 } 479 480 static long 481 uartwrite(Chan *c, void *buf, long n, vlong) 482 { 483 Uart *p; 484 char *cmd; 485 486 if(c->qid.type & QTDIR) 487 error(Eperm); 488 489 p = uart[NETID(c->qid.path)]; 490 491 switch(NETTYPE(c->qid.path)){ 492 case Ndataqid: 493 qlock(p); 494 if(waserror()){ 495 qunlock(p); 496 nexterror(); 497 } 498 499 n = qwrite(p->oq, buf, n); 500 501 qunlock(p); 502 poperror(); 503 break; 504 case Nctlqid: 505 cmd = malloc(n+1); 506 memmove(cmd, buf, n); 507 cmd[n] = 0; 508 qlock(p); 509 if(waserror()){ 510 qunlock(p); 511 free(cmd); 512 nexterror(); 513 } 514 515 /* let output drain */ 516 if(uartctl(p, cmd) < 0) 517 error(Ebadarg); 518 519 qunlock(p); 520 poperror(); 521 free(cmd); 522 break; 523 } 524 525 return n; 526 } 527 528 static int 529 uartwstat(Chan *c, uchar *dp, int n) 530 { 531 Dir d; 532 Dirtab *dt; 533 534 if(!iseve()) 535 error(Eperm); 536 if(QTDIR & c->qid.type) 537 error(Eperm); 538 if(NETTYPE(c->qid.path) == Nstatqid) 539 error(Eperm); 540 541 dt = &uartdir[1 + 3 * NETID(c->qid.path)]; 542 n = convM2D(dp, n, &d, nil); 543 if(n == 0) 544 error(Eshortstat); 545 if(d.mode != ~0UL) 546 dt[0].perm = dt[1].perm = d.mode; 547 return n; 548 } 549 550 void 551 uartpower(int on) 552 { 553 Uart *p; 554 555 for(p = uartlist; p != nil; p = p->next) { 556 if(p->phys->power) 557 (*p->phys->power)(p, on); 558 } 559 } 560 561 Dev uartdevtab = { 562 't', 563 "uart", 564 565 uartreset, 566 devinit, 567 devshutdown, 568 uartattach, 569 uartwalk, 570 uartstat, 571 uartopen, 572 devcreate, 573 uartclose, 574 uartread, 575 devbread, 576 uartwrite, 577 devbwrite, 578 devremove, 579 uartwstat, 580 uartpower, 581 }; 582 583 /* 584 * restart input if it's off 585 */ 586 static void 587 uartflow(void *v) 588 { 589 Uart *p; 590 591 p = v; 592 if(p->modem) 593 (*p->phys->rts)(p, 1); 594 } 595 596 /* 597 * put some bytes into the local queue to avoid calling 598 * qconsume for every character 599 */ 600 int 601 uartstageoutput(Uart *p) 602 { 603 int n; 604 605 n = qconsume(p->oq, p->ostage, Stagesize); 606 if(n <= 0) 607 return 0; 608 p->op = p->ostage; 609 p->oe = p->ostage + n; 610 return n; 611 } 612 613 /* 614 * restart output 615 */ 616 void 617 uartkick(void *v) 618 { 619 Uart *p = v; 620 621 if(p->blocked) 622 return; 623 624 ilock(&p->tlock); 625 (*p->phys->kick)(p); 626 iunlock(&p->tlock); 627 628 if(p->drain && uartdrained(p)){ 629 p->drain = 0; 630 wakeup(&p->r); 631 } 632 } 633 634 /* 635 * Move data from the interrupt staging area to 636 * the input Queue. 637 */ 638 static void 639 uartstageinput(Uart *p) 640 { 641 int n; 642 uchar *ir, *iw; 643 644 while(p->ir != p->iw){ 645 ir = p->ir; 646 if(p->ir > p->iw){ 647 iw = p->ie; 648 p->ir = p->istage; 649 } 650 else{ 651 iw = p->iw; 652 p->ir = p->iw; 653 } 654 if((n = qproduce(p->iq, ir, iw - ir)) < 0){ 655 p->serr++; 656 (*p->phys->rts)(p, 0); 657 } 658 else if(n == 0) 659 p->berr++; 660 } 661 } 662 663 /* 664 * receive a character at interrupt time 665 */ 666 void 667 uartrecv(Uart *p, char ch) 668 { 669 uchar *next; 670 671 /* software flow control */ 672 if(p->xonoff){ 673 if(ch == CTLS){ 674 p->blocked = 1; 675 }else if(ch == CTLQ){ 676 p->blocked = 0; 677 p->ctsbackoff = 2; /* clock gets output going again */ 678 } 679 } 680 681 /* receive the character */ 682 if(p->putc) 683 p->putc(p->iq, ch); 684 else{ 685 ilock(&p->rlock); 686 next = p->iw + 1; 687 if(next == p->ie) 688 next = p->istage; 689 if(next == p->ir) 690 uartstageinput(p); 691 if(next != p->ir){ 692 *p->iw = ch; 693 p->iw = next; 694 } 695 iunlock(&p->rlock); 696 } 697 } 698 699 /* 700 * we save up input characters till clock time to reduce 701 * per character interrupt overhead. 702 */ 703 static void 704 uartclock(void) 705 { 706 Uart *p; 707 708 lock(&uartalloc); 709 for(p = uartalloc.elist; p; p = p->elist){ 710 711 /* this hopefully amortizes cost of qproduce to many chars */ 712 if(p->iw != p->ir){ 713 ilock(&p->rlock); 714 uartstageinput(p); 715 iunlock(&p->rlock); 716 } 717 718 /* hang up if requested */ 719 if(p->dohup){ 720 qhangup(p->iq, 0); 721 qhangup(p->oq, 0); 722 p->dohup = 0; 723 } 724 725 /* this adds hysteresis to hardware/software flow control */ 726 if(p->ctsbackoff){ 727 ilock(&p->tlock); 728 if(p->ctsbackoff){ 729 if(--(p->ctsbackoff) == 0) 730 (*p->phys->kick)(p); 731 } 732 iunlock(&p->tlock); 733 } 734 } 735 unlock(&uartalloc); 736 } 737 738 /* 739 * polling console input, output 740 */ 741 742 Uart* consuart; 743 744 int 745 uartgetc(void) 746 { 747 if(consuart == nil || consuart->phys->getc == nil) 748 return -1; 749 return consuart->phys->getc(consuart); 750 } 751 752 void 753 uartputc(int c) 754 { 755 if(consuart == nil || consuart->phys->putc == nil) 756 return; 757 consuart->phys->putc(consuart, c); 758 } 759 760 void 761 uartputs(char *s, int n) 762 { 763 char *e; 764 765 if(consuart == nil || consuart->phys->putc == nil) 766 return; 767 768 e = s+n; 769 for(; s<e; s++){ 770 if(*s == '\n') 771 consuart->phys->putc(consuart, '\r'); 772 consuart->phys->putc(consuart, *s); 773 } 774 } 775