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