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