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