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.14 (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, p) 404 dev_t dev; 405 int cmd; 406 caddr_t data; 407 int flag; 408 struct proc *p; 409 { 410 register struct tty *tp; 411 register int unit = UNIT(dev); 412 register struct dcadevice *dca; 413 register int error; 414 415 tp = &dca_tty[unit]; 416 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 417 if (error >= 0) 418 return (error); 419 error = ttioctl(tp, cmd, data, flag); 420 if (error >= 0) 421 return (error); 422 423 dca = dca_addr[unit]; 424 switch (cmd) { 425 426 case TIOCSBRK: 427 dca->dca_cfcr |= CFCR_SBREAK; 428 break; 429 430 case TIOCCBRK: 431 dca->dca_cfcr &= ~CFCR_SBREAK; 432 break; 433 434 case TIOCSDTR: 435 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 436 break; 437 438 case TIOCCDTR: 439 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 440 break; 441 442 case TIOCMSET: 443 (void) dcamctl(dev, *(int *)data, DMSET); 444 break; 445 446 case TIOCMBIS: 447 (void) dcamctl(dev, *(int *)data, DMBIS); 448 break; 449 450 case TIOCMBIC: 451 (void) dcamctl(dev, *(int *)data, DMBIC); 452 break; 453 454 case TIOCMGET: 455 *(int *)data = dcamctl(dev, 0, DMGET); 456 break; 457 458 default: 459 return (ENOTTY); 460 } 461 return (0); 462 } 463 464 dcaparam(tp, t) 465 register struct tty *tp; 466 register struct termios *t; 467 { 468 register struct dcadevice *dca; 469 register int cfcr, cflag = t->c_cflag; 470 int unit = UNIT(tp->t_dev); 471 int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 472 473 /* check requested parameters */ 474 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 475 return (EINVAL); 476 /* and copy to tty */ 477 tp->t_ispeed = t->c_ispeed; 478 tp->t_ospeed = t->c_ospeed; 479 tp->t_cflag = cflag; 480 481 dca = dca_addr[unit]; 482 dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 483 if (ospeed == 0) { 484 (void) dcamctl(unit, 0, DMSET); /* hang up line */ 485 return (0); 486 } 487 dca->dca_cfcr |= CFCR_DLAB; 488 dca->dca_data = ospeed & 0xFF; 489 dca->dca_ier = ospeed >> 8; 490 switch (cflag&CSIZE) { 491 case CS5: 492 cfcr = CFCR_5BITS; break; 493 case CS6: 494 cfcr = CFCR_6BITS; break; 495 case CS7: 496 cfcr = CFCR_7BITS; break; 497 case CS8: 498 cfcr = CFCR_8BITS; break; 499 } 500 if (cflag&PARENB) { 501 cfcr |= CFCR_PENAB; 502 if ((cflag&PARODD) == 0) 503 cfcr |= CFCR_PEVEN; 504 } 505 if (cflag&CSTOPB) 506 cfcr |= CFCR_STOPB; 507 dca->dca_cfcr = cfcr; 508 if (dca_hasfifo & (1 << unit)) 509 dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 510 return (0); 511 } 512 513 void 514 dcastart(tp) 515 register struct tty *tp; 516 { 517 register struct dcadevice *dca; 518 int s, unit, c; 519 520 unit = UNIT(tp->t_dev); 521 dca = dca_addr[unit]; 522 s = spltty(); 523 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 524 goto out; 525 if (tp->t_outq.c_cc <= tp->t_lowat) { 526 if (tp->t_state&TS_ASLEEP) { 527 tp->t_state &= ~TS_ASLEEP; 528 wakeup((caddr_t)&tp->t_outq); 529 } 530 if (tp->t_wsel) { 531 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 532 tp->t_wsel = 0; 533 tp->t_state &= ~TS_WCOLL; 534 } 535 } 536 if (tp->t_outq.c_cc == 0) 537 goto out; 538 if (dca->dca_lsr & LSR_TXRDY) { 539 c = getc(&tp->t_outq); 540 tp->t_state |= TS_BUSY; 541 dca->dca_data = c; 542 if (dca_hasfifo & (1 << unit)) { 543 for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 544 dca->dca_data = getc(&tp->t_outq); 545 #ifdef DEBUG 546 if (c > 16) 547 fifoout[0]++; 548 else 549 fifoout[c]++; 550 #endif 551 } 552 } 553 out: 554 splx(s); 555 } 556 557 /* 558 * Stop output on a line. 559 */ 560 /*ARGSUSED*/ 561 dcastop(tp, flag) 562 register struct tty *tp; 563 { 564 register int s; 565 566 s = spltty(); 567 if (tp->t_state & TS_BUSY) { 568 if ((tp->t_state&TS_TTSTOP)==0) 569 tp->t_state |= TS_FLUSH; 570 } 571 splx(s); 572 } 573 574 dcamctl(dev, bits, how) 575 dev_t dev; 576 int bits, how; 577 { 578 register struct dcadevice *dca; 579 register int unit; 580 int s; 581 582 unit = UNIT(dev); 583 dca = dca_addr[unit]; 584 s = spltty(); 585 switch (how) { 586 587 case DMSET: 588 dca->dca_mcr = bits; 589 break; 590 591 case DMBIS: 592 dca->dca_mcr |= bits; 593 break; 594 595 case DMBIC: 596 dca->dca_mcr &= ~bits; 597 break; 598 599 case DMGET: 600 bits = dca->dca_msr; 601 break; 602 } 603 (void) splx(s); 604 return (bits); 605 } 606 607 /* 608 * Following are all routines needed for DCA to act as console 609 */ 610 #include "../hp300/cons.h" 611 612 dcacnprobe(cp) 613 struct consdev *cp; 614 { 615 int unit; 616 617 /* locate the major number */ 618 for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 619 if (cdevsw[dcamajor].d_open == dcaopen) 620 break; 621 622 /* XXX: ick */ 623 unit = CONUNIT; 624 dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 625 626 /* make sure hardware exists */ 627 if (badaddr((short *)dca_addr[unit])) { 628 cp->cn_pri = CN_DEAD; 629 return; 630 } 631 632 /* initialize required fields */ 633 cp->cn_dev = makedev(dcamajor, unit); 634 cp->cn_tp = &dca_tty[unit]; 635 switch (dca_addr[unit]->dca_irid) { 636 case DCAID0: 637 case DCAID1: 638 cp->cn_pri = CN_NORMAL; 639 break; 640 case DCAREMID0: 641 case DCAREMID1: 642 cp->cn_pri = CN_REMOTE; 643 break; 644 default: 645 cp->cn_pri = CN_DEAD; 646 break; 647 } 648 /* 649 * If dcaconsole is initialized, raise our priority. 650 */ 651 if (dcaconsole == unit) 652 cp->cn_pri = CN_REMOTE; 653 #ifdef KGDB 654 if (major(kgdb_dev) == 1) /* XXX */ 655 kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 656 #endif 657 } 658 659 dcacninit(cp) 660 struct consdev *cp; 661 { 662 int unit = UNIT(cp->cn_dev); 663 664 dcainit(unit, dcadefaultrate); 665 dcaconsole = unit; 666 dcaconsinit = 1; 667 } 668 669 dcainit(unit, rate) 670 int unit, rate; 671 { 672 register struct dcadevice *dca; 673 int s; 674 short stat; 675 676 #ifdef lint 677 stat = unit; if (stat) return; 678 #endif 679 dca = dca_addr[unit]; 680 s = splhigh(); 681 dca->dca_irid = 0xFF; 682 DELAY(100); 683 dca->dca_ic = IC_IE; 684 dca->dca_cfcr = CFCR_DLAB; 685 rate = ttspeedtab(rate, dcaspeedtab); 686 dca->dca_data = rate & 0xFF; 687 dca->dca_ier = rate >> 8; 688 dca->dca_cfcr = CFCR_8BITS; 689 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 690 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 691 stat = dca->dca_iir; 692 splx(s); 693 } 694 695 dcacngetc(dev) 696 { 697 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 698 short stat; 699 int c, s; 700 701 #ifdef lint 702 stat = dev; if (stat) return (0); 703 #endif 704 s = splhigh(); 705 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 706 ; 707 c = dca->dca_data; 708 stat = dca->dca_iir; 709 splx(s); 710 return (c); 711 } 712 713 /* 714 * Console kernel output character routine. 715 */ 716 dcacnputc(dev, c) 717 dev_t dev; 718 register int c; 719 { 720 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 721 register int timo; 722 short stat; 723 int s = splhigh(); 724 725 #ifdef lint 726 stat = dev; if (stat) return; 727 #endif 728 if (dcaconsinit == 0) { 729 (void) dcainit(UNIT(dev), dcadefaultrate); 730 dcaconsinit = 1; 731 } 732 /* wait for any pending transmission to finish */ 733 timo = 50000; 734 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 735 ; 736 dca->dca_data = c; 737 /* wait for this transmission to complete */ 738 timo = 1500000; 739 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 740 ; 741 /* clear any interrupts generated by this transmission */ 742 stat = dca->dca_iir; 743 splx(s); 744 } 745 #endif 746