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.3 (Berkeley) 01/09/95 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 int flag; 276 { 277 int unit = UNIT(dev); 278 register struct tty *tp = &dca_tty[unit]; 279 int error, of; 280 281 of = dcaoflows[unit]; 282 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 283 /* 284 * XXX hardly a reasonable thing to do, but reporting overflows 285 * at interrupt time just exacerbates the problem. 286 */ 287 if (dcaoflows[unit] != of) 288 log(LOG_WARNING, "dca%d: silo overflow\n", unit); 289 return (error); 290 } 291 292 dcawrite(dev, uio, flag) 293 dev_t dev; 294 struct uio *uio; 295 int flag; 296 { 297 int unit = UNIT(dev); 298 register struct tty *tp = &dca_tty[unit]; 299 extern struct tty *constty; 300 301 /* 302 * (XXX) We disallow virtual consoles if the physical console is 303 * a serial port. This is in case there is a display attached that 304 * is not the console. In that situation we don't need/want the X 305 * server taking over the console. 306 */ 307 if (constty && unit == dcaconsole) 308 constty = NULL; 309 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 310 } 311 312 dcaintr(unit) 313 register int unit; 314 { 315 register struct dcadevice *dca; 316 register u_char code; 317 register struct tty *tp; 318 int iflowdone = 0; 319 320 dca = dca_addr[unit]; 321 #ifdef hp300 322 if ((dca->dca_ic & (IC_IR|IC_IE)) != (IC_IR|IC_IE)) 323 return (0); 324 #endif 325 tp = &dca_tty[unit]; 326 while (1) { 327 code = dca->dca_iir; 328 #ifdef DEBUG 329 dcaintrcount[code & IIR_IMASK]++; 330 #endif 331 switch (code & IIR_IMASK) { 332 case IIR_NOPEND: 333 return (1); 334 case IIR_RXTOUT: 335 case IIR_RXRDY: 336 /* do time-critical read in-line */ 337 /* 338 * Process a received byte. Inline for speed... 339 */ 340 #ifdef KGDB 341 #define RCVBYTE() \ 342 code = dca->dca_data; \ 343 if ((tp->t_state & TS_ISOPEN) == 0) { \ 344 if (code == FRAME_END && \ 345 kgdb_dev == makedev(dcamajor, unit)) \ 346 kgdb_connect(0); /* trap into kgdb */ \ 347 } else \ 348 (*linesw[tp->t_line].l_rint)(code, tp) 349 #else 350 #define RCVBYTE() \ 351 code = dca->dca_data; \ 352 if ((tp->t_state & TS_ISOPEN) != 0) \ 353 (*linesw[tp->t_line].l_rint)(code, tp) 354 #endif 355 RCVBYTE(); 356 if (dca_hasfifo & (1 << unit)) { 357 #ifdef DEBUG 358 register int fifocnt = 1; 359 #endif 360 while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 361 if (code == LSR_RXRDY) { 362 RCVBYTE(); 363 } else 364 dcaeint(unit, code, dca); 365 #ifdef DEBUG 366 fifocnt++; 367 #endif 368 } 369 #ifdef DEBUG 370 if (fifocnt > 16) 371 fifoin[0]++; 372 else 373 fifoin[fifocnt]++; 374 #endif 375 } 376 if (!iflowdone && (tp->t_cflag&CRTS_IFLOW) && 377 tp->t_rawq.c_cc > TTYHOG/2) { 378 dca->dca_mcr &= ~MCR_RTS; 379 iflowdone = 1; 380 } 381 break; 382 case IIR_TXRDY: 383 tp->t_state &=~ (TS_BUSY|TS_FLUSH); 384 if (tp->t_line) 385 (*linesw[tp->t_line].l_start)(tp); 386 else 387 dcastart(tp); 388 break; 389 case IIR_RLS: 390 dcaeint(unit, dca->dca_lsr, dca); 391 break; 392 default: 393 if (code & IIR_NOPEND) 394 return (1); 395 log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 396 unit, code); 397 /* fall through */ 398 case IIR_MLSC: 399 dcamint(unit, dca); 400 break; 401 } 402 } 403 } 404 405 dcaeint(unit, stat, dca) 406 register int unit, stat; 407 register struct dcadevice *dca; 408 { 409 register struct tty *tp; 410 register int c; 411 412 tp = &dca_tty[unit]; 413 c = dca->dca_data; 414 if ((tp->t_state & TS_ISOPEN) == 0) { 415 #ifdef KGDB 416 /* we don't care about parity errors */ 417 if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 418 kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 419 kgdb_connect(0); /* trap into kgdb */ 420 #endif 421 return; 422 } 423 if (stat & (LSR_BI | LSR_FE)) 424 c |= TTY_FE; 425 else if (stat & LSR_PE) 426 c |= TTY_PE; 427 else if (stat & LSR_OE) 428 dcaoflows[unit]++; 429 (*linesw[tp->t_line].l_rint)(c, tp); 430 } 431 432 dcamint(unit, dca) 433 register int unit; 434 register struct dcadevice *dca; 435 { 436 register struct tty *tp; 437 register u_char stat; 438 439 tp = &dca_tty[unit]; 440 stat = dca->dca_msr; 441 #ifdef DEBUG 442 dcamintcount[stat & 0xf]++; 443 #endif 444 if ((stat & MSR_DDCD) && 445 (dcasoftCAR & (1 << unit)) == 0) { 446 if (stat & MSR_DCD) 447 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 448 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 449 dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 450 } 451 /* 452 * CTS change. 453 * If doing HW output flow control start/stop output as appropriate. 454 */ 455 if ((stat & MSR_DCTS) && 456 (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) { 457 if (stat & MSR_CTS) { 458 tp->t_state &=~ TS_TTSTOP; 459 dcastart(tp); 460 } else { 461 tp->t_state |= TS_TTSTOP; 462 } 463 } 464 } 465 466 dcaioctl(dev, cmd, data, flag, p) 467 dev_t dev; 468 u_long cmd; 469 caddr_t data; 470 int flag; 471 struct proc *p; 472 { 473 register struct tty *tp; 474 register int unit = UNIT(dev); 475 register struct dcadevice *dca; 476 register int error; 477 478 tp = &dca_tty[unit]; 479 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 480 if (error >= 0) 481 return (error); 482 error = ttioctl(tp, cmd, data, flag); 483 if (error >= 0) 484 return (error); 485 486 dca = dca_addr[unit]; 487 switch (cmd) { 488 489 case TIOCSBRK: 490 dca->dca_cfcr |= CFCR_SBREAK; 491 break; 492 493 case TIOCCBRK: 494 dca->dca_cfcr &= ~CFCR_SBREAK; 495 break; 496 497 case TIOCSDTR: 498 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 499 break; 500 501 case TIOCCDTR: 502 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 503 break; 504 505 case TIOCMSET: 506 (void) dcamctl(dev, *(int *)data, DMSET); 507 break; 508 509 case TIOCMBIS: 510 (void) dcamctl(dev, *(int *)data, DMBIS); 511 break; 512 513 case TIOCMBIC: 514 (void) dcamctl(dev, *(int *)data, DMBIC); 515 break; 516 517 case TIOCMGET: 518 *(int *)data = dcamctl(dev, 0, DMGET); 519 break; 520 521 default: 522 return (ENOTTY); 523 } 524 return (0); 525 } 526 527 dcaparam(tp, t) 528 register struct tty *tp; 529 register struct termios *t; 530 { 531 register struct dcadevice *dca; 532 register int cfcr, cflag = t->c_cflag; 533 int unit = UNIT(tp->t_dev); 534 int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 535 536 /* check requested parameters */ 537 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 538 return (EINVAL); 539 /* and copy to tty */ 540 tp->t_ispeed = t->c_ispeed; 541 tp->t_ospeed = t->c_ospeed; 542 tp->t_cflag = cflag; 543 544 dca = dca_addr[unit]; 545 dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 546 #ifdef hp700 547 dca->dca_mcr |= MCR_IEN; 548 #endif 549 if (ospeed == 0) { 550 (void) dcamctl(unit, 0, DMSET); /* hang up line */ 551 return (0); 552 } 553 dca->dca_cfcr |= CFCR_DLAB; 554 dca->dca_data = ospeed & 0xFF; 555 dca->dca_ier = ospeed >> 8; 556 switch (cflag&CSIZE) { 557 case CS5: 558 cfcr = CFCR_5BITS; break; 559 case CS6: 560 cfcr = CFCR_6BITS; break; 561 case CS7: 562 cfcr = CFCR_7BITS; break; 563 case CS8: 564 cfcr = CFCR_8BITS; break; 565 } 566 if (cflag&PARENB) { 567 cfcr |= CFCR_PENAB; 568 if ((cflag&PARODD) == 0) 569 cfcr |= CFCR_PEVEN; 570 } 571 if (cflag&CSTOPB) 572 cfcr |= CFCR_STOPB; 573 dca->dca_cfcr = cfcr; 574 if (dca_hasfifo & (1 << unit)) 575 dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 576 return (0); 577 } 578 579 void 580 dcastart(tp) 581 register struct tty *tp; 582 { 583 register struct dcadevice *dca; 584 int s, unit, c; 585 586 unit = UNIT(tp->t_dev); 587 dca = dca_addr[unit]; 588 s = spltty(); 589 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 590 goto out; 591 if (tp->t_outq.c_cc <= tp->t_lowat) { 592 if (tp->t_state&TS_ASLEEP) { 593 tp->t_state &= ~TS_ASLEEP; 594 wakeup((caddr_t)&tp->t_outq); 595 } 596 selwakeup(&tp->t_wsel); 597 } 598 if (tp->t_outq.c_cc == 0) 599 goto out; 600 if (dca->dca_lsr & LSR_TXRDY) { 601 c = getc(&tp->t_outq); 602 tp->t_state |= TS_BUSY; 603 dca->dca_data = c; 604 if (dca_hasfifo & (1 << unit)) { 605 for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 606 dca->dca_data = getc(&tp->t_outq); 607 #ifdef DEBUG 608 if (c > 16) 609 fifoout[0]++; 610 else 611 fifoout[c]++; 612 #endif 613 } 614 } 615 out: 616 splx(s); 617 } 618 619 /* 620 * Stop output on a line. 621 */ 622 /*ARGSUSED*/ 623 dcastop(tp, flag) 624 register struct tty *tp; 625 int flag; 626 { 627 register int s; 628 629 s = spltty(); 630 if (tp->t_state & TS_BUSY) { 631 if ((tp->t_state&TS_TTSTOP)==0) 632 tp->t_state |= TS_FLUSH; 633 } 634 splx(s); 635 } 636 637 dcamctl(dev, bits, how) 638 dev_t dev; 639 int bits, how; 640 { 641 register struct dcadevice *dca; 642 register int unit; 643 int s; 644 645 unit = UNIT(dev); 646 dca = dca_addr[unit]; 647 #ifdef hp700 648 /* 649 * Always make sure MCR_IEN is set (unless setting to 0) 650 */ 651 #ifdef KGDB 652 if (how == DMSET && kgdb_dev == makedev(dcamajor, unit)) 653 bits |= MCR_IEN; 654 else 655 #endif 656 if (how == DMBIS || (how == DMSET && bits)) 657 bits |= MCR_IEN; 658 else if (how == DMBIC) 659 bits &= ~MCR_IEN; 660 #endif 661 s = spltty(); 662 switch (how) { 663 664 case DMSET: 665 dca->dca_mcr = bits; 666 break; 667 668 case DMBIS: 669 dca->dca_mcr |= bits; 670 break; 671 672 case DMBIC: 673 dca->dca_mcr &= ~bits; 674 break; 675 676 case DMGET: 677 bits = dca->dca_msr; 678 break; 679 } 680 (void) splx(s); 681 return (bits); 682 } 683 684 /* 685 * Following are all routines needed for DCA to act as console 686 */ 687 #include <hp/dev/cons.h> 688 689 dcacnprobe(cp) 690 struct consdev *cp; 691 { 692 int unit; 693 694 /* locate the major number */ 695 for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 696 if (cdevsw[dcamajor].d_open == dcaopen) 697 break; 698 699 /* XXX: ick */ 700 unit = CONUNIT; 701 #ifdef hp300 702 dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 703 704 /* make sure hardware exists */ 705 if (badaddr((short *)dca_addr[unit])) { 706 cp->cn_pri = CN_DEAD; 707 return; 708 } 709 #endif 710 #ifdef hp700 711 dca_addr[CONUNIT] = CONPORT; 712 #endif 713 714 /* initialize required fields */ 715 cp->cn_dev = makedev(dcamajor, unit); 716 cp->cn_tp = &dca_tty[unit]; 717 #ifdef hp300 718 switch (dca_addr[unit]->dca_id) { 719 case DCAID0: 720 case DCAID1: 721 cp->cn_pri = CN_NORMAL; 722 break; 723 case DCAREMID0: 724 case DCAREMID1: 725 cp->cn_pri = CN_REMOTE; 726 break; 727 default: 728 cp->cn_pri = CN_DEAD; 729 break; 730 } 731 #endif 732 #ifdef hp700 733 cp->cn_pri = CN_NORMAL; 734 #endif 735 /* 736 * If dcaconsole is initialized, raise our priority. 737 */ 738 if (dcaconsole == unit) 739 cp->cn_pri = CN_REMOTE; 740 #ifdef KGDB 741 if (major(kgdb_dev) == 1) /* XXX */ 742 kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 743 #endif 744 } 745 746 dcacninit(cp) 747 struct consdev *cp; 748 { 749 int unit = UNIT(cp->cn_dev); 750 751 dcainit(unit, dcadefaultrate); 752 dcaconsole = unit; 753 dcaconsinit = 1; 754 } 755 756 dcainit(unit, rate) 757 int unit, rate; 758 { 759 register struct dcadevice *dca; 760 int s; 761 short stat; 762 763 #ifdef lint 764 stat = unit; if (stat) return; 765 #endif 766 dca = dca_addr[unit]; 767 s = splhigh(); 768 #ifdef hp300 769 dca->dca_reset = 0xFF; 770 DELAY(100); 771 dca->dca_ic = IC_IE; 772 #endif 773 dca->dca_cfcr = CFCR_DLAB; 774 rate = ttspeedtab(rate, dcaspeedtab); 775 dca->dca_data = rate & 0xFF; 776 dca->dca_ier = rate >> 8; 777 dca->dca_cfcr = CFCR_8BITS; 778 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 779 #ifdef hp700 780 dca->dca_mcr |= MCR_IEN; 781 #endif 782 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 783 DELAY(100); 784 stat = dca->dca_iir; 785 splx(s); 786 } 787 788 dcacngetc(dev) 789 dev_t dev; 790 { 791 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 792 register u_char stat; 793 int c, s; 794 795 #ifdef lint 796 stat = dev; if (stat) return (0); 797 #endif 798 s = splhigh(); 799 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 800 ; 801 c = dca->dca_data; 802 stat = dca->dca_iir; 803 splx(s); 804 return (c); 805 } 806 807 /* 808 * Console kernel output character routine. 809 */ 810 dcacnputc(dev, c) 811 dev_t dev; 812 register int c; 813 { 814 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 815 register int timo; 816 register u_char stat; 817 int s = splhigh(); 818 819 #ifdef lint 820 stat = dev; if (stat) return; 821 #endif 822 if (dcaconsinit == 0) { 823 (void) dcainit(UNIT(dev), dcadefaultrate); 824 dcaconsinit = 1; 825 } 826 /* wait for any pending transmission to finish */ 827 timo = 50000; 828 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 829 ; 830 dca->dca_data = c; 831 /* wait for this transmission to complete */ 832 timo = 1500000; 833 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 834 ; 835 /* 836 * If the "normal" interface was busy transfering a character 837 * we must let our interrupt through to keep things moving. 838 * Otherwise, we clear the interrupt that we have caused. 839 */ 840 if ((dca_tty[UNIT(dev)].t_state & TS_BUSY) == 0) 841 stat = dca->dca_iir; 842 splx(s); 843 } 844 #endif 845