1 /* 2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)dca.c 7.10 (Berkeley) 05/07/91 8 */ 9 10 #include "dca.h" 11 #if NDCA > 0 12 /* 13 * 98626/98644/internal serial interface 14 * uses National Semiconductor INS8250/NS16550AF UART 15 */ 16 #include "sys/param.h" 17 #include "sys/systm.h" 18 #include "sys/ioctl.h" 19 #include "sys/tty.h" 20 #include "sys/proc.h" 21 #include "sys/conf.h" 22 #include "sys/file.h" 23 #include "sys/uio.h" 24 #include "sys/kernel.h" 25 #include "sys/syslog.h" 26 27 #include "device.h" 28 #include "dcareg.h" 29 #include "machine/cpu.h" 30 #include "../hp300/isr.h" 31 32 int dcaprobe(); 33 struct driver dcadriver = { 34 dcaprobe, "dca", 35 }; 36 37 int dcastart(), dcaparam(), dcaintr(); 38 int dcasoftCAR; 39 int dca_active; 40 int dca_hasfifo; 41 int ndca = NDCA; 42 #ifdef DCACONSOLE 43 int dcaconsole = DCACONSOLE; 44 #else 45 int dcaconsole = -1; 46 #endif 47 int dcaconsinit; 48 int dcadefaultrate = TTYDEF_SPEED; 49 int dcamajor; 50 struct dcadevice *dca_addr[NDCA]; 51 struct tty dca_tty[NDCA]; 52 struct isr dcaisr[NDCA]; 53 54 struct speedtab dcaspeedtab[] = { 55 0, 0, 56 50, DCABRD(50), 57 75, DCABRD(75), 58 110, DCABRD(110), 59 134, DCABRD(134), 60 150, DCABRD(150), 61 200, DCABRD(200), 62 300, DCABRD(300), 63 600, DCABRD(600), 64 1200, DCABRD(1200), 65 1800, DCABRD(1800), 66 2400, DCABRD(2400), 67 4800, DCABRD(4800), 68 9600, DCABRD(9600), 69 19200, DCABRD(19200), 70 38400, DCABRD(38400), 71 -1, -1 72 }; 73 74 extern struct tty *constty; 75 #ifdef KGDB 76 #include "machine/remote-sl.h" 77 78 extern int kgdb_dev; 79 extern int kgdb_rate; 80 extern int kgdb_debug_init; 81 #endif 82 83 #define UNIT(x) minor(x) 84 85 #ifdef DEBUG 86 long fifoin[17]; 87 long fifoout[17]; 88 long dcaintrcount[16]; 89 long dcamintcount[16]; 90 #endif 91 92 dcaprobe(hd) 93 register struct hp_device *hd; 94 { 95 register struct dcadevice *dca; 96 register int unit; 97 98 dca = (struct dcadevice *)hd->hp_addr; 99 if (dca->dca_irid != DCAID0 && 100 dca->dca_irid != DCAREMID0 && 101 dca->dca_irid != DCAID1 && 102 dca->dca_irid != DCAREMID1) 103 return (0); 104 unit = hd->hp_unit; 105 if (unit == dcaconsole) 106 DELAY(100000); 107 dca->dca_irid = 0xFF; 108 DELAY(100); 109 110 /* look for a NS 16550AF UART with FIFOs */ 111 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 112 DELAY(100); 113 if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) 114 dca_hasfifo |= 1 << unit; 115 116 hd->hp_ipl = DCAIPL(dca->dca_ic); 117 dcaisr[unit].isr_ipl = hd->hp_ipl; 118 dcaisr[unit].isr_arg = unit; 119 dcaisr[unit].isr_intr = dcaintr; 120 dca_addr[unit] = dca; 121 dca_active |= 1 << unit; 122 dcasoftCAR = hd->hp_flags; 123 isrlink(&dcaisr[unit]); 124 #ifdef KGDB 125 if (kgdb_dev == makedev(dcamajor, unit)) { 126 if (dcaconsole == unit) 127 kgdb_dev = -1; /* can't debug over console port */ 128 else { 129 (void) dcainit(unit, kgdb_rate); 130 if (kgdb_debug_init) { 131 /* 132 * Print prefix of device name, 133 * let kgdb_connect print the rest. 134 */ 135 printf("dca%d: ", unit); 136 kgdb_connect(1); 137 } else 138 printf("dca%d: kgdb enabled\n", unit); 139 } 140 } 141 #endif 142 dca->dca_ic = IC_IE; 143 /* 144 * Need to reset baud rate, etc. of next print so reset dcaconsinit. 145 * Also make sure console is always "hardwired." 146 */ 147 if (unit == dcaconsole) { 148 dcaconsinit = 0; 149 dcasoftCAR |= (1 << unit); 150 } 151 return (1); 152 } 153 154 /* ARGSUSED */ 155 #ifdef __STDC__ 156 dcaopen(dev_t dev, int flag, int mode, struct proc *p) 157 #else 158 dcaopen(dev, flag, mode, p) 159 dev_t dev; 160 int flag, mode; 161 struct proc *p; 162 #endif 163 { 164 register struct tty *tp; 165 register int unit; 166 int error = 0; 167 168 unit = UNIT(dev); 169 if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 170 return (ENXIO); 171 tp = &dca_tty[unit]; 172 tp->t_oproc = dcastart; 173 tp->t_param = dcaparam; 174 tp->t_dev = dev; 175 if ((tp->t_state & TS_ISOPEN) == 0) { 176 tp->t_state |= TS_WOPEN; 177 ttychars(tp); 178 if (tp->t_ispeed == 0) { 179 tp->t_iflag = TTYDEF_IFLAG; 180 tp->t_oflag = TTYDEF_OFLAG; 181 tp->t_cflag = TTYDEF_CFLAG; 182 tp->t_lflag = TTYDEF_LFLAG; 183 tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 184 } 185 dcaparam(tp, &tp->t_termios); 186 ttsetwater(tp); 187 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 188 return (EBUSY); 189 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 190 if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 191 tp->t_state |= TS_CARR_ON; 192 (void) spltty(); 193 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 194 (tp->t_state & TS_CARR_ON) == 0) { 195 tp->t_state |= TS_WOPEN; 196 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 197 ttopen, 0)) 198 break; 199 } 200 (void) spl0(); 201 if (error == 0) 202 error = (*linesw[tp->t_line].l_open)(dev, tp); 203 return (error); 204 } 205 206 /*ARGSUSED*/ 207 dcaclose(dev, flag) 208 dev_t dev; 209 { 210 register struct tty *tp; 211 register struct dcadevice *dca; 212 register int unit; 213 214 unit = UNIT(dev); 215 dca = dca_addr[unit]; 216 tp = &dca_tty[unit]; 217 (*linesw[tp->t_line].l_close)(tp); 218 dca->dca_cfcr &= ~CFCR_SBREAK; 219 #ifdef KGDB 220 /* do not disable interrupts if debugging */ 221 if (dev != kgdb_dev) 222 #endif 223 dca->dca_ier = 0; 224 (void) dcamctl(dev, 0, DMSET); 225 if (tp->t_state & TS_HUPCLS) 226 (*linesw[tp->t_line].l_modem)(tp, 0); 227 ttyclose(tp); 228 return(0); 229 } 230 231 dcaread(dev, uio, flag) 232 dev_t dev; 233 struct uio *uio; 234 { 235 register struct tty *tp = &dca_tty[UNIT(dev)]; 236 237 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 238 } 239 240 dcawrite(dev, uio, flag) 241 dev_t dev; 242 struct uio *uio; 243 { 244 int unit = UNIT(dev); 245 register struct tty *tp = &dca_tty[unit]; 246 247 /* 248 * (XXX) We disallow virtual consoles if the physical console is 249 * a serial port. This is in case there is a display attached that 250 * is not the console. In that situation we don't need/want the X 251 * server taking over the console. 252 */ 253 if (constty && unit == dcaconsole) 254 constty = NULL; 255 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 256 } 257 258 dcaintr(unit) 259 register int unit; 260 { 261 register struct dcadevice *dca; 262 register u_char code; 263 register struct tty *tp; 264 265 dca = dca_addr[unit]; 266 if ((dca->dca_ic & IC_IR) == 0) 267 return(0); 268 while (1) { 269 code = dca->dca_iir; 270 #ifdef DEBUG 271 dcaintrcount[code & IIR_IMASK]++; 272 #endif 273 switch (code & IIR_IMASK) { 274 case IIR_NOPEND: 275 return (1); 276 case IIR_RXTOUT: 277 case IIR_RXRDY: 278 /* do time-critical read in-line */ 279 tp = &dca_tty[unit]; 280 /* 281 * Process a received byte. Inline for speed... 282 */ 283 #ifdef KGDB 284 #define RCVBYTE() \ 285 code = dca->dca_data; \ 286 if ((tp->t_state & TS_ISOPEN) == 0) { \ 287 if (kgdb_dev == makedev(dcamajor, unit) && \ 288 code == FRAME_END) \ 289 kgdb_connect(0); /* trap into kgdb */ \ 290 } else \ 291 (*linesw[tp->t_line].l_rint)(code, tp) 292 #else 293 #define RCVBYTE() \ 294 code = dca->dca_data; \ 295 if ((tp->t_state & TS_ISOPEN) != 0) \ 296 (*linesw[tp->t_line].l_rint)(code, tp) 297 #endif 298 RCVBYTE(); 299 if (dca_hasfifo & (1 << unit)) { 300 #ifdef DEBUG 301 register int fifocnt = 1; 302 #endif 303 while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 304 if (code == LSR_RXRDY) { 305 RCVBYTE(); 306 } else 307 dcaeint(unit, code, dca); 308 #ifdef DEBUG 309 fifocnt++; 310 #endif 311 } 312 #ifdef DEBUG 313 if (fifocnt > 16) 314 fifoin[0]++; 315 else 316 fifoin[fifocnt]++; 317 #endif 318 } 319 break; 320 case IIR_TXRDY: 321 tp = &dca_tty[unit]; 322 tp->t_state &=~ (TS_BUSY|TS_FLUSH); 323 if (tp->t_line) 324 (*linesw[tp->t_line].l_start)(tp); 325 else 326 dcastart(tp); 327 break; 328 case IIR_RLS: 329 dcaeint(unit, dca->dca_lsr, dca); 330 break; 331 default: 332 if (code & IIR_NOPEND) 333 return (1); 334 log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 335 unit, code); 336 /* fall through */ 337 case IIR_MLSC: 338 dcamint(unit, dca); 339 break; 340 } 341 } 342 } 343 344 dcaeint(unit, stat, dca) 345 register int unit, stat; 346 register struct dcadevice *dca; 347 { 348 register struct tty *tp; 349 register int c; 350 351 tp = &dca_tty[unit]; 352 c = dca->dca_data; 353 if ((tp->t_state & TS_ISOPEN) == 0) { 354 #ifdef KGDB 355 /* we don't care about parity errors */ 356 if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 357 kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 358 kgdb_connect(0); /* trap into kgdb */ 359 #endif 360 return; 361 } 362 if (stat & (LSR_BI | LSR_FE)) 363 c |= TTY_FE; 364 else if (stat & LSR_PE) 365 c |= TTY_PE; 366 else if (stat & LSR_OE) 367 log(LOG_WARNING, "dca%d: silo overflow\n", unit); 368 (*linesw[tp->t_line].l_rint)(c, tp); 369 } 370 371 dcamint(unit, dca) 372 register int unit; 373 register struct dcadevice *dca; 374 { 375 register struct tty *tp; 376 register int stat; 377 378 tp = &dca_tty[unit]; 379 stat = dca->dca_msr; 380 #ifdef DEBUG 381 dcamintcount[stat & 0xf]++; 382 #endif 383 if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 384 if (stat & MSR_DCD) 385 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 386 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 387 dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 388 } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 389 (tp->t_flags & CRTSCTS)) { 390 /* the line is up and we want to do rts/cts flow control */ 391 if (stat & MSR_CTS) { 392 tp->t_state &=~ TS_TTSTOP; 393 ttstart(tp); 394 } else 395 tp->t_state |= TS_TTSTOP; 396 } 397 } 398 399 dcaioctl(dev, cmd, data, flag) 400 dev_t dev; 401 caddr_t data; 402 { 403 register struct tty *tp; 404 register int unit = UNIT(dev); 405 register struct dcadevice *dca; 406 register int error; 407 408 tp = &dca_tty[unit]; 409 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 410 if (error >= 0) 411 return (error); 412 error = ttioctl(tp, cmd, data, flag); 413 if (error >= 0) 414 return (error); 415 416 dca = dca_addr[unit]; 417 switch (cmd) { 418 419 case TIOCSBRK: 420 dca->dca_cfcr |= CFCR_SBREAK; 421 break; 422 423 case TIOCCBRK: 424 dca->dca_cfcr &= ~CFCR_SBREAK; 425 break; 426 427 case TIOCSDTR: 428 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 429 break; 430 431 case TIOCCDTR: 432 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 433 break; 434 435 case TIOCMSET: 436 (void) dcamctl(dev, *(int *)data, DMSET); 437 break; 438 439 case TIOCMBIS: 440 (void) dcamctl(dev, *(int *)data, DMBIS); 441 break; 442 443 case TIOCMBIC: 444 (void) dcamctl(dev, *(int *)data, DMBIC); 445 break; 446 447 case TIOCMGET: 448 *(int *)data = dcamctl(dev, 0, DMGET); 449 break; 450 451 default: 452 return (ENOTTY); 453 } 454 return (0); 455 } 456 457 dcaparam(tp, t) 458 register struct tty *tp; 459 register struct termios *t; 460 { 461 register struct dcadevice *dca; 462 register int cfcr, cflag = t->c_cflag; 463 int unit = UNIT(tp->t_dev); 464 int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 465 466 /* check requested parameters */ 467 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 468 return(EINVAL); 469 /* and copy to tty */ 470 tp->t_ispeed = t->c_ispeed; 471 tp->t_ospeed = t->c_ospeed; 472 tp->t_cflag = cflag; 473 474 dca = dca_addr[unit]; 475 dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 476 if (ospeed == 0) { 477 (void) dcamctl(unit, 0, DMSET); /* hang up line */ 478 return(0); 479 } 480 dca->dca_cfcr |= CFCR_DLAB; 481 dca->dca_data = ospeed & 0xFF; 482 dca->dca_ier = ospeed >> 8; 483 switch (cflag&CSIZE) { 484 case CS5: 485 cfcr = CFCR_5BITS; break; 486 case CS6: 487 cfcr = CFCR_6BITS; break; 488 case CS7: 489 cfcr = CFCR_7BITS; break; 490 case CS8: 491 cfcr = CFCR_8BITS; break; 492 } 493 if (cflag&PARENB) { 494 cfcr |= CFCR_PENAB; 495 if ((cflag&PARODD) == 0) 496 cfcr |= CFCR_PEVEN; 497 } 498 if (cflag&CSTOPB) 499 cfcr |= CFCR_STOPB; 500 dca->dca_cfcr = cfcr; 501 if (dca_hasfifo & (1 << unit)) 502 dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 503 return(0); 504 } 505 506 dcastart(tp) 507 register struct tty *tp; 508 { 509 register struct dcadevice *dca; 510 int s, unit, c; 511 512 unit = UNIT(tp->t_dev); 513 dca = dca_addr[unit]; 514 s = spltty(); 515 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 516 goto out; 517 if (tp->t_outq.c_cc <= tp->t_lowat) { 518 if (tp->t_state&TS_ASLEEP) { 519 tp->t_state &= ~TS_ASLEEP; 520 wakeup((caddr_t)&tp->t_outq); 521 } 522 if (tp->t_wsel) { 523 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 524 tp->t_wsel = 0; 525 tp->t_state &= ~TS_WCOLL; 526 } 527 } 528 if (tp->t_outq.c_cc == 0) 529 goto out; 530 if (dca->dca_lsr & LSR_TXRDY) { 531 c = getc(&tp->t_outq); 532 tp->t_state |= TS_BUSY; 533 dca->dca_data = c; 534 if (dca_hasfifo & (1 << unit)) { 535 for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 536 dca->dca_data = getc(&tp->t_outq); 537 #ifdef DEBUG 538 if (c > 16) 539 fifoout[0]++; 540 else 541 fifoout[c]++; 542 #endif 543 } 544 } 545 out: 546 splx(s); 547 } 548 549 /* 550 * Stop output on a line. 551 */ 552 /*ARGSUSED*/ 553 dcastop(tp, flag) 554 register struct tty *tp; 555 { 556 register int s; 557 558 s = spltty(); 559 if (tp->t_state & TS_BUSY) { 560 if ((tp->t_state&TS_TTSTOP)==0) 561 tp->t_state |= TS_FLUSH; 562 } 563 splx(s); 564 } 565 566 dcamctl(dev, bits, how) 567 dev_t dev; 568 int bits, how; 569 { 570 register struct dcadevice *dca; 571 register int unit; 572 int s; 573 574 unit = UNIT(dev); 575 dca = dca_addr[unit]; 576 s = spltty(); 577 switch (how) { 578 579 case DMSET: 580 dca->dca_mcr = bits; 581 break; 582 583 case DMBIS: 584 dca->dca_mcr |= bits; 585 break; 586 587 case DMBIC: 588 dca->dca_mcr &= ~bits; 589 break; 590 591 case DMGET: 592 bits = dca->dca_msr; 593 break; 594 } 595 (void) splx(s); 596 return(bits); 597 } 598 599 /* 600 * Following are all routines needed for DCA to act as console 601 */ 602 #include "../hp300/cons.h" 603 604 dcacnprobe(cp) 605 struct consdev *cp; 606 { 607 int unit; 608 609 /* locate the major number */ 610 for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 611 if (cdevsw[dcamajor].d_open == dcaopen) 612 break; 613 614 /* XXX: ick */ 615 unit = CONUNIT; 616 dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 617 618 /* make sure hardware exists */ 619 if (badaddr((short *)dca_addr[unit])) { 620 cp->cn_pri = CN_DEAD; 621 return; 622 } 623 624 /* initialize required fields */ 625 cp->cn_dev = makedev(dcamajor, unit); 626 cp->cn_tp = &dca_tty[unit]; 627 switch (dca_addr[unit]->dca_irid) { 628 case DCAID0: 629 case DCAID1: 630 cp->cn_pri = CN_NORMAL; 631 break; 632 case DCAREMID0: 633 case DCAREMID1: 634 cp->cn_pri = CN_REMOTE; 635 break; 636 default: 637 cp->cn_pri = CN_DEAD; 638 break; 639 } 640 /* 641 * If dcaconsole is initialized, raise our priority. 642 */ 643 if (dcaconsole == unit) 644 cp->cn_pri = CN_REMOTE; 645 #ifdef KGDB 646 if (major(kgdb_dev) == 1) /* XXX */ 647 kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 648 #endif 649 } 650 651 dcacninit(cp) 652 struct consdev *cp; 653 { 654 int unit = UNIT(cp->cn_dev); 655 656 dcainit(unit, dcadefaultrate); 657 dcaconsole = unit; 658 dcaconsinit = 1; 659 } 660 661 dcainit(unit, rate) 662 int unit, rate; 663 { 664 register struct dcadevice *dca; 665 int s; 666 short stat; 667 668 #ifdef lint 669 stat = unit; if (stat) return; 670 #endif 671 dca = dca_addr[unit]; 672 s = splhigh(); 673 dca->dca_irid = 0xFF; 674 DELAY(100); 675 dca->dca_ic = IC_IE; 676 dca->dca_cfcr = CFCR_DLAB; 677 rate = ttspeedtab(rate, dcaspeedtab); 678 dca->dca_data = rate & 0xFF; 679 dca->dca_ier = rate >> 8; 680 dca->dca_cfcr = CFCR_8BITS; 681 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 682 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 683 stat = dca->dca_iir; 684 splx(s); 685 } 686 687 dcacngetc(dev) 688 { 689 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 690 short stat; 691 int c, s; 692 693 #ifdef lint 694 stat = dev; if (stat) return(0); 695 #endif 696 s = splhigh(); 697 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 698 ; 699 c = dca->dca_data; 700 stat = dca->dca_iir; 701 splx(s); 702 return(c); 703 } 704 705 /* 706 * Console kernel output character routine. 707 */ 708 dcacnputc(dev, c) 709 dev_t dev; 710 register int c; 711 { 712 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 713 register int timo; 714 short stat; 715 int s = splhigh(); 716 717 #ifdef lint 718 stat = dev; if (stat) return; 719 #endif 720 #ifdef KGDB 721 if (dev != kgdb_dev) 722 #endif 723 if (dcaconsinit == 0) { 724 (void) dcainit(UNIT(dev), dcadefaultrate); 725 dcaconsinit = 1; 726 } 727 /* wait for any pending transmission to finish */ 728 timo = 50000; 729 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 730 ; 731 dca->dca_data = c; 732 /* wait for this transmission to complete */ 733 timo = 1500000; 734 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 735 ; 736 /* clear any interrupts generated by this transmission */ 737 stat = dca->dca_iir; 738 splx(s); 739 } 740 #endif 741