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