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 /* 12 * Driver for the uart. 13 */ 14 enum 15 { 16 /* 17 * register numbers 18 */ 19 Data= 0, /* xmit/rcv buffer */ 20 Iena= 1, /* interrupt enable */ 21 Ircv= (1<<0), /* for char rcv'd */ 22 Ixmt= (1<<1), /* for xmit buffer empty */ 23 Irstat=(1<<2), /* for change in rcv'er status */ 24 Imstat=(1<<3), /* for change in modem status */ 25 Istat= 2, /* interrupt flag (read) */ 26 Ipend= 1, /* interrupt pending (not) */ 27 Fenabd=(3<<6), /* on if fifo's enabled */ 28 Fifoctl=2, /* fifo control (write) */ 29 Fena= (1<<0), /* enable xmit/rcv fifos */ 30 Fdma= (1<<3), /* dma on */ 31 Ftrig= (1<<6), /* trigger after 4 input characters */ 32 Fclear=(3<<1), /* clear xmit & rcv fifos */ 33 Format= 3, /* byte format */ 34 Bits8= (3<<0), /* 8 bits/byte */ 35 Stop2= (1<<2), /* 2 stop bits */ 36 Pena= (1<<3), /* generate parity */ 37 Peven= (1<<4), /* even parity */ 38 Pforce=(1<<5), /* force parity */ 39 Break= (1<<6), /* generate a break */ 40 Dra= (1<<7), /* address the divisor */ 41 Mctl= 4, /* modem control */ 42 Dtr= (1<<0), /* data terminal ready */ 43 Rts= (1<<1), /* request to send */ 44 Ri= (1<<2), /* ring */ 45 Inton= (1<<3), /* turn on interrupts */ 46 Loop= (1<<4), /* loop back */ 47 Lstat= 5, /* line status */ 48 Inready=(1<<0), /* receive buffer full */ 49 Oerror=(1<<1), /* receiver overrun */ 50 Perror=(1<<2), /* receiver parity error */ 51 Ferror=(1<<3), /* rcv framing error */ 52 Berror=(1<<4), /* break alarm */ 53 Outready=(1<<5), /* output buffer full */ 54 Mstat= 6, /* modem status */ 55 Ctsc= (1<<0), /* clear to send changed */ 56 Dsrc= (1<<1), /* data set ready changed */ 57 Rire= (1<<2), /* rising edge of ring indicator */ 58 Dcdc= (1<<3), /* data carrier detect changed */ 59 Cts= (1<<4), /* complement of clear to send line */ 60 Dsr= (1<<5), /* complement of data set ready line */ 61 Ringl= (1<<6), /* complement of ring indicator line */ 62 Dcd= (1<<7), /* complement of data carrier detect line */ 63 Scratch=7, /* scratchpad */ 64 Dlsb= 0, /* divisor lsb */ 65 Dmsb= 1, /* divisor msb */ 66 67 CTLS= 023, 68 CTLQ= 021, 69 70 Stagesize= 1024, 71 Nuart= 2, /* max per machine */ 72 }; 73 74 typedef struct Uart Uart; 75 struct Uart 76 { 77 QLock; 78 int opens; 79 80 int enabled; 81 Uart *elist; /* next enabled interface */ 82 char name[KNAMELEN]; 83 84 uchar sticky[8]; /* sticky write register values */ 85 void* regs; 86 ulong port; 87 ulong freq; /* clock frequency */ 88 uchar mask; /* bits/char */ 89 int dev; 90 int baud; /* baud rate */ 91 92 uchar istat; /* last istat read */ 93 int frame; /* framing errors */ 94 int overrun; /* rcvr overruns */ 95 96 /* buffers */ 97 int (*putc)(Queue*, int); 98 Queue *iq; 99 Queue *oq; 100 101 Lock flock; /* fifo */ 102 uchar fifoon; /* fifo's enabled */ 103 uchar nofifo; /* earlier chip version with nofifo */ 104 105 Lock rlock; /* receive */ 106 uchar istage[Stagesize]; 107 uchar *ip; 108 uchar *ie; 109 110 int haveinput; 111 112 Lock tlock; /* transmit */ 113 uchar ostage[Stagesize]; 114 uchar *op; 115 uchar *oe; 116 117 int modem; /* hardware flow control on */ 118 int xonoff; /* software flow control on */ 119 int blocked; 120 int cts, dsr, dcd; /* keep track of modem status */ 121 int ctsbackoff; 122 int hup_dsr, hup_dcd; /* send hangup upstream? */ 123 int dohup; 124 125 Rendez r; 126 }; 127 128 static Uart *uart[Nuart]; 129 static int nuart; 130 131 struct Uartalloc { 132 Lock; 133 Uart *elist; /* list of enabled interfaces */ 134 } uartalloc; 135 136 static void uartintr(Uart*); 137 138 /* 139 * pick up architecture specific routines and definitions 140 */ 141 #include "uart.h" 142 143 /* 144 * set the baud rate by calculating and setting the baudrate 145 * generator constant. This will work with fairly non-standard 146 * baud rates. 147 */ 148 static void 149 uartsetbaud(Uart *p, int rate) 150 { 151 ulong brconst; 152 153 if(rate <= 0) 154 return; 155 156 p->freq = archuartclock(p->port, rate); 157 if(p->freq == 0) 158 return; 159 160 brconst = (p->freq+8*rate-1)/(16*rate); 161 162 uartwrreg(p, Format, Dra); 163 uartwr(p, Dmsb, (brconst>>8) & 0xff); 164 uartwr(p, Dlsb, brconst & 0xff); 165 uartwrreg(p, Format, 0); 166 167 p->baud = rate; 168 } 169 170 /* 171 * decide if we should hangup when dsr or dcd drops. 172 */ 173 static void 174 uartdsrhup(Uart *p, int n) 175 { 176 p->hup_dsr = n; 177 } 178 179 static void 180 uartdcdhup(Uart *p, int n) 181 { 182 p->hup_dcd = n; 183 } 184 185 static void 186 uartparity(Uart *p, char type) 187 { 188 switch(type){ 189 case 'e': 190 p->sticky[Format] |= Pena|Peven; 191 break; 192 case 'o': 193 p->sticky[Format] &= ~Peven; 194 p->sticky[Format] |= Pena; 195 break; 196 default: 197 p->sticky[Format] &= ~(Pena|Peven); 198 break; 199 } 200 uartwrreg(p, Format, 0); 201 } 202 203 /* 204 * set bits/character, default 8 205 */ 206 void 207 uartbits(Uart *p, int bits) 208 { 209 if(bits < 5 || bits > 8) 210 error(Ebadarg); 211 212 p->sticky[Format] &= ~3; 213 p->sticky[Format] |= bits-5; 214 215 uartwrreg(p, Format, 0); 216 } 217 218 219 /* 220 * toggle DTR 221 */ 222 void 223 uartdtr(Uart *p, int n) 224 { 225 if(n) 226 p->sticky[Mctl] |= Dtr; 227 else 228 p->sticky[Mctl] &= ~Dtr; 229 230 uartwrreg(p, Mctl, 0); 231 } 232 233 /* 234 * toggle RTS 235 */ 236 void 237 uartrts(Uart *p, int n) 238 { 239 if(n) 240 p->sticky[Mctl] |= Rts; 241 else 242 p->sticky[Mctl] &= ~Rts; 243 244 uartwrreg(p, Mctl, 0); 245 } 246 247 /* 248 * send break 249 */ 250 static void 251 uartbreak(Uart *p, int ms) 252 { 253 if(ms == 0) 254 ms = 200; 255 256 uartwrreg(p, Format, Break); 257 tsleep(&up->sleep, return0, 0, ms); 258 uartwrreg(p, Format, 0); 259 } 260 261 static void 262 uartfifoon(Uart *p) 263 { 264 ulong i, x; 265 266 if(p->nofifo || uartrdreg(p, Istat) & Fenabd) 267 return; 268 269 x = splhi(); 270 271 /* reset fifos */ 272 p->sticky[Fifoctl] = 0; 273 uartwrreg(p, Fifoctl, Fclear); 274 275 /* empty buffer and interrupt conditions */ 276 for(i = 0; i < 16; i++){ 277 if(uartrdreg(p, Istat)){ 278 /* nothing to do */ 279 } 280 if(uartrdreg(p, Data)){ 281 /* nothing to do */ 282 } 283 } 284 285 /* turn on fifo */ 286 p->fifoon = 1; 287 p->sticky[Fifoctl] = Fena|Ftrig; 288 uartwrreg(p, Fifoctl, 0); 289 p->istat = uartrdreg(p, Istat); 290 if((p->istat & Fenabd) == 0) { 291 /* didn't work, must be an earlier chip type */ 292 p->nofifo = 1; 293 } 294 295 splx(x); 296 } 297 298 /* 299 * modem flow control on/off (rts/cts) 300 */ 301 static void 302 uartmflow(Uart *p, int n) 303 { 304 ilock(&p->tlock); 305 if(n){ 306 p->sticky[Iena] |= Imstat; 307 uartwrreg(p, Iena, 0); 308 p->modem = 1; 309 p->cts = uartrdreg(p, Mstat) & Cts; 310 } else { 311 p->sticky[Iena] &= ~Imstat; 312 uartwrreg(p, Iena, 0); 313 p->modem = 0; 314 p->cts = 1; 315 } 316 iunlock(&p->tlock); 317 318 // ilock(&p->flock); 319 // if(1) 320 // /* turn on fifo's */ 321 // uartfifoon(p); 322 // else { 323 // /* turn off fifo's */ 324 // p->fifoon = 0; 325 // p->sticky[Fifoctl] = 0; 326 // uartwrreg(p, Fifoctl, Fclear); 327 // } 328 // iunlock(&p->flock); 329 } 330 331 /* 332 * turn on a port's interrupts. set DTR and RTS 333 */ 334 static void 335 uartenable(Uart *p) 336 { 337 Uart **l; 338 339 if(p->enabled) 340 return; 341 342 uartportpower(p, 1); 343 344 p->hup_dsr = p->hup_dcd = 0; 345 p->cts = p->dsr = p->dcd = 0; 346 347 /* 348 * turn on interrupts 349 */ 350 p->sticky[Iena] = Ircv | Ixmt | Irstat; 351 uartwrreg(p, Iena, 0); 352 353 /* 354 * turn on DTR and RTS 355 */ 356 uartdtr(p, 1); 357 uartrts(p, 1); 358 359 uartfifoon(p); 360 361 /* 362 * assume we can send 363 */ 364 ilock(&p->tlock); 365 p->cts = 1; 366 p->blocked = 0; 367 iunlock(&p->tlock); 368 369 /* 370 * set baud rate to the last used 371 */ 372 uartsetbaud(p, p->baud); 373 374 lock(&uartalloc); 375 for(l = &uartalloc.elist; *l; l = &(*l)->elist){ 376 if(*l == p) 377 break; 378 } 379 if(*l == 0){ 380 p->elist = uartalloc.elist; 381 uartalloc.elist = p; 382 } 383 p->enabled = 1; 384 unlock(&uartalloc); 385 } 386 387 /* 388 * turn off a port's interrupts. reset DTR and RTS 389 */ 390 static void 391 uartdisable(Uart *p) 392 { 393 Uart **l; 394 395 /* 396 * turn off interrupts 397 */ 398 p->sticky[Iena] = 0; 399 uartwrreg(p, Iena, 0); 400 401 /* 402 * revert to default settings 403 */ 404 p->sticky[Format] = Bits8; 405 uartwrreg(p, Format, 0); 406 407 /* 408 * turn off DTR, RTS, hardware flow control & fifo's 409 */ 410 uartdtr(p, 0); 411 uartrts(p, 0); 412 uartmflow(p, 0); 413 ilock(&p->tlock); 414 p->xonoff = p->blocked = 0; 415 iunlock(&p->tlock); 416 417 uartportpower(p, 0); 418 419 lock(&uartalloc); 420 for(l = &uartalloc.elist; *l; l = &(*l)->elist){ 421 if(*l == p){ 422 *l = p->elist; 423 break; 424 } 425 } 426 p->enabled = 0; 427 unlock(&uartalloc); 428 } 429 430 /* 431 * put some bytes into the local queue to avoid calling 432 * qconsume for every character 433 */ 434 static int 435 stageoutput(Uart *p) 436 { 437 int n; 438 439 n = qconsume(p->oq, p->ostage, Stagesize); 440 if(n <= 0) 441 return 0; 442 p->op = p->ostage; 443 p->oe = p->ostage + n; 444 return n; 445 } 446 447 /* 448 * (re)start output 449 */ 450 static void 451 uartkick0(Uart *p) 452 { 453 int i; 454 if((p->modem && (p->cts == 0)) || p->blocked) 455 return; 456 457 /* 458 * 128 here is an arbitrary limit to make sure 459 * we don't stay in this loop too long. If the 460 * chips output queue is longer than 128, too 461 * bad -- presotto 462 */ 463 for(i = 0; i < 128; i++){ 464 if(!(uartrdreg(p, Lstat) & Outready)) 465 break; 466 if(p->op >= p->oe && stageoutput(p) == 0) 467 break; 468 uartwr(p, Data, *p->op++); 469 } 470 } 471 472 static void 473 uartkick(void *v) 474 { 475 Uart *p; 476 477 p = v; 478 ilock(&p->tlock); 479 uartkick0(p); 480 iunlock(&p->tlock); 481 } 482 483 /* 484 * restart input if it's off 485 */ 486 static void 487 uartflow(void *v) 488 { 489 Uart *p; 490 491 p = v; 492 if(p->modem) 493 uartrts(p, 1); 494 ilock(&p->rlock); 495 p->haveinput = 1; 496 iunlock(&p->rlock); 497 } 498 499 /* 500 * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts, 501 * transmit and receive enabled, interrupts disabled. 502 */ 503 static void 504 uartsetup0(Uart *p) 505 { 506 memset(p->sticky, 0, sizeof(p->sticky)); 507 /* 508 * set rate to 9600 baud. 509 * 8 bits/character. 510 * 1 stop bit. 511 * interrupts enabled. 512 */ 513 p->sticky[Format] = Bits8; 514 uartwrreg(p, Format, 0); 515 p->sticky[Mctl] |= Inton; 516 uartwrreg(p, Mctl, 0x0); 517 518 uartsetbaud(p, 9600); 519 520 p->iq = qopen(4*1024, 0, uartflow, p); 521 p->oq = qopen(4*1024, 0, uartkick, p); 522 if(p->iq == nil || p->oq == nil) 523 panic("uartsetup0"); 524 525 p->ip = p->istage; 526 p->ie = &p->istage[Stagesize]; 527 p->op = p->ostage; 528 p->oe = p->ostage; 529 } 530 531 /* 532 * called by uartinstall() to create a new duart 533 */ 534 void 535 uartsetup(ulong port, void *regs, ulong freq, char *name) 536 { 537 Uart *p; 538 539 if(nuart >= Nuart) 540 return; 541 542 p = xalloc(sizeof(Uart)); 543 uart[nuart] = p; 544 strcpy(p->name, name); 545 p->dev = nuart; 546 nuart++; 547 p->port = port; 548 p->regs = regs; 549 p->freq = freq; 550 uartsetup0(p); 551 } 552 553 /* 554 * called by main() to configure a duart port as a console or a mouse 555 */ 556 void 557 uartspecial(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int)) 558 { 559 Uart *p = uart[port]; 560 uartenable(p); 561 if(baud) 562 uartsetbaud(p, baud); 563 p->putc = putc; 564 if(in) 565 *in = p->iq; 566 if(out) 567 *out = p->oq; 568 p->opens++; 569 } 570 571 /* 572 * handle an interrupt to a single uart 573 */ 574 static void 575 uartintr(Uart *p) 576 { 577 uchar ch; 578 int s, l; 579 580 for (s = uartrdreg(p, Istat); !(s&Ipend); s = uartrdreg(p, Istat)) { 581 switch(s&0x3f){ 582 case 4: /* received data available */ 583 case 6: /* receiver line status (alarm or error) */ 584 case 12: /* character timeout indication */ 585 while ((l = uartrdreg(p, Lstat)) & Inready) { 586 if(l & Ferror) 587 p->frame++; 588 if(l & Oerror) 589 p->overrun++; 590 ch = uartrdreg(p, Data) & 0xff; 591 if (l & (Berror|Perror|Ferror)) { 592 /* ch came with break, parity or framing error - consume */ 593 continue; 594 } 595 if (ch == CTLS || ch == CTLQ) { 596 ilock(&p->tlock); 597 if(p->xonoff){ 598 if(ch == CTLS) 599 p->blocked = 1; 600 else 601 p->blocked = 0; /* clock gets output going again */ 602 } 603 iunlock(&p->tlock); 604 } 605 if(p->putc) 606 p->putc(p->iq, ch); 607 else { 608 ilock(&p->rlock); 609 if(p->ip < p->ie) 610 *p->ip++ = ch; 611 else 612 p->overrun++; 613 p->haveinput = 1; 614 iunlock(&p->rlock); 615 } 616 } 617 break; 618 619 case 2: /* transmitter not full */ 620 uartkick(p); 621 break; 622 623 case 0: /* modem status */ 624 ch = uartrdreg(p, Mstat); 625 if(ch & Ctsc){ 626 ilock(&p->tlock); 627 l = p->cts; 628 p->cts = ch & Cts; 629 if(l == 0 && p->cts) 630 p->ctsbackoff = 2; /* clock gets output going again */ 631 iunlock(&p->tlock); 632 } 633 if (ch & Dsrc) { 634 l = ch & Dsr; 635 if(p->hup_dsr && p->dsr && !l){ 636 ilock(&p->rlock); 637 p->dohup = 1; 638 iunlock(&p->rlock); 639 } 640 p->dsr = l; 641 } 642 if (ch & Dcdc) { 643 l = ch & Dcd; 644 if(p->hup_dcd && p->dcd && !l){ 645 ilock(&p->rlock); 646 p->dohup = 1; 647 iunlock(&p->rlock); 648 } 649 p->dcd = l; 650 } 651 break; 652 653 default: 654 iprint("weird uart interrupt #%2.2ux\n", s); 655 break; 656 } 657 } 658 p->istat = s; 659 } 660 661 /* 662 * we save up input characters till clock time 663 * 664 * There's also a bit of code to get a stalled print going. 665 * It shouldn't happen, but it does. Obviously I don't 666 * understand something. Since it was there, I bundled a 667 * restart after flow control with it to give some hysteresis 668 * to the hardware flow control. This makes compressing 669 * modems happier but will probably bother something else. 670 * -- presotto 671 */ 672 void 673 uartclock(void) 674 { 675 int n; 676 Uart *p; 677 678 for(p = uartalloc.elist; p; p = p->elist){ 679 680 /* this amortizes cost of qproduce to many chars */ 681 if(p->haveinput){ 682 ilock(&p->rlock); 683 if(p->haveinput){ 684 n = p->ip - p->istage; 685 if(n > 0 && p->iq){ 686 if(n > Stagesize) 687 panic("uartclock"); 688 if(qproduce(p->iq, p->istage, n) < 0) 689 uartrts(p, 0); 690 else 691 p->ip = p->istage; 692 } 693 p->haveinput = 0; 694 } 695 iunlock(&p->rlock); 696 } 697 if(p->dohup){ 698 ilock(&p->rlock); 699 if(p->dohup){ 700 qhangup(p->iq, 0); 701 qhangup(p->oq, 0); 702 } 703 p->dohup = 0; 704 iunlock(&p->rlock); 705 } 706 707 /* this adds hysteresis to hardware flow control */ 708 if(p->ctsbackoff){ 709 ilock(&p->tlock); 710 if(p->ctsbackoff){ 711 if(--(p->ctsbackoff) == 0) 712 uartkick0(p); 713 } 714 iunlock(&p->tlock); 715 } 716 } 717 } 718 719 Dirtab *uartdir; 720 int ndir; 721 722 static void 723 setlength(int i) 724 { 725 Uart *p; 726 727 if(i >= 0){ 728 p = uart[i]; 729 if(p && p->opens && p->iq) 730 uartdir[1+3*i].length = qlen(p->iq); 731 } else for(i = 0; i < nuart; i++){ 732 p = uart[i]; 733 if(p && p->opens && p->iq) 734 uartdir[1+3*i].length = qlen(p->iq); 735 } 736 } 737 738 /* 739 * all uarts must be uartsetup() by this point or inside of uartinstall() 740 */ 741 static void 742 uartreset(void) 743 { 744 int i; 745 Dirtab *dp; 746 uartinstall(); /* architecture specific */ 747 748 ndir = 1+3*nuart; 749 uartdir = xalloc(ndir * sizeof(Dirtab)); 750 dp = uartdir; 751 strcpy(dp->name, "."); 752 mkqid(&dp->qid, 0, 0, QTDIR); 753 dp->length = 0; 754 dp->perm = DMDIR|0555; 755 dp++; 756 for(i = 0; i < nuart; i++){ 757 /* 3 directory entries per port */ 758 strcpy(dp->name, uart[i]->name); 759 dp->qid.path = NETQID(i, Ndataqid); 760 dp->perm = 0666; 761 dp++; 762 sprint(dp->name, "%sctl", uart[i]->name); 763 dp->qid.path = NETQID(i, Nctlqid); 764 dp->perm = 0666; 765 dp++; 766 sprint(dp->name, "%sstatus", uart[i]->name); 767 dp->qid.path = NETQID(i, Nstatqid); 768 dp->perm = 0444; 769 dp++; 770 } 771 } 772 773 static Chan* 774 uartattach(char *spec) 775 { 776 return devattach('t', spec); 777 } 778 779 static Walkqid* 780 uartwalk(Chan *c, Chan *nc, char **name, int nname) 781 { 782 return devwalk(c, nc, name, nname, uartdir, ndir, devgen); 783 } 784 785 static int 786 uartstat(Chan *c, uchar *dp, int n) 787 { 788 if(NETTYPE(c->qid.path) == Ndataqid) 789 setlength(NETID(c->qid.path)); 790 return devstat(c, dp, n, uartdir, ndir, devgen); 791 } 792 793 static Chan* 794 uartopen(Chan *c, int omode) 795 { 796 Uart *p; 797 798 c = devopen(c, omode, uartdir, ndir, devgen); 799 800 switch(NETTYPE(c->qid.path)){ 801 case Nctlqid: 802 case Ndataqid: 803 p = uart[NETID(c->qid.path)]; 804 qlock(p); 805 if(p->opens++ == 0){ 806 uartenable(p); 807 qreopen(p->iq); 808 qreopen(p->oq); 809 } 810 qunlock(p); 811 break; 812 } 813 814 return c; 815 } 816 817 static void 818 uartclose(Chan *c) 819 { 820 Uart *p; 821 822 if(c->qid.type & QTDIR) 823 return; 824 if((c->flag & COPEN) == 0) 825 return; 826 switch(NETTYPE(c->qid.path)){ 827 case Ndataqid: 828 case Nctlqid: 829 p = uart[NETID(c->qid.path)]; 830 qlock(p); 831 if(--(p->opens) == 0){ 832 uartdisable(p); 833 qclose(p->iq); 834 qclose(p->oq); 835 p->ip = p->istage; 836 p->dcd = p->dsr = p->dohup = 0; 837 } 838 qunlock(p); 839 break; 840 } 841 } 842 843 static long 844 uartstatus(Chan*, Uart *p, void *buf, long n, long offset) 845 { 846 uchar mstat, fstat, istat, tstat; 847 char str[256]; 848 849 str[0] = 0; 850 tstat = p->sticky[Mctl]; 851 mstat = uartrdreg(p, Mstat); 852 istat = p->sticky[Iena]; 853 fstat = p->sticky[Format]; 854 snprint(str, sizeof str, 855 "b%d c%d d%d e%d l%d m%d p%c r%d s%d\n" 856 "%d %d %d%s%s%s%s%s\n", 857 858 p->baud, 859 p->hup_dcd, 860 (tstat & Dtr) != 0, 861 p->hup_dsr, 862 (fstat & Bits8) + 5, 863 (istat & Imstat) != 0, 864 (fstat & Pena) ? ((fstat & Peven) ? 'e' : 'o') : 'n', 865 (tstat & Rts) != 0, 866 (fstat & Stop2) ? 2 : 1, 867 868 p->dev, 869 p->frame, 870 p->overrun, 871 uartrdreg(p, Istat) & Fenabd ? " fifo" : "", 872 (mstat & Cts) ? " cts" : "", 873 (mstat & Dsr) ? " dsr" : "", 874 (mstat & Dcd) ? " dcd" : "", 875 (mstat & Ringl) ? " ring" : "" 876 ); 877 return readstr(offset, buf, n, str); 878 } 879 880 static long 881 uartread(Chan *c, void *buf, long n, vlong off) 882 { 883 Uart *p; 884 ulong offset = off; 885 886 if(c->qid.type & QTDIR){ 887 setlength(-1); 888 return devdirread(c, buf, n, uartdir, ndir, devgen); 889 } 890 891 p = uart[NETID(c->qid.path)]; 892 switch(NETTYPE(c->qid.path)){ 893 case Ndataqid: 894 return qread(p->iq, buf, n); 895 case Nctlqid: 896 return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE); 897 case Nstatqid: 898 return uartstatus(c, p, buf, n, offset); 899 } 900 901 return 0; 902 } 903 904 static void 905 uartctl(Uart *p, char *cmd) 906 { 907 int i, n; 908 909 /* let output drain for a while */ 910 for(i = 0; i < 16 && qlen(p->oq); i++) 911 tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125); 912 913 if(strncmp(cmd, "break", 5) == 0){ 914 uartbreak(p, 0); 915 return; 916 } 917 918 919 n = atoi(cmd+1); 920 switch(*cmd){ 921 case 'B': 922 case 'b': 923 uartsetbaud(p, n); 924 break; 925 case 'C': 926 case 'c': 927 uartdcdhup(p, n); 928 break; 929 case 'D': 930 case 'd': 931 uartdtr(p, n); 932 break; 933 case 'E': 934 case 'e': 935 uartdsrhup(p, n); 936 break; 937 case 'f': 938 case 'F': 939 qflush(p->oq); 940 break; 941 case 'H': 942 case 'h': 943 qhangup(p->iq, 0); 944 qhangup(p->oq, 0); 945 break; 946 case 'L': 947 case 'l': 948 uartbits(p, n); 949 break; 950 case 'm': 951 case 'M': 952 uartmflow(p, n); 953 break; 954 case 'n': 955 case 'N': 956 qnoblock(p->oq, n); 957 break; 958 case 'P': 959 case 'p': 960 uartparity(p, *(cmd+1)); 961 break; 962 case 'K': 963 case 'k': 964 uartbreak(p, n); 965 break; 966 case 'R': 967 case 'r': 968 uartrts(p, n); 969 break; 970 case 'Q': 971 case 'q': 972 qsetlimit(p->iq, n); 973 qsetlimit(p->oq, n); 974 break; 975 case 'W': 976 case 'w': 977 /* obsolete */ 978 break; 979 case 'X': 980 case 'x': 981 ilock(&p->tlock); 982 p->xonoff = n; 983 iunlock(&p->tlock); 984 break; 985 } 986 } 987 988 static long 989 uartwrite(Chan *c, void *buf, long n, vlong) 990 { 991 Uart *p; 992 char cmd[32]; 993 994 if(c->qid.type & QTDIR) 995 error(Eperm); 996 997 p = uart[NETID(c->qid.path)]; 998 999 /* 1000 * The fifo's turn themselves off sometimes. 1001 * It must be something I don't understand. -- presotto 1002 */ 1003 lock(&p->flock); 1004 if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0) 1005 uartfifoon(p); 1006 unlock(&p->flock); 1007 1008 switch(NETTYPE(c->qid.path)){ 1009 case Ndataqid: 1010 return qwrite(p->oq, buf, n); 1011 case Nctlqid: 1012 if(n >= sizeof(cmd)) 1013 n = sizeof(cmd)-1; 1014 memmove(cmd, buf, n); 1015 cmd[n] = 0; 1016 uartctl(p, cmd); 1017 return n; 1018 } 1019 } 1020 1021 static int 1022 uartwstat(Chan *c, uchar *dp, int n) 1023 { 1024 Dir d; 1025 Dirtab *dt; 1026 1027 if(!iseve()) 1028 error(Eperm); 1029 if(c->qid.type & QTDIR) 1030 error(Eperm); 1031 if(NETTYPE(c->qid.path) == Nstatqid) 1032 error(Eperm); 1033 1034 dt = &uartdir[1+3 * NETID(c->qid.path)]; 1035 n = convM2D(dp, n, &d, nil); 1036 if(n == 0) 1037 error(Eshortstat); 1038 if(d.mode != ~0UL){ 1039 d.mode &= 0666; 1040 dt[0].perm = dt[1].perm = d.mode; 1041 } 1042 return n; 1043 } 1044 1045 Dev uartdevtab = { 1046 't', 1047 "uart", 1048 1049 uartreset, 1050 devinit, 1051 devshutdown, 1052 uartattach, 1053 uartwalk, 1054 uartstat, 1055 uartopen, 1056 devcreate, 1057 uartclose, 1058 uartread, 1059 devbread, 1060 uartwrite, 1061 devbwrite, 1062 devremove, 1063 uartwstat, 1064 }; 1065