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 Nbuf= 2, /* double buffered */ 13 Rbufsize= 512, 14 Bufsize= (Rbufsize+CACHELINESZ-1)&~(CACHELINESZ-1), 15 Nuart= 2+4, /* max in any 8xx architecture (2xSMC, 4xSCC) */ 16 CTLS= 's'&037, 17 CTLQ= 'q'&037, 18 }; 19 20 enum { 21 /* status bits in SCC receive buffer descriptors */ 22 RxBRK= 1<<7, /* break ended frame (async hdlc) */ 23 RxDE= 1<<7, /* DPLL error (hdlc) */ 24 RxBOF= 1<<6, /* BOF ended frame (async hdlc) */ 25 RxLG= 1<<5, /* frame too large (hdlc) */ 26 RxNO= 1<<4, /* bad bit alignment (hdlc) */ 27 RxBR= 1<<5, /* break received during frame (uart) */ 28 RxFR= 1<<4, /* framing error (uart) */ 29 RxPR= 1<<3, /* parity error (uart) */ 30 RxAB= 1<<3, /* frame aborted (hdlc, async hdlc) */ 31 RxCR= 1<<2, /* bad CRC (hdlc, async hdlc) */ 32 RxOV= 1<<1, /* receiver overrun (all) */ 33 RxCD= 1<<0, /* CD lost (all) */ 34 35 /* hdlc-specific Rx/Tx BDs */ 36 TxTC= 1<<10, 37 }; 38 39 /* 40 * SMC in UART mode 41 */ 42 43 typedef struct Uartsmc Uartsmc; 44 struct Uartsmc { 45 IOCparam; 46 ushort maxidl; 47 ushort idlc; 48 ushort brkln; 49 ushort brkec; 50 ushort brkcr; 51 ushort rmask; 52 }; 53 54 /* 55 * SCC2 UART parameters 56 */ 57 enum { 58 /* special mode bits */ 59 SccAHDLC = 1<<0, 60 SccHDLC = 1<<1, 61 SccIR = 1<<2, 62 SccPPP = 1<<3, 63 }; 64 65 typedef struct Uartscc Uartscc; 66 struct Uartscc { 67 SCCparam; 68 uchar rsvd[8]; 69 ushort max_idl; 70 ushort idlc; 71 ushort brkcr; 72 ushort parec; 73 ushort frmec; 74 ushort nosec; 75 ushort brkec; 76 ushort brkln; 77 ushort uaddr1; 78 ushort uaddr2; 79 ushort rtemp; 80 ushort toseq; 81 ushort character[8]; 82 ushort rccm; 83 ushort rccrp; 84 ushort rlbc; 85 }; 86 87 typedef struct UartAHDLC UartAHDLC; 88 struct UartAHDLC { 89 SCCparam; 90 ulong rsvd1; 91 ulong c_mask; 92 ulong c_pres; 93 ushort bof; 94 ushort eof; 95 ushort esc; 96 ushort rsvd2[2]; 97 ushort zero; 98 ushort rsvd3; 99 ushort rfthr; 100 ushort resvd4[2]; 101 ulong txctl_tbl; 102 ulong rxctl_tbl; 103 ushort nof; 104 ushort rsvd5; 105 }; 106 107 typedef struct UartHDLC UartHDLC; 108 struct UartHDLC { 109 SCCparam; 110 ulong rsvd1; 111 ulong c_mask; 112 ulong c_pres; 113 ushort disfc; 114 ushort crcec; 115 ushort abtsc; 116 ushort nmarc; 117 ushort retrc; 118 ushort mflr; 119 ushort max_cnt; 120 ushort rfthr; 121 ushort rfcnt; 122 ushort hmask; 123 ushort haddr[4]; 124 ushort tmp; 125 ushort tmp_mb; 126 }; 127 128 enum { 129 /* SCC events of possible interest here eventually */ 130 AB= 1<<9, /* autobaud detected */ 131 GRA= 1<<7, /* graceful stop completed */ 132 CCR= 1<<3, /* control character detected */ 133 134 /* SCC, SMC common interrupt events */ 135 BSY= 1<<2, /* receive buffer was busy (overrun) */ 136 TXB= 1<<1, /* block sent */ 137 RXB= 1<<0, /* block received */ 138 139 /* SCC events */ 140 TXE = 1<<4, /* transmission error */ 141 RXF = 1<<3, /* final block received */ 142 143 /* gsmr_l */ 144 ENR = 1<<5, /* enable receiver */ 145 ENT = 1<<4, /* enable transmitter */ 146 147 /* port A */ 148 RXD1= SIBIT(15), 149 TXD1= SIBIT(14), 150 151 /* port B */ 152 RTS1B= IBIT(19), 153 154 /* port C */ 155 RTS1C= SIBIT(15), 156 CTS1= SIBIT(11), 157 CD1= SIBIT(10), 158 }; 159 160 typedef struct Uart Uart; 161 struct Uart 162 { 163 QLock; 164 165 Uart *elist; /* next enabled interface */ 166 char name[KNAMELEN]; 167 168 int x; /* index: x in SMCx or SCCx */ 169 int cpmid; /* eg, SCC1ID, SMC1ID */ 170 CPMdev* cpm; 171 int opens; 172 uchar bpc; /* bits/char */ 173 uchar parity; 174 uchar stopb; 175 uchar setup; 176 uchar enabled; 177 int dev; 178 179 ulong frame; /* framing errors */ 180 ulong perror; 181 ulong overrun; /* rcvr overruns */ 182 ulong crcerr; 183 ulong interrupts; 184 int baud; /* baud rate */ 185 186 /* flow control */ 187 int xonoff; /* software flow control on */ 188 int blocked; 189 int modem; /* hardware flow control on */ 190 int cts; /* ... cts state */ 191 int rts; /* ... rts state */ 192 Rendez r; 193 194 /* buffers */ 195 int (*putc)(Queue*, int); 196 Queue *iq; 197 Queue *oq; 198 199 /* staging areas to avoid some of the per character costs */ 200 /* TO DO: should probably use usual Ring */ 201 Block* istage[Nbuf]; /* double buffered */ 202 int rdrx; /* last buffer read */ 203 204 Lock plock; /* for output variables */ 205 Block* outb; /* currently transmitting Block */ 206 207 BD* rxb; 208 BD* txb; 209 210 SMC* smc; 211 SCC* scc; 212 IOCparam* param; 213 ushort* brkcr; /* brkcr location in appropriate block */ 214 int brgc; 215 int mode; 216 Block* partial; 217 int loopback; 218 }; 219 220 static Uart *uart[Nuart]; 221 static int nuart; 222 223 struct Uartalloc { 224 Lock; 225 Uart *elist; /* list of enabled interfaces */ 226 } uartalloc; 227 228 static void uartintr(Uart*, int); 229 static void smcuintr(Ureg*, void*); 230 static void sccuintr(Ureg*, void*); 231 232 static void 233 uartsetbuf(Uart *up) 234 { 235 IOCparam *p; 236 BD *bd; 237 int i; 238 Block *bp; 239 240 p = up->param; 241 p->rfcr = 0x18; 242 p->tfcr = 0x18; 243 p->mrblr = Rbufsize; 244 245 if((bd = up->rxb) == nil){ 246 bd = bdalloc(Nbuf); 247 up->rxb = bd; 248 } 249 p->rbase = (ushort)bd; 250 for(i=0; i<Nbuf; i++){ 251 bd->status = BDEmpty|BDInt; 252 bd->length = 0; 253 if((bp = up->istage[i]) == nil) 254 up->istage[i] = bp = allocb(Bufsize); 255 bd->addr = PADDR(bp->wp); 256 dcflush(bp->wp, Bufsize); 257 bd++; 258 } 259 (bd-1)->status |= BDWrap; 260 up->rdrx = 0; 261 262 if((bd = up->txb) == nil){ 263 bd = bdalloc(1); 264 up->txb = bd; 265 } 266 p->tbase = (ushort)bd; 267 bd->status = BDWrap|BDInt; 268 bd->length = 0; 269 bd->addr = 0; 270 } 271 272 static void 273 smcsetup(Uart *up) 274 { 275 IMM *io; 276 Uartsmc *p; 277 SMC *smc; 278 ulong txrx; 279 280 archdisableuart(up->cpmid); 281 up->brgc = brgalloc(); 282 if(up->brgc < 0) 283 error(Eio); 284 m->iomem->brgc[up->brgc] = baudgen(up->baud, 16) | BaudEnable; 285 smcnmsi(up->x, up->brgc); 286 287 archenableuart(up->cpmid, 0); 288 289 if(up->x == 1) 290 txrx = IBIT(24)|IBIT(25); /* SMC1 RX/TX */ 291 else 292 txrx = IBIT(20)|IBIT(21); /* SMC2 */ 293 io = ioplock(); 294 io->pbpar |= txrx; 295 io->pbdir &= ~txrx; 296 iopunlock(); 297 298 up->param = up->cpm->param; 299 uartsetbuf(up); 300 301 cpmop(up->cpm, InitRxTx, 0); 302 303 /* SMC protocol parameters */ 304 p = (Uartsmc*)up->param; 305 up->brkcr = &p->brkcr; 306 p->maxidl = 1; /* non-zero so buffer closes when idle before mrblr reached */ 307 p->brkln = 0; 308 p->brkec = 0; 309 p->brkcr = 1; 310 smc = up->cpm->regs; 311 smc->smce = 0xff; /* clear events */ 312 smc->smcm = BSY|RXB|TXB; /* enable all possible interrupts */ 313 up->smc = smc; 314 smc->smcmr = ((1+8+1-1)<<11)|(2<<4); /* 8-bit, 1 stop, no parity; UART mode */ 315 intrenable(VectorCPIC+up->cpm->irq, smcuintr, up, BUSUNKNOWN, up->name); 316 /* enable when device opened */ 317 } 318 319 static void 320 smcuintr(Ureg*, void *a) 321 { 322 Uart *up; 323 int events; 324 325 up = a; 326 events = up->smc->smce; 327 eieio(); 328 up->smc->smce = events; 329 uartintr(up, events&(BSY|RXB|TXB)); 330 } 331 332 /* 333 * set the IO ports to enable the control signals for SCCx 334 */ 335 static void 336 sccuartpins(int x, int mode) 337 { 338 IMM *io; 339 int i, w; 340 341 x--; 342 io = ioplock(); 343 i = 2*x; 344 w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */ 345 io->papar |= w; /* enable TXDn and RXDn pins */ 346 io->padir &= ~w; 347 if((mode & SccIR) == 0) 348 io->paodr |= TXD1<<i; 349 else 350 io->paodr &= ~w; /* not open drain */ 351 352 w = (CD1|CTS1)<<i; /* CDn and CTSn in port C */ 353 io->pcpar &= ~w; 354 io->pcdir &= ~w; 355 if(conf.nocts2 || mode) 356 io->pcso &= ~w; /* force CTS and CD on */ 357 else 358 io->pcso |= w; 359 360 w = RTS1B<<x; 361 io->pbpar &= ~w; 362 io->pbdir &= ~w; 363 364 w = RTS1C<<x; /* RTSn~ */ 365 if((mode & SccIR) == 0) 366 io->pcpar |= w; 367 else 368 io->pcpar &= ~w; /* don't use for IR */ 369 iopunlock(); 370 } 371 372 static void 373 sccsetup(Uart *up) 374 { 375 SCC *scc; 376 int i; 377 378 scc = up->cpm->regs; 379 up->scc = scc; 380 up->param = up->cpm->param; 381 sccxstop(up->cpm); 382 archdisableuart(up->cpmid); 383 if(up->brgc < 0){ 384 up->brgc = brgalloc(); 385 if(up->brgc < 0) 386 error(Eio); 387 } 388 m->iomem->brgc[up->brgc] = baudgen(up->baud, 16) | BaudEnable; 389 sccnmsi(up->x, up->brgc, up->brgc); 390 sccuartpins(up->x, up->mode); 391 392 uartsetbuf(up); 393 394 cpmop(up->cpm, InitRxTx, 0); 395 396 /* SCC protocol parameters */ 397 if((up->mode & (SccAHDLC|SccHDLC)) == 0){ 398 Uartscc *sp; 399 sp = (Uartscc*)up->param; 400 sp->max_idl = 1; 401 sp->brkcr = 1; 402 sp->parec = 0; 403 sp->frmec = 0; 404 sp->nosec = 0; 405 sp->brkec = 0; 406 sp->brkln = 0; 407 sp->brkec = 0; 408 sp->uaddr1 = 0; 409 sp->uaddr2 = 0; 410 sp->toseq = 0; 411 for(i=0; i<8; i++) 412 sp->character[i] = 0x8000; 413 sp->rccm = 0xC0FF; 414 up->brkcr = &sp->brkcr; 415 scc->irmode = 0; 416 scc->dsr = ~0; 417 scc->gsmrh = 1<<5; /* 8-bit oriented receive fifo */ 418 scc->gsmrl = 0x28004; /* UART mode */ 419 }else{ 420 UartAHDLC *hp; 421 hp = (UartAHDLC*)up->param; 422 hp->c_mask = 0x0000F0B8; 423 hp->c_pres = 0x0000FFFF; 424 if(up->mode & SccIR){ 425 hp->bof = 0xC0; 426 hp->eof = 0xC1; 427 //scc->dsr = 0xC0C0; 428 scc->dsr = 0x7E7E; 429 }else{ 430 hp->bof = 0x7E; 431 hp->eof = 0x7E; 432 scc->dsr = 0x7E7E; 433 } 434 hp->esc = 0x7D; 435 hp->zero = 0; 436 if(up->mode & SccHDLC) 437 hp->rfthr = 1; 438 else 439 hp->rfthr = 0; /* receive threshold of 1 doesn't work properly for Async HDLC */ 440 hp->txctl_tbl = 0; 441 hp->rxctl_tbl = 0; 442 if(up->mode & SccIR){ 443 /* low-speed infrared */ 444 hp->nof = 12-1; /* 12 flags */ 445 scc->irsip = 0; 446 scc->irmode = (2<<8) | 1; 447 archsetirxcvr(0); 448 if(up->loopback) 449 scc->irmode = (3<<4)|1; /* loopback */ 450 }else{ 451 scc->irmode = 0; 452 hp->txctl_tbl = ~0; 453 hp->rxctl_tbl = ~0; 454 hp->nof = 1-1; /* one opening flag */ 455 } 456 up->brkcr = nil; 457 scc->gsmrh = 1<<5; /* 8-bit oriented receive fifo */ 458 if(up->mode & SccHDLC) 459 scc->gsmrl = 0x28000; /* HDLC */ 460 else 461 scc->gsmrl = 0x28006; /* async HDLC/IrDA */ 462 } 463 archenableuart(up->cpmid, (up->mode&SccIR)!=0); 464 scc->scce = ~0; /* clear events */ 465 scc->sccm = TXE|BSY|RXF|TXB|RXB; /* enable all interesting interrupts */ 466 intrenable(VectorCPIC+up->cpm->irq, sccuintr, up, BUSUNKNOWN, up->name); 467 scc->psmr = 3<<12; /* 8-bit, 1 stop, no parity; UART mode */ 468 if(up->loopback && (up->mode & SccIR) == 0) 469 scc->gsmrl |= 1<<6; /* internal loop back */ 470 scc->gsmrl |= ENT|ENR; /* enable rx/tx */ 471 if(0){ 472 print("gsmrl=%8.8lux gsmrh=%8.8lux dsr=%4.4ux irmode=%4.4ux\n", scc->gsmrl, scc->gsmrh, scc->dsr, scc->irmode); 473 for(i=0; i<sizeof(Uartscc); i+=4) 474 print("%2.2ux %8.8lux\n", i, *(ulong*)((uchar*)up->param+i)); 475 } 476 } 477 478 static void 479 sccuintr(Ureg*, void *a) 480 { 481 Uart *up; 482 int events; 483 484 up = a; 485 if(up->scc == nil) 486 return; 487 events = up->scc->scce; 488 eieio(); 489 up->scc->scce = events; 490 if(up->enabled){ 491 if(0) 492 print("#%ux|", events); 493 uartintr(up, events); 494 } 495 } 496 497 static void 498 uartsetbaud(Uart *p, int rate) 499 { 500 if(rate <= 0 || p->brgc < 0) 501 return; 502 p->baud = rate; 503 m->iomem->brgc[p->brgc] = baudgen(rate, 16) | BaudEnable; 504 } 505 506 static void 507 uartsetmode(Uart *p) 508 { 509 int r, clen; 510 511 ilock(&p->plock); 512 clen = p->bpc; 513 if(p->parity == 'e' || p->parity == 'o') 514 clen++; 515 clen++; /* stop bit */ 516 if(p->stopb == 2) 517 clen++; 518 if(p->smc){ 519 r = p->smc->smcmr & 0x3F; /* keep mode, enable bits */ 520 r |= (clen<<11); 521 if(p->parity == 'e') 522 r |= 3<<8; 523 else if(p->parity == 'o') 524 r |= 2<<8; 525 if(p->stopb == 2) 526 r |= 1<<10; 527 eieio(); 528 p->smc->smcmr = r; 529 }else if(p->scc && p->mode == 0){ 530 r = p->scc->psmr & 0x8FE0; /* keep mode bits */ 531 r |= ((p->bpc-5)&3)<<12; 532 if(p->parity == 'e') 533 r |= (6<<2)|2; 534 else if(p->parity == 'o') 535 r |= (4<<2)|0; 536 if(p->stopb == 2) 537 r |= 1<<14; 538 eieio(); 539 p->scc->psmr = r; 540 } 541 iunlock(&p->plock); 542 } 543 544 static void 545 uartparity(Uart *p, char type) 546 { 547 ilock(&p->plock); 548 p->parity = type; 549 iunlock(&p->plock); 550 uartsetmode(p); 551 } 552 553 /* 554 * set bits/character 555 */ 556 static void 557 uartbits(Uart *p, int bits) 558 { 559 if(bits < 5 || bits > 14 || bits > 8 && p->scc) 560 error(Ebadarg); 561 562 ilock(&p->plock); 563 p->bpc = bits; 564 iunlock(&p->plock); 565 uartsetmode(p); 566 } 567 568 569 /* 570 * toggle DTR 571 */ 572 static void 573 uartdtr(Uart *p, int n) 574 { 575 if(p->scc == nil) 576 return; /* not possible */ 577 USED(n); /* not possible on FADS */ 578 } 579 580 /* 581 * toggle RTS 582 */ 583 static void 584 uartrts(Uart *p, int n) 585 { 586 p->rts = n; 587 if(p->scc == nil) 588 return; /* not possible */ 589 USED(n); /* not possible on FADS */ 590 } 591 592 /* 593 * send break 594 */ 595 static void 596 uartbreak(Uart *p, int ms) 597 { 598 if(p->brkcr == nil) 599 return; 600 601 if(ms <= 0) 602 ms = 200; 603 604 if(waserror()){ 605 ilock(&p->plock); 606 *p->brkcr = 1; 607 cpmop(p->cpm, RestartTx, 0); 608 iunlock(&p->plock); 609 nexterror(); 610 } 611 ilock(&p->plock); 612 *p->brkcr = ((p->baud/(p->bpc+2))*ms+500)/1000; 613 cpmop(p->cpm, StopTx, 0); 614 iunlock(&p->plock); 615 616 tsleep(&up->sleep, return0, 0, ms); 617 618 poperror(); 619 ilock(&p->plock); 620 *p->brkcr = 1; 621 cpmop(p->cpm, RestartTx, 0); 622 iunlock(&p->plock); 623 } 624 625 /* 626 * modem flow control on/off (rts/cts) 627 */ 628 static void 629 uartmflow(Uart *p, int n) 630 { 631 if(p->scc == nil) 632 return; /* not possible */ 633 if(n){ 634 p->modem = 1; 635 /* enable status interrupts ... */ 636 p->scc->psmr |= 1<<15; /* enable async flow control */ 637 p->cts = 1; 638 /* could change maxidl */ 639 }else{ 640 p->modem = 0; 641 /* stop status interrupts ... */ 642 p->scc->psmr &= ~(1<<15); 643 p->cts = 1; 644 } 645 } 646 647 /* 648 * turn on a port's interrupts. set DTR and RTS 649 */ 650 void 651 uartenable(Uart *p) 652 { 653 Uart **l; 654 655 if(p->enabled) 656 return; 657 658 if(p->setup == 0){ 659 if(p->cpmid == CPsmc1 || p->cpmid == CPsmc2) 660 smcsetup(p); 661 else 662 sccsetup(p); 663 p->setup = 1; 664 } 665 666 /* 667 * turn on interrupts 668 */ 669 if(p->smc){ 670 cpmop(p->cpm, RestartTx, 0); 671 p->smc->smcmr |= 3; 672 p->smc->smcm = BSY|TXB|RXB; 673 eieio(); 674 }else if(p->scc){ 675 cpmop(p->cpm, RestartTx, 0); 676 p->scc->gsmrl |= ENT|ENR; 677 p->scc->sccm = BSY|TXB|RXB; 678 eieio(); 679 } 680 681 /* 682 * turn on DTR and RTS 683 */ 684 uartdtr(p, 1); 685 uartrts(p, 1); 686 687 /* 688 * assume we can send 689 */ 690 p->cts = 1; 691 p->blocked = 0; 692 693 /* 694 * set baud rate to the last used 695 */ 696 uartsetbaud(p, p->baud); 697 698 lock(&uartalloc); 699 for(l = &uartalloc.elist; *l; l = &(*l)->elist){ 700 if(*l == p) 701 break; 702 } 703 if(*l == 0){ 704 p->elist = uartalloc.elist; 705 uartalloc.elist = p; 706 } 707 p->enabled = 1; 708 unlock(&uartalloc); 709 p->cts = 1; 710 p->blocked = 0; 711 p->xonoff = 0; 712 p->enabled = 1; 713 } 714 715 /* 716 * turn off a port's interrupts. reset DTR and RTS 717 */ 718 void 719 uartdisable(Uart *p) 720 { 721 Uart **l; 722 723 /* 724 * turn off interrpts 725 */ 726 if(p->smc) 727 smcxstop(p->cpm); 728 else if(p->scc) 729 sccxstop(p->cpm); 730 731 /* 732 * revert to default settings 733 */ 734 p->bpc = 8; 735 p->parity = 0; 736 p->stopb = 0; 737 738 /* 739 * turn off DTR, RTS, hardware flow control & fifo's 740 */ 741 uartdtr(p, 0); 742 uartrts(p, 0); 743 uartmflow(p, 0); 744 p->xonoff = p->blocked = 0; 745 746 lock(&uartalloc); 747 for(l = &uartalloc.elist; *l; l = &(*l)->elist){ 748 if(*l == p){ 749 *l = p->elist; 750 break; 751 } 752 } 753 p->enabled = 0; 754 unlock(&uartalloc); 755 } 756 757 /* 758 * set the next output buffer going 759 */ 760 static void 761 txstart(Uart *p) 762 { 763 Block *b; 764 int n, flags; 765 766 if(!p->cts || p->blocked || p->txb->status & BDReady) 767 return; 768 if((b = p->outb) == nil){ 769 if((b = qget(p->oq)) == nil) 770 return; 771 if(p->mode & SccPPP && 772 p->mode & SccAHDLC && 773 BLEN(b) >= 8){ /* strip framing data */ 774 UartAHDLC *hp; 775 hp = (UartAHDLC*)p->param; 776 if(hp != nil && (p->mode & SccIR) == 0){ 777 hp->txctl_tbl = nhgetl(b->rp); 778 hp->rxctl_tbl = nhgetl(b->rp+4); 779 } 780 b->rp += 8; 781 if(0) 782 print("tx #%lux rx #%lux\n", hp->txctl_tbl, hp->rxctl_tbl); 783 } 784 } 785 n = BLEN(b); 786 if(n <= 0) 787 print("txstart: 0\n"); 788 if(p->bpc > 8){ 789 /* half-word alignment and length if chars are long */ 790 if(PADDR(b->rp)&1){ /* must be even if chars are long */ 791 memmove(b->base, b->rp, n); 792 b->rp = b->base; 793 b->wp = b->rp+n; 794 } 795 if(n & 1) 796 n++; 797 } 798 dcflush(b->rp, n); 799 p->outb = b; 800 if(n > 0xFFFF) 801 n = 0xFFFE; 802 if(p->mode & SccHDLC) 803 flags = BDLast | TxTC; 804 else if(p->mode) 805 flags = BDLast; 806 else 807 flags = 0; 808 p->txb->addr = PADDR(b->rp); 809 p->txb->length = n; 810 eieio(); 811 p->txb->status = (p->txb->status & BDWrap) | flags | BDReady|BDInt; 812 eieio(); 813 } 814 815 /* 816 * (re)start output 817 */ 818 static void 819 uartkick(void *v) 820 { 821 Uart *p; 822 823 p = v; 824 ilock(&p->plock); 825 if(p->outb == nil) 826 txstart(p); 827 iunlock(&p->plock); 828 } 829 830 /* 831 * restart input if it's off 832 */ 833 static void 834 uartflow(void *v) 835 { 836 Uart *p; 837 838 p = v; 839 if(p->modem) 840 uartrts(p, 1); 841 } 842 843 static void 844 uartsetup(int x, int lid, char *name) 845 { 846 Uart *p; 847 848 if(nuart >= Nuart) 849 return; 850 851 p = xalloc(sizeof(Uart)); 852 uart[nuart] = p; 853 strcpy(p->name, name); 854 p->dev = nuart; 855 nuart++; 856 p->x = x; 857 p->cpmid = lid; 858 p->cpm = cpmdev(lid); 859 p->brgc = -1; 860 p->mode = 0; 861 862 /* 863 * set rate to 9600 baud. 864 * 8 bits/character. 865 * 1 stop bit. 866 * interrupts enabled. 867 */ 868 p->bpc = 8; 869 p->parity = 0; 870 p->baud = 9600; 871 872 p->iq = qopen(4*1024, Qcoalesce, uartflow, p); 873 p->oq = qopen(4*1024, 0, uartkick, p); 874 } 875 876 /* 877 * called by main() to configure a duart port as a console or a mouse 878 */ 879 void 880 uartspecial(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int)) 881 { 882 Uart *p; 883 884 if(port < 0 || port >= nuart || (p = uart[port]) == nil) 885 return; /* specified port not implemented */ 886 uartenable(p); 887 if(baud) 888 uartsetbaud(p, baud); 889 p->putc = putc; 890 if(in) 891 *in = p->iq; 892 if(out) 893 *out = p->oq; 894 p->opens++; 895 } 896 897 static int 898 uartinput(Uart *p, BD *bd) 899 { 900 int ch, dokick, i, l; 901 uchar *bp; 902 903 dokick = 0; 904 if(bd->status & RxFR) 905 p->frame++; 906 if(bd->status & RxOV) 907 p->overrun++; 908 l = bd->length; 909 if(bd->status & RxPR){ 910 p->perror++; 911 l--; /* it's the last character */ 912 } 913 bp = KADDR(bd->addr); 914 if(p->xonoff || p->putc && p->opens==1){ 915 for(i=0; i<l; i++){ 916 ch = bp[i]; 917 if(p->xonoff){ 918 if(ch == CTLS){ 919 p->blocked = 1; 920 cpmop(p->cpm, StopTx, 0); 921 }else if (ch == CTLQ){ 922 p->blocked = 0; 923 dokick = 1; 924 } 925 /* BUG? should discard on/off char? */ 926 } 927 if(p->putc) 928 (*p->putc)(p->iq, ch); 929 } 930 } 931 if(l > 0 && (p->putc == nil || p->opens>1)) 932 qproduce(p->iq, bp, l); 933 return dokick; 934 } 935 936 static void 937 framedinput(Uart *p, BD *bd) 938 { 939 Block *pkt; 940 int l; 941 942 pkt = p->partial; 943 p->partial = nil; 944 if(bd->status & RxOV){ 945 p->overrun++; 946 goto Discard; 947 } 948 if(bd->status & (RxAB|RxCR|RxCD|RxLG|RxNO|RxDE|RxBOF|RxBRK)){ 949 if(bd->status & RxCR) 950 p->crcerr++; 951 else 952 p->frame++; 953 goto Discard; 954 } 955 if(pkt == nil){ 956 pkt = iallocb(1500); /* TO DO: allocate less if possible */ 957 if(pkt == nil) 958 return; 959 } 960 l = bd->length; 961 if(bd->status & BDLast) 962 l -= BLEN(pkt); /* last one gives size of entire frame */ 963 if(l > 0){ 964 if(pkt->wp+l > pkt->lim) 965 goto Discard; 966 memmove(pkt->wp, KADDR(bd->addr), l); 967 pkt->wp += l; 968 } 969 if(0) 970 print("#%ux|", bd->status); 971 if(bd->status & BDLast){ 972 if(p->mode & (SccHDLC|SccAHDLC)){ 973 if(BLEN(pkt) <= 2){ 974 p->frame++; 975 goto Discard; 976 } 977 pkt->wp -= 2; /* strip CRC */ 978 } 979 qpass(p->iq, pkt); 980 }else 981 p->partial = pkt; 982 return; 983 984 Discard: 985 if(pkt != nil) 986 freeb(pkt); 987 } 988 989 /* 990 * handle an interrupt to a single uart 991 */ 992 static void 993 uartintr(Uart *p, int events) 994 { 995 int dokick; 996 BD *bd; 997 Block *b; 998 999 if(events & BSY) 1000 p->overrun++; 1001 p->interrupts++; 1002 dokick = 0; 1003 while(p->rxb != nil && ((bd = &p->rxb[p->rdrx])->status & BDEmpty) == 0){ 1004 dcinval(KADDR(bd->addr), bd->length); 1005 if(p->mode) 1006 framedinput(p, bd); 1007 else if(uartinput(p, bd)) 1008 dokick = 1; 1009 bd->status = (bd->status & BDWrap) | BDEmpty|BDInt; 1010 eieio(); 1011 if(++p->rdrx >= Nbuf) 1012 p->rdrx = 0; 1013 } 1014 if((bd = p->txb) != nil){ 1015 if((bd->status & BDReady) == 0){ 1016 ilock(&p->plock); 1017 if((b = p->outb) != nil){ 1018 b->rp += bd->length; 1019 if(b->rp >= b->wp){ 1020 p->outb = nil; 1021 freeb(b); 1022 } 1023 } 1024 txstart(p); 1025 iunlock(&p->plock); 1026 } 1027 } 1028 eieio(); 1029 /* TO DO: modem status isn't available on 82xFADS */ 1030 if(dokick && p->cts && !p->blocked){ 1031 if(p->outb == nil){ 1032 ilock(&p->plock); 1033 txstart(p); 1034 iunlock(&p->plock); 1035 } 1036 cpmop(p->cpm, RestartTx, 0); 1037 } else if (events & TXE) 1038 cpmop(p->cpm, RestartTx, 0); 1039 } 1040 1041 /* 1042 * used to ensure uart console output when debugging 1043 */ 1044 void 1045 uartwait(void) 1046 { 1047 Uart *p = uart[0]; 1048 int s; 1049 1050 while(p && (p->outb||qlen(p->oq))){ 1051 if(islo()) 1052 continue; 1053 s = splhi(); 1054 if((p->txb->status & BDReady) == 0){ 1055 p->blocked = 0; 1056 p->cts = 1; 1057 if(p->scc == nil) 1058 smcuintr(nil, p); 1059 else 1060 sccuintr(nil, p); 1061 } 1062 splx(s); 1063 } 1064 } 1065 1066 static Dirtab *uartdir; 1067 static int ndir; 1068 1069 static void 1070 setlength(int i) 1071 { 1072 Uart *p; 1073 1074 if(i >= 0){ 1075 p = uart[i]; 1076 if(p && p->opens && p->iq) 1077 uartdir[1+4*i].length = qlen(p->iq); 1078 } else for(i = 0; i < nuart; i++){ 1079 p = uart[i]; 1080 if(p && p->opens && p->iq) 1081 uartdir[1+4*i].length = qlen(p->iq); 1082 } 1083 1084 } 1085 1086 void 1087 uartinstall(void) 1088 { 1089 static int already; 1090 int i, n; 1091 char name[2*KNAMELEN]; 1092 if(already) 1093 return; 1094 already = 1; 1095 n = 0; 1096 for(i=0; i<2; i++) 1097 if(conf.smcuarts & (1<<i)){ 1098 snprint(name, sizeof(name), "eia%d", n++); 1099 uartsetup(i+1, CPsmc1+i, name); 1100 } 1101 n = 2; 1102 for(i=0; i<conf.nscc; i++) 1103 if(conf.sccuarts & (1<<i)){ 1104 snprint(name, sizeof(name), "eia%d", n++); 1105 uartsetup(i+1, CPscc1+i, name); 1106 } 1107 } 1108 1109 /* 1110 * all uarts must be uartsetup() by this point or inside of uartinstall() 1111 */ 1112 static void 1113 uartreset(void) 1114 { 1115 int i; 1116 Dirtab *dp; 1117 1118 uartinstall(); /* architecture specific */ 1119 1120 ndir = 1+4*nuart; 1121 uartdir = xalloc(ndir * sizeof(Dirtab)); 1122 dp = uartdir; 1123 strcpy(dp->name, "."); 1124 mkqid(&dp->qid, 0, 0, QTDIR); 1125 dp->length = 0; 1126 dp->perm = DMDIR|0555; 1127 dp++; 1128 for(i = 0; i < nuart; i++){ 1129 /* 4 directory entries per port */ 1130 strcpy(dp->name, uart[i]->name); 1131 dp->qid.path = NETQID(i, Ndataqid); 1132 dp->perm = 0660; 1133 dp++; 1134 sprint(dp->name, "%sctl", uart[i]->name); 1135 dp->qid.path = NETQID(i, Nctlqid); 1136 dp->perm = 0660; 1137 dp++; 1138 sprint(dp->name, "%sstatus", uart[i]->name); 1139 dp->qid.path = NETQID(i, Nstatqid); 1140 dp->perm = 0444; 1141 dp++; 1142 sprint(dp->name, "%smode", uart[i]->name); 1143 dp->qid.path = NETQID(i, Ntypeqid); 1144 dp->perm = 0660; 1145 dp++; 1146 } 1147 } 1148 1149 static Chan* 1150 uartattach(char *spec) 1151 { 1152 return devattach('t', spec); 1153 } 1154 1155 static Walkqid* 1156 uartwalk(Chan *c, Chan *nc, char **name, int nname) 1157 { 1158 return devwalk(c, nc, name, nname, uartdir, ndir, devgen); 1159 } 1160 1161 static int 1162 uartstat(Chan *c, uchar *dp, int n) 1163 { 1164 if(NETTYPE(c->qid.path) == Ndataqid) 1165 setlength(NETID(c->qid.path)); 1166 return devstat(c, dp, n, uartdir, ndir, devgen); 1167 } 1168 1169 static Chan* 1170 uartopen(Chan *c, int omode) 1171 { 1172 Uart *p; 1173 1174 c = devopen(c, omode, uartdir, ndir, devgen); 1175 1176 switch(NETTYPE(c->qid.path)){ 1177 case Nctlqid: 1178 case Ndataqid: 1179 p = uart[NETID(c->qid.path)]; 1180 qlock(p); 1181 if(p->opens++ == 0){ 1182 uartenable(p); 1183 qreopen(p->iq); 1184 qreopen(p->oq); 1185 } 1186 qunlock(p); 1187 break; 1188 } 1189 1190 return c; 1191 } 1192 1193 static void 1194 uartclose(Chan *c) 1195 { 1196 Uart *p; 1197 1198 if(c->qid.type & QTDIR) 1199 return; 1200 if((c->flag & COPEN) == 0) 1201 return; 1202 switch(NETTYPE(c->qid.path)){ 1203 case Ndataqid: 1204 case Nctlqid: 1205 p = uart[NETID(c->qid.path)]; 1206 qlock(p); 1207 if(--(p->opens) == 0){ 1208 uartdisable(p); 1209 qclose(p->iq); 1210 qclose(p->oq); 1211 } 1212 qunlock(p); 1213 break; 1214 } 1215 } 1216 1217 static long 1218 uartstatus(Chan*, Uart *p, void *buf, long n, long offset) 1219 { 1220 IMM *io; 1221 char str[256]; 1222 1223 // TO DO: change to standard format for first line: 1224 //"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n" 1225 sprint(str, "opens %d ferr %lud oerr %lud crcerr %lud baud %ud perr %lud intr %lud", p->opens, 1226 p->frame, p->overrun, p->crcerr, p->baud, p->perror, p->interrupts); 1227 /* TO DO: cts, dsr, ring, dcd, dtr, rts aren't all available on 82xFADS */ 1228 io = m->iomem; 1229 if(p->scc){ 1230 if((io->pcdat & SIBIT(9)) == 0) 1231 strcat(str, " cts"); 1232 if((io->pcdat & SIBIT(8)) == 0) 1233 strcat(str, " dcd"); 1234 if((io->pbdat & IBIT(22)) == 0) 1235 strcat(str, " dtr"); 1236 }else if(p->smc){ 1237 if((io->pbdat & IBIT(23)) == 0) 1238 strcat(str, " dtr"); 1239 } 1240 strcat(str, "\n"); 1241 return readstr(offset, buf, n, str); 1242 } 1243 1244 static long 1245 uartread(Chan *c, void *buf, long n, vlong offset) 1246 { 1247 Uart *p; 1248 1249 if(c->qid.type & QTDIR){ 1250 setlength(-1); 1251 return devdirread(c, buf, n, uartdir, ndir, devgen); 1252 } 1253 1254 p = uart[NETID(c->qid.path)]; 1255 switch(NETTYPE(c->qid.path)){ 1256 case Ndataqid: 1257 return qread(p->iq, buf, n); 1258 case Nctlqid: 1259 return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE); 1260 case Nstatqid: 1261 return uartstatus(c, p, buf, n, offset); 1262 case Ntypeqid: 1263 return readnum(offset, buf, n, p->mode, NUMSIZE); 1264 } 1265 1266 return 0; 1267 } 1268 1269 static Block* 1270 uartbread(Chan *c, long n, ulong offset) 1271 { 1272 if(c->qid.type & QTDIR || NETTYPE(c->qid.path) != Ndataqid) 1273 return devbread(c, n, offset); 1274 return qbread(uart[NETID(c->qid.path)]->iq, n); 1275 } 1276 1277 static void 1278 uartctl(Uart *p, char *cmd) 1279 { 1280 int i, n; 1281 1282 /* let output drain for a while */ 1283 for(i = 0; i < 16 && qlen(p->oq); i++) 1284 tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125); 1285 1286 if(strncmp(cmd, "break", 5) == 0){ 1287 uartbreak(p, 0); 1288 return; 1289 } 1290 1291 n = atoi(cmd+1); 1292 switch(*cmd){ 1293 case 'B': 1294 case 'b': 1295 uartsetbaud(p, n); 1296 break; 1297 case 'D': 1298 case 'd': 1299 uartdtr(p, n); 1300 break; 1301 case 'f': 1302 case 'F': 1303 qflush(p->oq); 1304 break; 1305 case 'H': 1306 case 'h': 1307 qhangup(p->iq, 0); 1308 qhangup(p->oq, 0); 1309 break; 1310 case 'L': 1311 case 'l': 1312 uartbits(p, n); 1313 break; 1314 case 'm': 1315 case 'M': 1316 uartmflow(p, n); 1317 break; 1318 case 'n': 1319 case 'N': 1320 qnoblock(p->oq, n); 1321 break; 1322 case 'P': 1323 case 'p': 1324 uartparity(p, *(cmd+1)); 1325 break; 1326 case 'K': 1327 case 'k': 1328 uartbreak(p, n); 1329 break; 1330 case 'R': 1331 case 'r': 1332 uartrts(p, n); 1333 break; 1334 case 'Q': 1335 case 'q': 1336 qsetlimit(p->iq, n); 1337 qsetlimit(p->oq, n); 1338 break; 1339 case 'W': 1340 case 'w': 1341 /* obsolete */ 1342 break; 1343 case 'X': 1344 case 'x': 1345 p->xonoff = n; 1346 break; 1347 case 'Z': 1348 case 'z': 1349 p->loopback = n; 1350 break; 1351 } 1352 } 1353 1354 static long 1355 uartwrite(Chan *c, void *buf, long n, vlong offset) 1356 { 1357 Uart *p; 1358 char cmd[32]; 1359 int m, inuse; 1360 1361 USED(offset); 1362 1363 if(c->qid.type & QTDIR) 1364 error(Eperm); 1365 1366 p = uart[NETID(c->qid.path)]; 1367 1368 switch(NETTYPE(c->qid.path)){ 1369 case Ndataqid: 1370 return qwrite(p->oq, buf, n); 1371 case Nctlqid: 1372 if(n >= sizeof(cmd)) 1373 n = sizeof(cmd)-1; 1374 memmove(cmd, buf, n); 1375 cmd[n] = 0; 1376 uartctl(p, cmd); 1377 return n; 1378 case Ntypeqid: 1379 if(p->smc || p->putc) 1380 error(Ebadarg); 1381 if(n >= sizeof(cmd)) 1382 n = sizeof(cmd)-1; 1383 memmove(cmd, buf, n); 1384 cmd[n] = 0; 1385 m = strtoul(cmd, nil, 0); 1386 inuse = 0; 1387 qlock(p); 1388 if(p->opens == 0){ 1389 p->mode = m & 0x7F; 1390 p->loopback = (m&0x80)!=0; 1391 p->setup = 0; 1392 }else 1393 inuse = 1; 1394 qunlock(p); 1395 if(inuse) 1396 error(Einuse); 1397 return n; 1398 } 1399 } 1400 1401 static long 1402 uartbwrite(Chan *c, Block *bp, ulong offset) 1403 { 1404 if(c->qid.type & QTDIR || NETTYPE(c->qid.path) != Ndataqid) 1405 return devbwrite(c, bp, offset); 1406 return qbwrite(uart[NETID(c->qid.path)]->oq, bp); 1407 } 1408 1409 static int 1410 uartwstat(Chan *c, uchar *dp, int n) 1411 { 1412 Dir d; 1413 Dirtab *dt; 1414 1415 if(!iseve()) 1416 error(Eperm); 1417 if(c->qid.type & QTDIR) 1418 error(Eperm); 1419 if(NETTYPE(c->qid.path) == Nstatqid) 1420 error(Eperm); 1421 1422 dt = &uartdir[1+4 * NETID(c->qid.path)]; 1423 n = convM2D(dp, n, &d, nil); 1424 if(d.mode != ~0UL){ 1425 d.mode &= 0666; 1426 dt[0].perm = dt[1].perm = d.mode; 1427 } 1428 return n; 1429 } 1430 1431 Dev uartdevtab = { 1432 't', 1433 "uart", 1434 1435 uartreset, 1436 devinit, 1437 devshutdown, 1438 uartattach, 1439 uartwalk, 1440 uartstat, 1441 uartopen, 1442 devcreate, 1443 uartclose, 1444 uartread, 1445 uartbread, 1446 uartwrite, 1447 uartbwrite, 1448 devremove, 1449 uartwstat, 1450 }; 1451