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