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