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