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