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.15 (Berkeley) 02/15/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/proc.h" 20 #include "sys/tty.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 selwakeup(&tp->t_wsel); 531 } 532 if (tp->t_outq.c_cc == 0) 533 goto out; 534 if (dca->dca_lsr & LSR_TXRDY) { 535 c = getc(&tp->t_outq); 536 tp->t_state |= TS_BUSY; 537 dca->dca_data = c; 538 if (dca_hasfifo & (1 << unit)) { 539 for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 540 dca->dca_data = getc(&tp->t_outq); 541 #ifdef DEBUG 542 if (c > 16) 543 fifoout[0]++; 544 else 545 fifoout[c]++; 546 #endif 547 } 548 } 549 out: 550 splx(s); 551 } 552 553 /* 554 * Stop output on a line. 555 */ 556 /*ARGSUSED*/ 557 dcastop(tp, flag) 558 register struct tty *tp; 559 { 560 register int s; 561 562 s = spltty(); 563 if (tp->t_state & TS_BUSY) { 564 if ((tp->t_state&TS_TTSTOP)==0) 565 tp->t_state |= TS_FLUSH; 566 } 567 splx(s); 568 } 569 570 dcamctl(dev, bits, how) 571 dev_t dev; 572 int bits, how; 573 { 574 register struct dcadevice *dca; 575 register int unit; 576 int s; 577 578 unit = UNIT(dev); 579 dca = dca_addr[unit]; 580 s = spltty(); 581 switch (how) { 582 583 case DMSET: 584 dca->dca_mcr = bits; 585 break; 586 587 case DMBIS: 588 dca->dca_mcr |= bits; 589 break; 590 591 case DMBIC: 592 dca->dca_mcr &= ~bits; 593 break; 594 595 case DMGET: 596 bits = dca->dca_msr; 597 break; 598 } 599 (void) splx(s); 600 return (bits); 601 } 602 603 /* 604 * Following are all routines needed for DCA to act as console 605 */ 606 #include "../hp300/cons.h" 607 608 dcacnprobe(cp) 609 struct consdev *cp; 610 { 611 int unit; 612 613 /* locate the major number */ 614 for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 615 if (cdevsw[dcamajor].d_open == dcaopen) 616 break; 617 618 /* XXX: ick */ 619 unit = CONUNIT; 620 dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 621 622 /* make sure hardware exists */ 623 if (badaddr((short *)dca_addr[unit])) { 624 cp->cn_pri = CN_DEAD; 625 return; 626 } 627 628 /* initialize required fields */ 629 cp->cn_dev = makedev(dcamajor, unit); 630 cp->cn_tp = &dca_tty[unit]; 631 switch (dca_addr[unit]->dca_irid) { 632 case DCAID0: 633 case DCAID1: 634 cp->cn_pri = CN_NORMAL; 635 break; 636 case DCAREMID0: 637 case DCAREMID1: 638 cp->cn_pri = CN_REMOTE; 639 break; 640 default: 641 cp->cn_pri = CN_DEAD; 642 break; 643 } 644 /* 645 * If dcaconsole is initialized, raise our priority. 646 */ 647 if (dcaconsole == unit) 648 cp->cn_pri = CN_REMOTE; 649 #ifdef KGDB 650 if (major(kgdb_dev) == 1) /* XXX */ 651 kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 652 #endif 653 } 654 655 dcacninit(cp) 656 struct consdev *cp; 657 { 658 int unit = UNIT(cp->cn_dev); 659 660 dcainit(unit, dcadefaultrate); 661 dcaconsole = unit; 662 dcaconsinit = 1; 663 } 664 665 dcainit(unit, rate) 666 int unit, rate; 667 { 668 register struct dcadevice *dca; 669 int s; 670 short stat; 671 672 #ifdef lint 673 stat = unit; if (stat) return; 674 #endif 675 dca = dca_addr[unit]; 676 s = splhigh(); 677 dca->dca_irid = 0xFF; 678 DELAY(100); 679 dca->dca_ic = IC_IE; 680 dca->dca_cfcr = CFCR_DLAB; 681 rate = ttspeedtab(rate, dcaspeedtab); 682 dca->dca_data = rate & 0xFF; 683 dca->dca_ier = rate >> 8; 684 dca->dca_cfcr = CFCR_8BITS; 685 dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 686 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 687 stat = dca->dca_iir; 688 splx(s); 689 } 690 691 dcacngetc(dev) 692 { 693 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 694 short stat; 695 int c, s; 696 697 #ifdef lint 698 stat = dev; if (stat) return (0); 699 #endif 700 s = splhigh(); 701 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 702 ; 703 c = dca->dca_data; 704 stat = dca->dca_iir; 705 splx(s); 706 return (c); 707 } 708 709 /* 710 * Console kernel output character routine. 711 */ 712 dcacnputc(dev, c) 713 dev_t dev; 714 register int c; 715 { 716 register struct dcadevice *dca = dca_addr[UNIT(dev)]; 717 register int timo; 718 short stat; 719 int s = splhigh(); 720 721 #ifdef lint 722 stat = dev; if (stat) return; 723 #endif 724 if (dcaconsinit == 0) { 725 (void) dcainit(UNIT(dev), dcadefaultrate); 726 dcaconsinit = 1; 727 } 728 /* wait for any pending transmission to finish */ 729 timo = 50000; 730 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 731 ; 732 dca->dca_data = c; 733 /* wait for this transmission to complete */ 734 timo = 1500000; 735 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 736 ; 737 /* clear any interrupts generated by this transmission */ 738 stat = dca->dca_iir; 739 splx(s); 740 } 741 #endif 742